XSL排序元素取决于属性,但特定元素除外

时间:2012-10-10 20:02:21

标签: xml xslt sorting

我已经有了一个XSL,它根据属性值@id或@category对我的整个Document进行排序。现在我想通过定义永远不应该排序的节点来增强它。

以下是XML示例:

<root>
    [several levels of xml open]

    <elemetsToBeSorted>
        <sortMe id="8" />
        <sortMe id="2" />
        <sortMe id="4" />
    </elemetsToBeSorted>

    <elemetsNOTToBeSorted>
        <dontSortMe id="5" />
        <dontSortMe id="3" />
        <dontSortMe id="2" />
    </elemetsNOTToBeSorted>

    [several levels of xml closing]
</root>

这是我的XSL:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:output method="xml" indent="yes" />

<!-- Sort all Elements after their id or category -->
<xsl:template match="@* | node()">
    <xsl:copy>
        <xsl:apply-templates select="@* | node()">
            <xsl:sort select="@id" />
            <xsl:sort select="@category" />
        </xsl:apply-templates>
    </xsl:copy>
</xsl:template>


<!-- Next two templates clean up formatting after sorting -->
<xsl:template match="text()[not(string-length(normalize-space()))]" />

<xsl:template match="text()[string-length(normalize-space()) > 0]">
    <xsl:value-of select="translate(.,'&#xA;&#xD;', '  ')" />
</xsl:template>

预期输出:

<root>
    [several levels of xml open]

    <elemetsToBeSorted>
        <sortMe id="2" />
        <sortMe id="4" />
        <sortMe id="8" />
    </elemetsToBeSorted>

    <elemetsNOTToBeSorted>
        <dontSortMe id="5" />
        <dontSortMe id="3" />
        <dontSortMe id="2" />
    </elemetsNOTToBeSorted>

    [several levels of xml closing]
</root>

我怎样才能实现我的XSL忽略“elementsNOTToBeSorted”?

编辑: 我有数百个应该排序的元素,但只有少数元素(及其子元素)不应该排序。所以逻辑就像“排序所有,除了a和b”

2 个答案:

答案 0 :(得分:2)

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

<!-- all elements except a few sort their children -->
<xsl:template match="*[not(self::elemetsNOTToBeSorted | self::otherElemetsNOTToBeSorted)]">
    <xsl:copy>
        <xsl:apply-templates select="@*" />
        <xsl:apply-templates>
            <xsl:sort select="@id" />
            <xsl:sort select="@category" />
        </xsl:apply-templates>
    </xsl:copy>
</xsl:template>

<!-- ... -->

请注意,匹配表达特异性在此处起作用。更具体的匹配表达式决定了将运行的模板:

  • node()的具体程度低于*,因此元素节点将由<xsl:template match="*">
  • 处理
  • 匹配self::elemetsNOTToBeSorted | self::otherElemetsNOTToBeSorted的元素将由身份模板处理。

答案 1 :(得分:0)

添加此行应忽略elementsNOTToBeSorted的所有后代元素:

<xsl:template match="elemetsNOTToBeSorted" />

如果您希望这些元素仍然存在于输出文档中,您只需复制它们而不是抑制:

<xsl:template match="elemetsNOTToBeSorted">
    <xsl:copy-of select="." />
</xsl:template>