2

我已经查看了几篇分别做这些事情的帖子,但还没有成功地将它们组合在一起。

我有一个类似于这个结构的输入:

 <Response>
    <Confirmation>Success</Confirmation>
    <SecondResponse>
       <InquiryResponse>
          <ID>99999</ID>
          <Confirmation>Success</Confirmation>
          <Exception/>
          <!-- The following structure repeats a varying amount of times -->
          <DataNode1>
             <!-- Child nodes could be null, transform should remove null nodes -->
             <Child1>data</Child1>
             ...
             <Childn>dataN</Childn>
          </DataNode1>
          ...
          <DataNodeN>
             <Child1>data</Child1>
             ...
             <Childn>dataN</Childn>
          </DataNodeN>
       </InquiryResponse>
    </SecondResponse>
 </Response>

现在,我需要完成以下事情:

1)复制<InquiryResponse>(但不是<InquiryResponse>自身)的所有子节点

2)排除<Confirmation><Exception>节点

3) 排除 DataNode 中的任何 null 子节点

4)在DataNode中插入一个新的子元素

所以所需的输出如下所示:

 <ID>99999</ID>
 <DataNode1>
   <Child1>data</Child1>
   <ChiildInsert>newData</ChildInsert>
   <Childn>dataN</Childn>
 </DataNode1>
 ...
 <DataNodeN>
    <Child1>data</Child1>
    <ChildInsert>newData</ChildInsert>
    <Childn>dataN</Childn>
 </DataNodeN>

我相信我必须通过为每个 DataNode 创建一个模板(我知道所有可能出现的值)和模板来删除我不想要的节点,然后将它们全部应用于忽略 null 的主副本模板节点。这是我目前使用 2.0 的 XSLT 化身 - 虽然我知道它并不完全完整,但据我所知:

 <xsl:stylesheet version="2.0" xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"   
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

  <!-- Remove Unwanted Nodes -->
  <xsl:template match='Confirmation|Exception'/>

  <!-- DataNode Template -->
  <template match='DataNode1'>
    <xsl:copy>
       <xsl:apply-templates select="@*|node()"/>
       <ChildInsert>
          <xsl:value-of select='newData'/>
       </ChildInsert>
    </xsl:copy>
  </xsl:template>

  <!-- Identity Transform -->
  <xsl:template match='@*|node()'> 
    <xsl:if test='. != ""'>
       <xsl:copy>
         <xsl:apply-templates select='@*|node()'/>
       </xsl:copy>
    </xsl:if>
  </xsl:template>

  </xsl:stylesheet>

这是我使用 Saxon-PE 9.3.0.5 生成的输出

 <Response>
   <SecondResponse>
     <InquiryResponse>
         <ID>99999</ID>
         <DataNode1>
            <Child1>data</Child1>
            <ChiildInsert>newData</ChildInsert>
            <Childn>dataN</Childn>
         </DataNode1>
         ....
         <DataNodeN>...</DataNodeN>
     </InquiryResponse>
   </SecondResponse>
 </Response>

显然,我仍然得到了父母的所有回应,因为我没有指定处理它们的方法;但是,每当我尝试将模板与 XPath 匹配时,我得到的是数据,而不是 XML。我知道我可以通过另一个只复制 的子节点的转换来传递它<InquiryResponse>,但我觉得应该有更优雅的方式来代替它。以下是我仍然面临的问题/疑问。

1)由于使用这样的模板:<xsl:template match='Response'/>将使我的整个响应无效,我尝试切换识别模板以匹配Response/SecondResponse/InquiryResponse/*但结果只产生文本数据,而不是 XML。

2)当<Exception>节点填充了一个值时,它会继续被复制而不是像<Confirmation>节点一样被移除。

3)如果我想更新一个不为空的子节点的值,我会这样做吗?更新一些子节点还有一个额外的要求,所以我还在考虑怎么做,这似乎是正确的方法,但我想验证一下。

 <xsl:template match='childNodeA'>
     <childNodeA>
        <xsl:value-of select='someValue/>
     </childNodeA>
 </xsl:template> 

如果不清楚,我深表歉意,但请随时要求您提供所需的任何进一步详细信息,并提前非常感谢任何可以提供帮助的人。

4

1 回答 1

8

您发布的输出 XML 格式不正确,因为它没有根元素,但是这个 XSLT 1.0 样式表应该可以满足您的要求:

样式表

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes" encoding="utf-8"/>
  <xsl:strip-space elements="*"/>

  <!-- Identity transform -->
  <xsl:template match="@* | node()">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
  </xsl:template>

  <!-- Apply all child nodes; don't copy the element itself -->
  <xsl:template match="Response | SecondResponse | InquiryResponse">
    <xsl:apply-templates/>
  </xsl:template>

  <!-- Drop elements -->
  <xsl:template match="Confirmation | Exception"/>

  <xsl:template match="DataNode1 | DataNode2 | DataNodeN">
    <xsl:copy>
      <!-- Apply Child1, ignore children with no text content -->
      <xsl:apply-templates select="Child1[normalize-space(.)]"/>
      <!-- Insert new element -->
      <ChildInsert>newData</ChildInsert>
      <!-- Apply all other child elements except Child1 -->
      <xsl:apply-templates select="*[normalize-space(.)][not(self::Child1)]"/>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

输入

<Response>
  <Confirmation>Success</Confirmation>
  <SecondResponse>
     <InquiryResponse>
        <ID>99999</ID>
        <Confirmation>Success</Confirmation>
        <Exception/>
        <!-- The following structure repeats a varying amount of times -->
        <DataNode1>
           <!-- Child nodes could be null, transform should remove null nodes -->
           <Child1>data</Child1>
           <Childn>dataN</Childn>
        </DataNode1>
        <DataNodeN>
           <Child1>data</Child1>
           <Childn>dataN</Childn>
        </DataNodeN>
     </InquiryResponse>
  </SecondResponse>
</Response>

输出

<?xml version="1.0" encoding="utf-8"?>
<ID>99999</ID>
<DataNode1>
  <Child1>data</Child1>
  <ChildInsert>newData</ChildInsert>
  <Childn>dataN</Childn>
</DataNode1>
<DataNodeN>
  <Child1>data</Child1>
  <ChildInsert>newData</ChildInsert>
  <Childn>dataN</Childn>
</DataNodeN>

请注意,由于您没有指定“null”的含义,我假设它表示没有文本内容的元素。所以上面的代码会删除一个<Child1>像这样的元素:

<Child1>
  <GrandChild1/>
</Child1>
于 2013-02-18T07:22:41.393 回答