2009-09-15 73 views
10

我試圖通過按名稱(而不是值)對每個元素的屬性進行排序來對一些XML數據的表示進行規範化。這個想法是在添加或刪除屬性時儘量減少文本差異,並防止不同編輯引入等效變體。這些XML文件受源代碼控制,開發人員希望能夠在不借助專門的XML工具的情況下對變化進行區分。使用XSL排序屬性

我很驚訝不是找到了一個如何做到這一點的XSL示例。基本上我只想用帶有排序屬性的身份轉換。我想出了用下面好像在我所有的測試用例工作:

<?xml version="1.0"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" encoding="UTF-8" indent="yes"/> 
    <xsl:template match="*|/|text()|comment()|processing-instruction()"> 
    <xsl:copy> 
    <xsl:for-each select="@*"> 
     <xsl:sort select="name(.)"/> 
     <xsl:copy/> 
     </xsl:for-each> 
     <xsl:apply-templates/> 
    </xsl:copy> 
    </xsl:template> 
</xsl:stylesheet> 

作爲總XSL的n00b我將不勝感激風格或效率的任何意見。我認爲在這裏發佈它可能會有所幫助,因爲它似乎至少不是一個常見的例子。

回答

11

由於xslt是一種功能語言,對於我們人類來說,它們通常都是最簡單的路徑,但對XSLT處理器來說卻不是最有效的,因爲它們無法完全優化呼叫。

<?xml version="1.0"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" encoding="UTF-8" indent="yes"/> 
    <xsl:template match="*"> 
    <xsl:copy> 
     <xsl:apply-templates select="@*"> 
     <xsl:sort select="name()"/> 
     </xsl:apply-templates> 
     <xsl:apply-templates/> 
    </xsl:copy> 
    </xsl:template> 
    <xsl:template match="@*|comment()|processing-instruction()"> 
    <xsl:copy />  
    </xsl:template> 
</xsl:stylesheet> 

這完全是微不足道的在這方面,雖然並作爲「XSL的n00b」我想你解決了這個問題確實非常好。

2

做得很好解決了這個問題。正如我假設你知道XML分析器的順序或屬性並不重要,所以這個練習的主要好處是對於人類來說 - 一臺機器會以不可預知的方式對輸入或輸出進行重新排序。

在XML中規範化並不重要,因此建議您使用隨任何合理的XML工具包提供的規範化工具,而不是編寫自己的規範化工具。

+0

XSL變換器是否保證您爲屬性指定的順序是寫出的順序? – 2009-09-15 22:58:46

+3

即使您嘗試像上面那樣構建它,XML工具也不能保證任何XML輸出都能保留屬性順序。還要記住,你甚至不能保證使用什麼符號來引用值。 XML的詞法比較通常是一個糟糕的主意。 – 2009-09-16 06:17:22