使用XSLT连接相同类型的数据

时间:2012-06-12 08:10:06

标签: xslt

我想加入与XSLT相同类型的所有数据。我有以下XML:

<ZE1MARAM>
        <ZE1KONDM SEGMENT="1">
            <VKORG>NL01</VKORG>
            <KONDART>VKP0</KONDART>
            <BEGINDATUM>99991231</BEGINDATUM>
            <ENDDATUM>20120605</ENDDATUM>
            <KONDWERT>NL01</KONDWERT>
            <MENGE> 70.00</MENGE>
            <CURRENCY>EUR</CURRENCY>
        </ZE1KONDM>
        <ZE1KONDM SEGMENT="1">
            <VKORG>NLWS</VKORG>
            <KONDART>VKP0</KONDART>
            <BEGINDATUM>99991231</BEGINDATUM>
            <ENDDATUM>20120605</ENDDATUM>
            <KONDWERT>NLWS</KONDWERT>
            <MENGE> 70.00</MENGE>
            <CURRENCY>EUR</CURRENCY>
        </ZE1KONDM>
        <ZE1KONDM SEGMENT="1">
            <VKORG>NLWS</VKORG>
            <KONDART>VKA0</KONDART>
            <BEGINDATUM>99991231</BEGINDATUM>
            <ENDDATUM>20120605</ENDDATUM>
            <KONDWERT>NLWS</KONDWERT>
            <MENGE> 33.00</MENGE>
            <CURRENCY>EUR</CURRENCY>
        </ZE1KONDM>
    </ZE1MARAM>

因此结果xml中具有相同VKORG值的每个ZE1KONDM都必须附加到同一个元素。所以结果会是这样的:

<result>
<prices value="NL01">
    <price type="VKP0">
        70.00
    </price>
</prices>
<prices value="NLWS">
    <price type="VKP0">
        70.00
    </price>
    <price type="VKA0">
        55.00
    </price>
</prices>

我尝试使用密钥,并执行类似的操作:

                    <xsl:key name="myKey" match="ZE1KONDM" use="normalize-space(VKORG)" />

                <xsl:for-each select="ZE1KONDM">

                    <xsl:choose>

                        <xsl:when test="KONDART='VKP0'">
                            <xsl:element name="prices">

                                <xsl:element name="price">
                                    <xsl:value-of select="key('myKey', normalize-space(VKORG))/MENGE"/>
                                </xsl:element>

                            </xsl:element>
                        </xsl:when>

                    </xsl:choose>

                </xsl:for-each>

但它不起作用,因为它只需要一个键..

有一些方法可以用xslt解决这个问题吗?

2 个答案:

答案 0 :(得分:1)

可能有更好的方法,但试试这个:

http://www.xmlplayground.com/2A3C7H

(参见输出源)

答案 1 :(得分:1)

<强>予。 XSLT 1.0解决方案:

以下是Muenchian grouping method

的经典应用
<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:key name="kZByM" match="ZE1KONDM" use="VKORG"/>

 <xsl:template match="/*">
     <result>
       <xsl:apply-templates select=
       "*[generate-id() = generate-id(key('kZByM', VKORG)[1])]"/>
     </result>
 </xsl:template>

 <xsl:template match="ZE1KONDM">
  <prices value="{VKORG}">
   <xsl:apply-templates select="key('kZByM', VKORG)" mode="inGroup"/>
  </prices>
 </xsl:template>

 <xsl:template match="ZE1KONDM" mode="inGroup">
   <price type="{KONDART}">
     <xsl:value-of select="MENGE"/>
   </price>
 </xsl:template>
</xsl:stylesheet>

在提供的XML文档上应用此转换时:

<ZE1MARAM>
    <ZE1KONDM SEGMENT="1">
        <VKORG>NL01</VKORG>
        <KONDART>VKP0</KONDART>
        <BEGINDATUM>99991231</BEGINDATUM>
        <ENDDATUM>20120605</ENDDATUM>
        <KONDWERT>NL01</KONDWERT>
        <MENGE>70.00</MENGE>
        <CURRENCY>EUR</CURRENCY>
    </ZE1KONDM>
    <ZE1KONDM SEGMENT="1">
        <VKORG>NLWS</VKORG>
        <KONDART>VKP0</KONDART>
        <BEGINDATUM>99991231</BEGINDATUM>
        <ENDDATUM>20120605</ENDDATUM>
        <KONDWERT>NLWS</KONDWERT>
        <MENGE>70.00</MENGE>
        <CURRENCY>EUR</CURRENCY>
    </ZE1KONDM>
    <ZE1KONDM SEGMENT="1">
        <VKORG>NLWS</VKORG>
        <KONDART>VKA0</KONDART>
        <BEGINDATUM>99991231</BEGINDATUM>
        <ENDDATUM>20120605</ENDDATUM>
        <KONDWERT>NLWS</KONDWERT>
        <MENGE>33.00</MENGE>
        <CURRENCY>EUR</CURRENCY>
    </ZE1KONDM>
</ZE1MARAM>

产生了想要的正确结果:

<result>
   <prices value="NL01">
      <price type="VKP0">70.00</price>
   </prices>
   <prices value="NLWS">
      <price type="VKP0">70.00</price>
      <price type="VKA0">33.00</price>
   </prices>
</result>

请注意 Muenchian分组方法可能是最快的XSLT 1.0分组方法,因为它使用密钥。其他方法(例如比较兄弟值)太慢了(O(N ^ 2)),这对于在大数据大小上使用它们来说是不可取的。


<强> II。 XSLT 2.0解决方案:

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

 <xsl:template match="/*">
     <result>
       <xsl:for-each-group select="*" group-by="VKORG">
          <prices value="{VKORG}">
           <xsl:apply-templates select="current-group()"/>
          </prices>
       </xsl:for-each-group>
     </result>
 </xsl:template>

 <xsl:template match="ZE1KONDM">
   <price type="{KONDART}">
     <xsl:value-of select="MENGE"/>
   </price>
 </xsl:template>
</xsl:stylesheet>

当此转换应用于同一XML文档(上图)时,会产生相同的正确结果

<result>
   <prices value="NL01">
      <price type="VKP0">70.00</price>
   </prices>
   <prices value="NLWS">
      <price type="VKP0">70.00</price>
      <price type="VKA0">33.00</price>
   </prices>
</result>

<强>解释

正确使用 xsl:for-each-group group-by属性以及 current-group() 功能。