XSLT转换根据其值对节点进行分组

时间:2015-11-15 11:25:28

标签: xml xslt xsd xslt-1.0

我是XSLT的新手,任何人都可以帮助我进行以下转换

这是我的输入XML:

<sent_items>
    <item>
        <RECEIPT_NUM>1</RECEIPT_NUM>
        <SHIPMENT_NUM>1</SHIPMENT_NUM>
        <ITEM_NUMBER>10</ITEM_NUMBER>
    </item>
    <item>
        <RECEIPT_NUM>2</RECEIPT_NUM>
        <SHIPMENT_NUM>2</SHIPMENT_NUM>
        <ITEM_NUMBER>100</ITEM_NUMBER>
    </item>
    <item>
        <RECEIPT_NUM>1</RECEIPT_NUM>
        <SHIPMENT_NUM>1</SHIPMENT_NUM>
        <ITEM_NUMBER>20</ITEM_NUMBER>
    </item>
    <item>
        <RECEIPT_NUM>2</RECEIPT_NUM>
        <SHIPMENT_NUM>2</SHIPMENT_NUM>
        <ITEM_NUMBER>30</ITEM_NUMBER>
    </item>
    <item>
        <RECEIPT_NUM>3</RECEIPT_NUM>
        <SHIPMENT_NUM>3</SHIPMENT_NUM>
        <ITEM_NUMBER>40</ITEM_NUMBER>
    </item>
</sent_items>

这是我的输出XML:即如果RECEIPT_NUMSHIPMENT_NUM中的值相同,则在同一个ITEM_NUMBER节点中添加多个item个节点。

<recived_items>
    <item>
        <RECEIPT_NUM>1</RECEIPT_NUM>
        <SHIPMENT_NUM>1</SHIPMENT_NUM>
        <ITEM_NUMBER>10</ITEM_NUMBER>
        <ITEM_NUMBER>20</ITEM_NUMBER>
    </item>
    <item>
        <RECEIPT_NUM>2</RECEIPT_NUM>
        <SHIPMENT_NUM>2</SHIPMENT_NUM>
        <ITEM_NUMBER>100</ITEM_NUMBER>
        <ITEM_NUMBER>30</ITEM_NUMBER>
    </item>
    <item>
        <RECEIPT_NUM>3</RECEIPT_NUM>
        <SHIPMENT_NUM>3</SHIPMENT_NUM>
        <ITEM_NUMBER>40</ITEM_NUMBER>
    </item>
</recived_items>

我已经使用了for-each,如下面的两个例子所示,但是它们都没有给出预期的输出。 1)XSLT:

<recived_items>
    <xsl:for-each select="/sent_items/item">
    <item>
        <RECEIPT_NUM><xsl:value-of select="RECEIPT_NUM"/></RECEIPT_NUM>
        <SHIPMENT_NUM><xsl:value-of select="SHIPMENT_NUM"/></SHIPMENT_NUM>
        <ITEM_NUMBER><xsl:value-of select="ITEM_NUMBER"/></ITEM_NUMBER>
    </item>
    </xsl:for-each>
</recived_items>

2)XSLT:

<recived_items>

    <item>
        <RECEIPT_NUM><xsl:value-of select="RECEIPT_NUM"/></RECEIPT_NUM>
        <SHIPMENT_NUM><xsl:value-of select="SHIPMENT_NUM"/></SHIPMENT_NUM>
        <xsl:for-each select="/sent_items/item">
        <ITEM_NUMBER><xsl:value-of select="ITEM_NUMBER"/></ITEM_NUMBER>
        </xsl:for-each>
    </item>
</recived_items>

请帮我编写XSLT,它将提供预期的输出XML。

1 个答案:

答案 0 :(得分:0)

这是一个分组问题,在使用Muenchian分组的XSLT 1.0中解决了

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:output indent="yes"/>
  <xsl:strip-space elements="*"/>

  <xsl:key name="group" match="item" use="concat(RECEIPT_NUM, '|', SHIPMENT_NUM)"/>

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

  <xsl:template match="item[generate-id() = generate-id(key('group', concat(RECEIPT_NUM, '|', SHIPMENT_NUM))[1])]">
    <xsl:copy>
      <xsl:copy-of select="* | key('group', concat(RECEIPT_NUM, '|', SHIPMENT_NUM))[position() > 1]/ITEM_NUMBER"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="item[not(generate-id() = generate-id(key('group', concat(RECEIPT_NUM, '|', SHIPMENT_NUM))[1]))]"/>

</xsl:stylesheet>