在两个不同字段的xslt中进行双重排序

时间:2014-06-26 15:17:00

标签: xml xslt

我想在两个fieds上对我的xml文件进行排序: 标识符和影响。 我想按标识符排序元素,除了必须出现在最后的XX产品的元素外。

我的xml文件是

<evolutionlist>
<date>
    <object>
        <identifier>id5</identifier>
        <impact>
            <product>AA</produit>
        </impact>
    </objet>
    <object>
        <identifier>id2</identifier>
        <impact>
            <product>XX</produit>
        </impact>
    </objet>
    <object>
        <identifier>id4</identifier>
        <impact>
            <product>BB</produit>
        </impact>
    </objet>
   <object>
        <identifier>id3</identifier>
        <impact>
            <product>XX</produit>
        </impact>
    </objet>
    <object>
        <identifier>id1</identifier>
        <impact>
            <product>CC</produit>
        </impact>
    </objet>
 </date>
 </evolutionlist>

显示的结果将是:

<evolutionlist>
<date>
    <object>
        <identifier>id1</identifier>
        <impact>
            <product>CC</produit>
        </impact>
    </objet>
    <object>
        <identifier>id4</identifier>
        <impact>
            <product>BB</produit>
        </impact>
    </objet>
    <object>
        <identifier>id5</identifier>
        <impact>
            <product>AA</produit>
        </impact>
    </objet>
   <object>
        <identifier>id2</identifier>
        <impact>
            <product>XX</produit>
        </impact>
    </objet>
    <object>
        <identifier>id3</identifier>
        <impact>
            <product>XX</produit>
        </impact>
    </objet>
 </date>
 </evolutionlist>

我的xslt代码(虽然不起作用)是

<xsl:for-each  select="//date">
   <tr>
  <td>
     <xsl:value-of select="./@id"/>
  </td>
   </tr>
   <xsl:for-each select="./object">
   <xsl:choose>
    <xsl:when test="impact/produit = 'XX'">
            <xsl:sort select="impact/produit" order="descending"/>
    </xsl:when>
    <xsl:otherwise>
        <xsl:sort select="identifiant"/>
    </xsl:otherwise>
   </xsl:choose>

        ...
 </xsl:for-each>

1 个答案:

答案 0 :(得分:1)

您可以在<xsl:sort><xsl:for-each>的开头放置<xsl:apply-templates/>,而不是<choose>块。

您正在使用排序来订购XX,所以我将假设在您的方案中没有问题(例如:您没有名为ZZ的产品,将放在XX之后。如果情况并非如此,则不应将sort用于该规则,而应使用与XX内容匹配的模板并将其放在最后。

此样式表使用原始样式表中的sort规则生成您期望的结果(按ID和产品字符串排序)。我将选择规则移动到XPath谓词中,并使用模板而不是嵌套的for-each节点。

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

    <xsl:template match="date">
            <xsl:apply-templates select="object">
                <xsl:sort select="impact/product[. = 'XX']" order="ascending"/>
                <xsl:sort select="identifier"/>
            </xsl:apply-templates>
    </xsl:template>

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

</xsl:stylesheet>

您可以在 XSLT Fiddle

中试用

更新如果您实际上并不想订购 XX个产品,而是将它们放在最后,那么您可以过滤这些元素并在处理其他元素后应用它们的模板。这个样式表就是这样做的:

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

    <xsl:template match="date">
        <xsl:apply-templates select="object[not(impact[product = 'XX'])]">
            <xsl:sort select="identifier"/>
        </xsl:apply-templates>
        <xsl:apply-templates select="object[impact[product = 'XX']]"/>
    </xsl:template>

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

</xsl:stylesheet>

此示例中有另一个 XSLT Fiddle