XSLT按名称排序节点?

问题描述:

我不确定xsl:sort指令是如何工作的。我需要通过他们的标签名称来排序元素(用于区分),而我似乎无法想出如何完成这项工作。我的第一个虽然是修改身份转换,只是修改它包括一个排序声明,但我不确定如何做到这一点。XSLT按名称排序节点?

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

+0

请提供一个小的源XML文档以及转换的预期结果。 – 2010-11-03 20:04:13

+0

好问题,+1。查看我的答案,获得一个完整的解决方案,它还可以对属性进行排序并发出警告 – 2010-11-03 20:14:36

这种转变

<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为diff文件是不可靠的,因为XML文档转换成排序的表示是不是1:1的映射。

+0

如果通过DOM纯粹访问XML结构,为什么排序后的文档不能被区分? – 2010-11-03 20:20:56

+0

@ Stefan-Kendall:因为一个元素可能具有相同数量的相同名称的子元素(在这两个文档中),但在每个文档中的顺序完全不同。这两个文件将被转换为产生相同的子元素列表,差异操作(或只是个人观察)不会发现任何差异。 – 2010-11-03 21:47:50

+0

无论如何,在我解析的文档中不保证顺序,同一级别的任何东西都是等价的,所以我猜这应该起作用。 – 2010-11-03 22:06:20