0

现有格式是

<A>
  <B>
    <C>hello</C>
    <C>how</C>
    <C>are</C>
    <C>you</C> 
  </B>
</A>

我想把它变成这样的东西

<start>
  <A>
    <B>
      <tag1> hello </tag1>
      <tag2> hello </tag2>
    </B>
  </A>
  <A>
    <B>
      <tag1> are </tag1>
      <tag2> you </tag2>
    </B>
  </A>
</start>

现在这个<C>标签可以出现 n 次,并且对于每组 2<C>个标签,应该创建一个具有相同标签名称的新<A> </A>标签(请参阅两种情况下的 tag1 和 tag2 名称相同)。整个过程是动态的。

更新:

我有一个像这样的现有动态 XML 结构

<LSR_RESP>
    <HDR> 
        <ORD>AAAAA</ORD>   
        <ORD>BBBBB</ORD>  
        <ORD>CCCCC</ORD>   
        <ORD>DDDDD</ORD> 
        <ORD>EEEEE</ORD> 
        <ORD>FFFFF</ORD>
        <ORD>GGGGG</ORD>
        <ORD>RRRRR</ORD>
        <ORD>KKKKK</ORD>
    </HDR>
</LSR_RESP>

我想通过 XSLT 将它转换成这样的东西

<entity>
<r>
  <c>
  <f ID="OrderNumber1">AAAAA</f> 
  <f ID="OrderNumber2">BBBBB</f> 
  <f ID="OrderNumber3">CCCCC</f> 
  <f ID="OrderNumber4">DDDDD</f> 
  <f ID="OrderNumber5">EEEEE</f> 
  <f ID="OrderNumber6">FFFFF</f> 
  <f ID="OrderNumber7">GGGGG</f> 
  </c>
  </r>
  <r>
  <c>
  <f ID="OrderNumber1">RRRRR</f> 
  <f ID="OrderNumber2">KKKKK</f> 
  </c>
  </r>
  </entity>

现在,正如您在上面看到的那样,每个行标签都是通过以 7 为一组获取标签值来制作的。新标签的名称也将在 7 组中重复出现,例如“OrderNumber1”到“OrderNumber7”。该场可以出现 n 次,但新结构将以 7 个一组的形式形成。

就像上面的例子一样,有 9 个标签,因此它形成 2 个组,其中 7 个留下 (9-7) 即下一组的 2 个标签,因此在下一组中您只能看到 OrderNumber1 和 OrderNumber2。如果有 10 个标签,它将是一组 7 个标签,然后是另一组 3 个标签。如果有 15 个标签,它将是两组 7 个标签,然后是另一组 1 个标签。

4

1 回答 1

3

最简单的方法(XSLT 1.0 就足够了):

<xsl:stylesheet
  version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>

<xsl:template match="/">
  <start>
    <xsl:apply-templates select="
      A/B/C[position() mod 2 = 1 and following-sibling::C]" 
    />
  </start>
</xsl:template>

<xsl:template match="C">
  <A>
    <B>
      <tag1>
        <xsl:value-of select="text()" />
      </tag1>
      <tag2>
        <xsl:value-of select="following-sibling::C[1]/text()" />
      </tag2>
    </B>
  </A>
</xsl:template>

</xsl:stylesheet>

也可能,由于使用单独的模板和<xsl:copy>/可能更灵活<xsl:copy-of>

<xsl:stylesheet
  version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>

  <xsl:template match="/">
    <start>
      <xsl:for-each select="
        A/B/C[position() mod 2 = 1 and following-sibling::C]
      ">
        <xsl:apply-templates select="ancestor::A">
          <xsl:with-param name="C" select="." />
        </xsl:apply-templates>
      </xsl:for-each>
    </start>
  </xsl:template>

  <xsl:template match="A">
    <xsl:param name="C" />
    <xsl:copy>
      <xsl:copy-of select="@*" />
      <xsl:apply-templates select="B">
        <xsl:with-param name="C" select="$C" />
      </xsl:apply-templates>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="B">
    <xsl:param name="C" />
    <xsl:copy>
      <xsl:copy-of select="@*" />
      <xsl:apply-templates select="$C" />
    </xsl:copy>
  </xsl:template>

  <xsl:template match="C">
    <tag1>
      <xsl:value-of select="text()" />
    </tag1>
    <tag2>
      <xsl:value-of select="following-sibling::C[1]/text()" />
    </tag2>
  </xsl:template>

</xsl:stylesheet>

但是话又说回来,也许这过于复杂,这取决于您的实际数据。关键是只选择感兴趣的<C>节点(位于奇数位置的节点)并围绕它们构建其余的转换。

两个模板都会导致:

<start>
  <A>
    <B>
      <tag1>hello</tag1>
      <tag2>how</tag2>
    </B>
  </A>
  <A>
    <B>
      <tag1>are</tag1>
      <tag2>you</tag2>
    </B>
  </A>
</start>
于 2009-07-22T16:59:34.143 回答