【问题标题】:XSLT, how to sort by element nameXSLT,如何按元素名称排序
【发布时间】:2012-06-12 13:46:51
【问题描述】:

我是 XSLT 的新手。我只是提出一个问题,希望有人能提供帮助。

假设我有一个源 xml,

<?xml version="1.0"?>
<docroot>
    <vc6>foo</vc6>
    <vc7>bar7</vc7>
    <vc8 arch="x64">amd64demo</vc8>
    <vc7>foo7</vc7>
    <vc6>bar</vc6>
</docroot> 

我想把它变成:

<?xml version="1.0"?>
<docroot>
    <vc6>bar</vc6>
    <vc6>foo</vc6>
    <vc7>bar7</vc7>
    <vc7>foo7</vc7>
    <vc8 arch="x64">amd64demo</vc8>
</docroot> 

也就是说,

  1. 的子元素应该按元素名称排序,所以&lt;vc6>在&lt;vc7>之前。
  2. 如果两个子元素名称相同,则应按其文本值对它们进行排序,因此“bar”在“foo”之前。

xsl怎么写?谢谢。

【问题讨论】:

    标签: xml xslt


    【解决方案1】:

    修改legoscia的答案:

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

    【讨论】:

    • 糟糕,您的两个 元素不是成对出现的。即使我并排复制 结束标记,以使其格式正确。 xsltproc 2.7.8 仅输出 &lt;docroot/&gt; ,而不是预期结果。
    【解决方案2】:

    this answer 中有一些如何使用xsl:sort 的示例。像这样的东西应该适合你:

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

    【讨论】:

    • 谢谢你,你给出了正确的答案。但是,您能否更新您的答案以便可以复制属性?目前,使用源 xml 中的属性,xsltproc 2.7.8 说“必须在元素的任何子节点之前添加属性节点”。
    • 不,还是错了。如果有一个名为 AA 的子元素和一个名为 ZZ 的属性,它会尝试将子元素放在属性之前。
    • 抱歉,legoscia,我注意到您刚刚交换了@*node(),但仍然出现错误:“必须在元素的任何子节点之前添加属性节点”。有没有用一些 xslt 软件验证过?
    • 对,现在它已经过实际测试了 :) 适用于我的 xsltproc。
    • 据报道,我还使用 xsltproc 得到“必须在元素的任何子节点之前添加属性节点”,但是 @MichaelKay 回答对我来说很好
    猜你喜欢
    • 2011-05-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-09
    • 1970-01-01
    • 1970-01-01
    • 2014-05-07
    相关资源
    最近更新 更多