1

我想用 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 解决这个问题?

4

2 回答 2

1

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

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

(见输出源)

于 2012-06-12T09:03:27.567 回答
1

一、XSLT 1.0 解决方案:

这是Muenchian 分组方法的经典应用:

<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)),这对于在大数据量上使用它们是禁止的。


二、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-groupwithgroup-by属性,和current-group()函数。

于 2012-06-12T12:30:41.367 回答