2011-02-14 103 views
0

我有幾個巨大的XML,我只需要對它們中的一小部分進行排序。 作爲輸出我應該有相同的XML,但有子結構。 下面是一個例子:使用XSLT排序的XML到XML

<testStructure> 
<parentStruct> 
    <firstpPreChild>some value here</firstpPreChild> 
    <secondPreChild>some other value</secondPreChild> 
    <thirdPreChild>third value here</thirdPreChild> 
    <fourtPreChild>fourth value here</fourtPreChild> 
    <struct id="5"> 
     <num>5</num> 
    </struct> 
    <struct id="4"> 
     <num>4</num> 
    </struct> 
    <struct id="1"> 
     <num>1</num> 
    </struct> 
    <struct id="2"> 
     <num>2</num> 
    </struct> 
    <struct id="3"> 
     <num>3</num> 
    </struct> 
    <firstAdditionalChild>some value here</firstAdditionalChild> 
    <secondAdditionalChild>some other value</secondAdditionalChild> 
    <thirdAdditionalChild>third value here</thirdAdditionalChild> 
    <fourtAdditionalChild>fourth value here</fourtAdditionalChild>--> 
</parentStruct> 
<otherStruct> 
    <firstChild>some value here</firstChild> 
    <secondChild>some other value</secondChild> 
    <thirdChild>third value here</thirdChild> 
    <fourtChild>fourth value here</fourtChild> 
</otherStruct> 

應轉變到

<testStructure> 
<parentStruct> 
    <firstpPreChild>some value here</firstpPreChild> 
    <secondPreChild>some other value</secondPreChild> 
    <thirdPreChild>third value here</thirdPreChild> 
    <fourtPreChild>fourth value here</fourtPreChild> 
    <struct id="1"> 
     <num>1</num> 
    </struct> 
    <struct id="2"> 
     <num>2</num> 
    </struct> 
    <struct id="3"> 
     <num>3</num> 
    </struct> 
    <struct id="4"> 
     <num>4</num> 
    </struct> 
    <struct id="5"> 
     <num>5</num> 
    </struct> 
    <firstAdditionalChild>some value here</firstAdditionalChild> 
    <secondAdditionalChild>some other value</secondAdditionalChild> 
    <thirdAdditionalChild>third value here</thirdAdditionalChild> 
    <fourtAdditionalChild>fourth value here</fourtAdditionalChild>--> 
</parentStruct> 
<otherStruct> 
    <firstChild>some value here</firstChild> 
    <secondChild>some other value</secondChild> 
    <thirdChild>third value here</thirdChild> 
    <fourtChild>fourth value here</fourtChild> 
</otherStruct> 

爲排序規則可用於任一num@id。 我已經嘗試了一些變化是這樣的:

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

它的工作原理,但是從原來的位置移到了有序結構。不幸的是我需要和輸出一樣的結構。

在此先感謝您的幫助!

+0

你希望如果有什麼的' '元素不是相鄰的,但有其他的孩子? –

回答

3

分組相鄰,然後排序,這個XSLT 1.0樣式:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:key name="kStructByFirstPreceding" 
      match="struct" 
      use="generate-id(
        preceding-sibling::struct[ 
         not(preceding-sibling::*[1]/self::struct) 
        ][1] 
       )"/> 
    <xsl:template match="node()|@*" name="identity"> 
     <xsl:copy> 
      <xsl:apply-templates select="node()|@*"/> 
     </xsl:copy> 
    </xsl:template> 
    <xsl:template match="struct[not(preceding-sibling::*[1]/self::struct)]"> 
     <xsl:apply-templates select=".|key('kStructByFirstPreceding', 
              generate-id())" 
          mode="copy"> 
      <xsl:sort select="@id"/> 
     </xsl:apply-templates> 
    </xsl:template> 
    <xsl:template match="struct"/> 
    <xsl:template match="node()" mode="copy"> 
     <xsl:call-template name="identity"/> 
    </xsl:template> 
</xsl:stylesheet> 

輸出:

<testStructure> 
    <parentStruct> 
     <firstpPreChild>some value here</firstpPreChild> 
     <secondPreChild>some other value</secondPreChild> 
     <thirdPreChild>third value here</thirdPreChild> 
     <fourtPreChild>fourth value here</fourtPreChild> 
     <struct id="1"> 
      <num>1</num> 
     </struct> 
     <struct id="2"> 
      <num>2</num> 
     </struct> 
     <struct id="3"> 
      <num>3</num> 
     </struct> 
     <struct id="4"> 
      <num>4</num> 
     </struct> 
     <struct id="5"> 
      <num>5</num> 
     </struct> 
     <firstAdditionalChild>some value here</firstAdditionalChild> 
     <secondAdditionalChild>some other value</secondAdditionalChild> 
     <thirdAdditionalChild>third value here</thirdAdditionalChild> 
     <fourtAdditionalChild>fourth value here</fourtAdditionalChild>--&gt; 
    </parentStruct> 
    <otherStruct> 
     <firstChild>some value here</firstChild> 
     <secondChild>some other value</secondChild> 
     <thirdChild>third value here</thirdChild> 
     <fourtChild>fourth value here</fourtChild> 
    </otherStruct> 
</testStructure> 

簡單的XSLT 2.0解決方案:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:template match="node()|@*"> 
     <xsl:copy> 
      <xsl:apply-templates select="node()|@*"/> 
     </xsl:copy> 
    </xsl:template> 
    <xsl:template match="*[struct]"> 
     <xsl:copy> 
      <xsl:for-each-group select="*" 
           group-adjacent="boolean(self::struct)"> 
       <xsl:apply-templates select="current-group()"> 
        <xsl:sort select="@id[current-grouping-key()]"/> 
       </xsl:apply-templates> 
      </xsl:for-each-group> 
     </xsl:copy> 
    </xsl:template> 
</xsl:stylesheet> 
+0

+1以獲得正確的解決方案。 – Flack

+2

+1表示解決問題的方法。 Alejandro,我有一個問題:我認爲具有'group-adjacent =「boolean(self :: struct)」的XSLT 2.0解決方案僅適用於自動剝離空白文本節點的XSLT處理器(如AltovaXML Tools)或如果將'添加到代碼中。在這兩種情況下,我認爲你也需要''來獲得可讀和縮進的輸出,就像你發佈的那樣。你是否刻意忽略了保持樣本短小的原因,或者你是否使用了自動進行縮進的工具/編輯器? –

+1

@Martin Honnen:你說的只是剝去空白文本節點是正確的,我正在使用Altova,現在正在編輯。關於識別:從不關注xsl:output/@ indent,因爲每個處理器都按照自己的意願做,因爲在生產中我永遠不會使用識別。 – 2011-02-14 13:44:24