XSLT-将具有少量结构的重复元素列表转换为有序列表

时间:2017-01-31 13:50:13

标签: xml xslt transform xslt-2.0

我正在尝试从xml源转换输出,如图所示。我的尝试显示

输入:

 <products>
   <name>bananas</name>
  <price>3.55</price>
  <sku>1223-777-93222</sku>
  <name>pineapple</name>
   <price>1.25</price>
   <sku>013-144-9355</sku>
 </products>

预期产出:

    <orders>
    <order>
     <name>bananas</name>
     <price>3.55</price>
     <item-number>1223-777-93222</item-number>
     </order>
    <order>
     <name>pineapple</name>
     <price>1.25</price>
     <item-number>013-144-9355</item-number>
    </order>
    </orders>

XSLT:

      <xsl:choose>
         <xsl:when test="name">
       <order>
         <name><xsl:value-of select="."/>
       </xsl:when>
       <xsl:when test="price">
       <price><xsl:value-of select="."/></price>
       </xsl:when>
       <xsl:when test="sku">
        <item-number><xsl:value-of select="."/></price></item-number>
        </order>
       <xsl:when>
       <xsl:otherwise>
        </orders>
      </xsl:otherwise>

然而,我无法让它发挥作用。它不打印我所期望的。我希望在转换输出方面有所帮助。

请帮助,谢谢

2 个答案:

答案 0 :(得分:0)

由于您已将问题标记为XSLT 2.0,因此您可以使用xsl:for-each-groupgroup-starting-with ...

XSLT 2.0

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output indent="yes"/>
  <xsl:strip-space elements="*"/>

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

  <xsl:template match="/*">
    <orders>
      <xsl:for-each-group select="*" group-starting-with="name">
        <order>
          <xsl:apply-templates select="current-group()"/>
        </order>
      </xsl:for-each-group>
    </orders>
  </xsl:template>

  <xsl:template match="sku">
    <item-number>
      <xsl:apply-templates/>
    </item-number>
  </xsl:template>

</xsl:stylesheet>

编辑:没有注意到您想要更改sku的输出。

答案 1 :(得分:0)

假设您的输入是常规的(即每个项目由完全相同的三个元素以相同的顺序表示),您可以做到:

XSLT 1.0

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

<xsl:template match="/products">
    <orders>
        <xsl:for-each select="name">
            <order>
                <xsl:copy-of select=". | following-sibling::price[1]"/>
                <item-number>
                    <xsl:value-of select="following-sibling::sku[1]"/>
                </item-number>
            </order>
        </xsl:for-each>
    </orders>
</xsl:template>

</xsl:stylesheet>