XSLT根据id匹配选择节点的最小值

时间:2016-03-17 18:12:14

标签: xml xslt

XML输入:

<Root>


<output>
    <queries>
        <query name="Test">
            <parameters>
                <parameter>298674,298673,298675,298676</parameter>
            </parameters>
            <queryResults>
                <record id="1">
                    <column name="Order">272334</column>
                    <column name="Task">272093</column>
                    <column name="FirstAction">2709305</column>                     
                </record>
                <record id="2">
                    <column name="Order">272334</column>
                    <column name="Task">272093</column>
                    <column name="FirstAction">2709301</column>
                </record>
                <record id="3">
                    <column name="Order">272334</column>
                    <column name="Task">272093</column>
                    <column name="FirstAction">2709306</column>
                </record>
                <record id="4">
                    <column name="Order">268997</column>
                    <column name="Task">268756</column>
                    <column name="FirstAction">2709307</column>
                </record>
                <record id="5">
                    <column name="Order"/>
                    <column name="Task"/>
                    <column name="FirstAction">2709307</column>
                </record>
            </queryResults>
        </query>
    </queries>
</output>
</Root>

期望的输出:

<Tag1>
<Tag2>
    <parameters>
        <order id="272334"/>
        <order id="268997"/>
        <task id="272093">
            <grt>
                <action id="2709301"/>
            </grt>
        </task>
        <task id="268756">
            <grt>
                <action id="2709307"/>
            </grt>
        </task>
    </parameters>
</Tag2>
</Tag1>

我希望每个列名称='Order'具有相同的ID,以便在<grt>标记中显示列名'FirstAction'的最低值。如果列名称“订单”不重复,则在<grt>标记中显示当前<record>标记中“FirstAction”的值。 基本上,如果相同的订单号重复,则采用最低的第一个操作号,如果不是,则从第一个操作节点获取值。 我似乎无法使其发挥作用。

我的XSL当前显示了订单的所有不同值,没有重复,但不知道如何为FirstAction节点做。

我的XSL:

<xsl:template match="/">
    <Tag1>
        <Tag2>
            <parameters>
                <xsl:for-each select="//record/column[@name='Order'][not(.=preceding::*)]">
                    <order>
                        <xsl:attribute name="id"><xsl:value-of select="."/></xsl:attribute>
                    </order>
                </xsl:for-each>
                <xsl:for-each select="//record/column[@name='Task'][not(.=preceding::*)]">
                    <task>
                        <xsl:attribute name="id"><xsl:value-of select="."/></xsl:attribute>
                        <grt>
                            <action>
                                <xsl:attribute name="id"><xsl:value-of select="current()/@column[@name='FirstAction']"/></xsl:attribute>
                            </action>
                        </grt>
                    </task>
                </xsl:for-each>

            </parameters>
        </Tag2>
    </Tag1>
</xsl:template>
</xsl:stylesheet>

非常感谢!

1 个答案:

答案 0 :(得分:2)

首先,我建议您使用Muenchian method对记录进行分组 - 并且只执行一次。

然后使用相同的密钥获取当前组中的记录,按FirstAction值对其进行排序,并获取已排序组中的第一条记录:

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:key name="record-by-order" match="record" use="column[@name='Order']" />

<xsl:template match="/Root">
    <xsl:variable name="unique-orders" select="//record[count(. | key('record-by-order', column[@name='Order'])[1]) = 1]"/>
    <Tag1>
        <Tag2>
            <parameters>
                <xsl:for-each select="$unique-orders">
                    <order id="{column[@name='Order']}"/>
                </xsl:for-each>
                <xsl:for-each select="$unique-orders">
                    <task id="{column[@name='Task']}">
                        <xsl:for-each select="key('record-by-order', column[@name='Order'])">
                            <xsl:sort select="column[@name='FirstAction']" data-type="number" order="ascending"/>
                            <xsl:if test="position()=1">
                                <grt>
                                    <action id="{column[@name='FirstAction']}"/>
                                </grt>
                            </xsl:if>
                        </xsl:for-each>
                    </task>
                </xsl:for-each>
            </parameters>
        </Tag2>
    </Tag1>
</xsl:template>

</xsl:stylesheet>

应用于您的输入,结果将是:

<?xml version="1.0" encoding="UTF-8"?>
<Tag1>
   <Tag2>
      <parameters>
         <order id="272334"/>
         <order id="268997"/>
         <order id=""/>
         <task id="272093">
            <grt>
               <action id="2709301"/>
            </grt>
         </task>
         <task id="268756">
            <grt>
               <action id="2709307"/>
            </grt>
         </task>
         <task id="">
            <grt>
               <action id="2709307"/>
            </grt>
         </task>
      </parameters>
   </Tag2>
</Tag1>

注意

要排除没有Order值的记录,请尝试:

<xsl:variable name="unique-orders" select="//record[string(column[@name='Order'])][count(. | key('record-by-order', column[@name='Order'])[1]) = 1]"/>