XSLT - 复制元素,其属性值大于列表中的其他元素

时间:2017-05-07 16:59:34

标签: xml xslt

我需要为下面的输入xml编写XSl - 预期的输出应该有一个具有最大属性(key)值的cluster元素。

输入:

<ProductList>
<Product ProductId="123">
 <ClusterList>
 <Cluster Key="1" Price="100.00"/>
 <Cluster Key="3" Price="200.00"/>
 <Cluster Key="2" Price="300.00"/>
 </ClusterList>
</Product>
<Product ProductId="456">
 <ClusterList>
 <Cluster Key="11" Price="100.00"/>
 <Cluster Key="33" Price="200.00"/>
 <Cluster Key="22" Price="300.00"/>
 </ClusterList>
</Product>
<ProductList>

预期产出:

<ProductList>
<Product ProductId="123">
 <ClusterList>
 <Cluster Key="3" Price="200.00"/>
 </ClusterList>
</Product>
<Product ProductId="456">
 <ClusterList>
 <Cluster Key="33" Price="200.00"/>
 </ClusterList>
</Product>
<ProductList>

这是我写的XSL,但没有工作:(

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

   <xsl:template match="/ClusterList/Cluster">
      <xsl:variable name="Max">
         <xsl:value-of select="/ClusterList/Cluster[not(preceding-sibling::Cluster/@Key &gt;= @Key) and not(following-sibling::Cluster/@Key &gt; @Key)]/@Key" />
      </xsl:variable>

      <xsl:if test="@Key=$Max">
         <xsl:copy>
            <xsl:apply-templates select="@*" />
         </xsl:copy>
      </xsl:if>
   </xsl:template>
</xsl:stylesheet>

1 个答案:

答案 0 :(得分:1)

我建议你这样试试:

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="*"/>

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

<xsl:template match="ClusterList">
    <xsl:copy>
        <xsl:for-each select="Cluster">
            <xsl:sort select="@Key" data-type="number" order="descending"/>
            <xsl:if test="position()=1">
                <xsl:copy-of select="."/>
            </xsl:if>
        </xsl:for-each>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

假设您使用的是不支持EXSLT math:max()math:highest()扩展功能的XSLT 1.0处理器。

请注意,如果是平局,则只会返回第一个结果。

要按照开始的方式进行操作,您需要:

<xsl:template match="Cluster">
    <xsl:if test="not(preceding-sibling::Cluster/@Key &gt; current()/@Key) and not(following-sibling::Cluster/@Key &gt; current()/@Key)">
        <xsl:copy>
            <xsl:apply-templates select="@*" />
        </xsl:copy>
    </xsl:if>
</xsl:template>

这是非常低效的,因为它必须将每个Cluster重新与所有兄弟姐妹进行比较。