通过XSL将一种XML格式转换为另一种格式

时间:2009-07-22 16:52:55

标签: xslt xslt-2.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>标记可以多次出现,并且对于每个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”。 该字段可以出现多次,但新结构将以7个为一组形成。

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

1 个答案:

答案 0 :(得分: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>