【问题标题】:XSLT to sort nodes by name?XSLT 按名称对节点进行排序?
【发布时间】:2011-05-04 17:09:01
【问题描述】:

我不确定xsl:sort 指令的工作原理。我需要按标签名称对元素进行排序(用于区分),我似乎无法想出如何使这项工作。我的第一个想法是修改身份转换,然后将其修改为包含一个排序语句,但我不确定该怎么做。

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

【问题讨论】:

  • 请提供一个小的源 XML 文档以及转换的预期结果。
  • 好问题,+1。请参阅我的答案以获取还对属性进行排序和警告的完整解决方案。

标签: xml xslt sorting


【解决方案1】:

这种转变

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

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

   <xsl:apply-templates select="node()">
    <xsl:sort select="name()"/>
   </xsl:apply-templates>
  </xsl:copy>
 </xsl:template>
</xsl:stylesheet>

应用于此 XML 文档时

<t b="x" c="y" a="t">
  <c/>
  <b/>
  <a/>
</t>

产生想要的排序输出

<t a="t" b="x" c="y">
    <a></a>
    <b></b>
    <c></c>
</t>

请注意

  1. 不仅元素而且属性都被排序(后者依赖于实现,但可以与 MSXML 一起使用)。

  2. 对差异使用排序的 XML 是不可靠的,因为将 XML 文档转换为排序的表示不是 1:1 映射。

【讨论】:

  • 如果XML结构是纯粹通过DOM访问的,为什么排序后的文档不能被diff?
  • @Stefan-Kendall:因为一个元素可能有相同数量的同名子级(在两个文档中),但在每个文档中的顺序却大不相同。两个文档都将被转换为该元素生成相同的子元素列表,并且 diff 操作(或只是个人观察)不会发现任何差异。
  • 无论如何,我正在解析的文档中的顺序都不能保证,并且同一级别的任何内容都是等效的,所以我想这应该可以。
  • @Stefan-Kendall:两个 XML 文档不同的,即使唯一的区别在于元素的顺序。
  • 我还想指出,作为答案的一部分,apply-template 的拆分对于防止sort 描述符以相同的序列化顺序处理节点和属性是必要的。一旦命中属性后的第一个节点,就无法处理更多属性。通过拆分排序指令,我们避免了这个问题并获得所需的排序。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-16
  • 2017-09-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-04
相关资源
最近更新 更多