2013-04-30 236 views
2

我發現了一些類似的問題,但仍苦苦掙扎以解決我所需的問題,所以請再次提問。使用XSLT將XML排序爲XML

我有一些這樣的XML ....

<?xml version="1.0" encoding="UTF-8"?> 

<ns:Root 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:ns="urn:Test.Namespace" 
    xsi:schemaLocation="urn:Test.Namespace Test1.xsd" 
    > 
    <ns:element1 id="001"> 
     <ns:element2 id="001.1" order="1"> 
      <ns:element3 id="001.1.1" /> 
     </ns:element2> 
     <ns:element2 id="001.2" order="2"> 
      <ns:element3 id="001.1.2" /> 
     </ns:element2>   
    </ns:element1> 
    <ns:element1 id="003"> 
     <ns:element2 id="007.0" order="1"> 
      <ns:element3 id="007.1.1" /> 
     </ns:element2> 
    </ns:element1> 
    <ns:element1 id="002"> 
     <ns:element2 id="002.1" order="3"> 
      <ns:element3 id="002.1.1" /> 
     </ns:element2> 
     <ns:element2 id="002.2" order="4"> 
      <ns:element3 id="002.1.2" /> 
     </ns:element2> 
    </ns:element1>  
</ns:Root> 

我寫了這個XSLT

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="1.0" 
       xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
       xmlns:ns="urn:Test.Namespace" 
       > 
    <xsl:output indent="no" /> 
    <xsl:template match="text()[not(string-length(normalize-space()))]"/> 
    <xsl:strip-space elements="*"/> 

    <xsl:template match="/"> 
     <xsl:apply-templates> 
      <xsl:sort select="/ns:Root/ns:element1/@id" /> 
      <xsl:copy-of select="." /> 
     </xsl:apply-templates> 
    </xsl:template> 

    <xsl:template match="ns:element1"> 
     <xsl:copy-of select="." /> 
     <xsl:apply-templates />   
    </xsl:template> 

    <xsl:template match="ns:element2"> 
     <xsl:copy-of select="." /> 
     <xsl:apply-templates /> 
    </xsl:template> 

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

</xsl:stylesheet> 

(我對那兒剽竊這個綱要從這裏how to sort xml?

我希望能夠做到的是使用此XSLT通過element1的id屬性對我的原始XML進行排序並生成XML。這個想法是,一旦它被排序,我就可以用其他一些XSLT來處理,以獲得最終結果。

不幸的是,這並沒有給我任何輸出,這讓我覺得有一個非常愚蠢的錯字。某處,但我看不到它。

任何幫助,將不勝感激。

謝謝

+0

你的命名空間依舊不匹配。在XML中它是'xmlns:ns =「urn:TestNamespace」'但在你的XSLT中顯示爲'xmlns:ns =「urn:Test.Namespace」' – 2013-04-30 16:53:28

+0

這就是試圖一次做太多不同的事情。謝謝。它應該是現在。 – Nerdio 2013-05-01 09:08:14

回答

3

你的問題都位於這裏

<xsl:template match="/"> 
    <xsl:apply-templates> 
     <xsl:sort select="/ns:Root/ns:element1/@id" /> 
     <xsl:copy-of select="." /> 
    </xsl:apply-templates> 
</xsl:template> 

這個匹配模板首先在\符號文檔級別的元素,這是不一樣的根匹配ns:根,但關於它的一個級別。這意味着當你做<xsl:apply-templates>時,所有選擇的是ns:root元素,其中只有一個元素,所以沒有點排序!

你可能需要開始的就是像這樣在根元素上匹配,複製它,然後開始對孩子進行排序。

<xsl:template match="/*"> 
    <xsl:copy> 
     <!-- Code to select and sort childrens --> 
    </xsl:copy> 
</xsl:template> 

你遇到的下一個問題是排序聲明。您正在使用xpath表達式/ns:Root/ns:element1/@id,但這是一個絕對路徑,而不是相對路徑,所以只會選取文檔中第一個ns:element1的@id屬性。

假設你被定位在根元素已經,並假設它只有NS:部件1種元素作爲孩子,你可能只是這個

<xsl:apply-templates> 
     <xsl:sort select="@id" /> 
    </xsl:apply-templates> 

你的最後一個問題是,你有一個<xsl:copy-of select="." />聲明在你的xsl:apply-templates這是不允許的。您可能應該在這裏使用xsl:複製,如上所示。

另外值得指出的是,如果您還沒有意識到,最好使用XSLT identity transform複製現有元素,除非您想以某種方式更改它們。這樣你就不必爲每種特定類型的元素創建模板。

試試下面的XSLT

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="1.0" 
       xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
       xmlns:ns="urn:TestNamespace"    > 
    <xsl:output indent="yes" /> 

    <xsl:strip-space elements="*"/> 

    <xsl:template match="text()[not(string-length(normalize-space()))]"/> 

    <xsl:template match="/*"> 
     <xsl:copy> 
     <xsl:apply-templates select="@*" /> 
     <xsl:apply-templates> 
      <xsl:sort select="@id" /> 
     </xsl:apply-templates> 
     </xsl:copy> 
    </xsl:template> 

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

當適用於您的XML,下面是輸出

<ns:Root xmlns:ns="urn:Test.Namespace" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="urn:Test.Namespace Test1.xsd"> 
    <ns:element1 id="001"> 
     <ns:element2 id="001.1" order="1"> 
     <ns:element3 id="001.1.1"/> 
     </ns:element2> 
     <ns:element2 id="001.2" order="2"> 
     <ns:element3 id="001.1.2"/> 
     </ns:element2> 
    </ns:element1> 
    <ns:element1 id="002"> 
     <ns:element2 id="002.1" order="3"> 
     <ns:element3 id="002.1.1"/> 
     </ns:element2> 
     <ns:element2 id="002.2" order="4"> 
     <ns:element3 id="002.1.2"/> 
     </ns:element2> 
    </ns:element1> 
    <ns:element1 id="003"> 
     <ns:element2 id="007.0" order="1"> 
     <ns:element3 id="007.1.1"/> 
     </ns:element2> 
    </ns:element1> 
</ns:Root> 
+0

這個像上面所說的那樣工作得很好,而且現在已經通過爲我的應用程序重新工作而得到證實。謝謝。我還有一點需要學習:) – Nerdio 2013-05-01 09:05:54

+0

對不起,當時沒有意識到,但這裏的'剝離'示例並不像我在那個ns中的真實應用程序那樣:除了顯示的以外,root還有其他屬性。當我使用這種排序時,這些屬性會丟失。 – Nerdio 2013-05-01 13:29:48

+0

對XML的'noob'我不確定這個解決方案是如何工作的。 從我可以辨認出這是做大多數XML的再現 的XSLT的 和匹配屬性似乎是匹配任何屬性或節點,但它似乎不適用於根。 我需要做什麼才能獲得ns中的任何附加屬性:root被複製出來? – Nerdio 2013-05-01 13:31:17

0

是的,這是一個簡單的錯字。 只需在XSLT中將您的名稱空間更改爲您在XML中使用的名稱空間。 -或相反亦然。

xmlns:ns="urn:Test.Namespace" -> xmlns:ns="urn:TestNamespace" 

第二個修復(根據您的評論)只包括交換。

<xsl:template match="/"> 
    <xsl:apply-templates> 
     <xsl:sort select="/ns:Root/ns:element1/@id" /> 
     <xsl:copy-of select="." /> 
    </xsl:apply-templates> 
</xsl:template> 

<xsl:template match="/"> 
    <xsl:apply-templates select="ns:Root/ns:element1"> 
     <xsl:sort select="@id" /> 
    </xsl:apply-templates> 
</xsl:template> 
+0

我已更新我的XML以包含更正的命名空間(請參閱上文)。我現在得到輸出,但沒有排序。 – Nerdio 2013-04-30 14:57:21

+0

可以按元素排序嗎?例如:<?XML版本= 「1.0」 編碼= 「UTF-8」><! - 大量的信息... - > ' <錘對象> 標題3 標題2 標題1 標題1 標題3 <錘對象> ' 如何由'title' – Robinho 2015-12-16 10:53:33

+0

2016-01-12 15:17:13