2013-04-12 45 views
1

我有下面的XML:XSLT排序混合孩子的

<?xml version="1.0" encoding="UTF-8"?> 
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
     <xsl:output method="xml" version="1.0" encoding="UTF-8" omit-xml-declaration="no" indent="yes" media-type="text/html"/> 

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

     <xsl:template match="nodeLevel1"> 
      <xsl:copy> 
      <xsl:apply-templates select="node()|@*"> 
       <xsl:sort select="rank" data-type="number" /> 
      </xsl:apply-templates> 
      </xsl:copy> 
     </xsl:template> 

     </xsl:stylesheet> 

結果是:

<?xml version="1.0" encoding="UTF-8"?> 
<root> 
    <nodeLevel1> 
    <nodeType1>node type 1</nodeType1> 
    <nodeType3>node type 3</nodeType3> 
    <nodeType2> 
     <rank>1</rank> 
    </nodeType2> 
    <nodeType2> 
     <rank>2</rank> 
    </nodeType2> 
    <nodeType2> 
     <rank>3</rank> 
    </nodeType2> 
    <nodeType2> 
     <rank>4</rank> 
    </nodeType2> 
</nodeLevel1> 
</root> 

問題

<root> 
    <nodeLevel1> 
    <nodeType1>node type 1</nodeType1> 
    <nodeType2><rank>3</rank></nodeType2> 
    <nodeType2><rank>1</rank></nodeType2> 
    <nodeType2><rank>4</rank></nodeType2> 
    <nodeType2><rank>2</rank></nodeType2> 
    <nodeType3>node type 3</nodeType3> 
    </nodeLevel1> 
</root> 

我使用下面的XSLT排序,這個XML是所有的「nodeType2」在我的XML中都不在正確的位置。 如何在「nodeType2」之前保留節點「nodeType1」,並在「nodeType2」之後保留節點「nodeType3」。您的幫助

<?xml version="1.0" encoding="UTF-8"?> 
<root> 
    <nodeLevel1> 
    <nodeType1>node type 1</nodeType1> 
    <nodeType2> 
     <rank>1</rank> 
    </nodeType2> 
    <nodeType2> 
     <rank>2</rank> 
    </nodeType2> 
    <nodeType2> 
     <rank>3</rank> 
    </nodeType2> 
    <nodeType2> 
     <rank>4</rank> 
    </nodeType2> 
    <nodeType3>node type 3</nodeType3> 
</nodeLevel1> 
</root> 

感謝:(該解決方案不能使用元素名稱「nodeType1」或「nodeType3」,因爲它可以被重命名爲任何東西)

所以,結果是768,16。要做到這一點

回答

0

一種方法是有一個匹配的第一個nodeType2元素

<xsl:template match="nodeType2[1]"> 

之內,你選擇和排序的所有nodeType2元素模板

<xsl:for-each select="self::*|following-sibling::nodeType2"> 
    <xsl:sort select="rank" data-type="number" /> 
    <!-- Copy element --> 
    <xsl:call-template name="identity" /> 
</xsl:for-each> 

唯一的其他你需要的是另一個模板來阻止其他模塊nodeType2元素被輸出兩次

<xsl:template match="nodeType2" /> 

以下是完整的XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
     <xsl:output method="xml" version="1.0" encoding="UTF-8" omit-xml-declaration="no" indent="yes" media-type="text/html"/> 

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

     <xsl:template match="nodeType2[1]"> 
      <xsl:for-each select="self::*|following-sibling::nodeType2"> 
       <xsl:sort select="rank" data-type="number" /> 
       <xsl:call-template name="identity" /> 
      </xsl:for-each> 
     </xsl:template> 

     <xsl:template match="nodeType2" /> 
</xsl:stylesheet> 

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

<root> 
    <nodeLevel1> 
     <nodeType1>node type 1</nodeType1> 
     <nodeType2> 
     <rank>1</rank> 
     </nodeType2> 
     <nodeType2> 
     <rank>2</rank> 
     </nodeType2> 
     <nodeType2> 
     <rank>3</rank> 
     </nodeType2> 
     <nodeType2> 
     <rank>4</rank> 
     </nodeType2> 
     <nodeType3>node type 3</nodeType3> 
    </nodeLevel1> 
</root> 
0

這種轉變與任何元素名稱的工作(沒有名字被硬編碼),併爲因爲它使用鍵來識別組

<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:key name="kSameNamed" match="nodeLevel1/*" use= 
    "generate-id(preceding-sibling::*[not(name()=name(current()))][1])"/> 

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

<xsl:template match="nodeLevel1"> 
    <nodeLevel1> 
    <xsl:apply-templates select= 
    "*[not(name() = name(preceding-sibling::*[1]))]"/> 
    </nodeLevel1> 
</xsl:template> 

<xsl:template match="nodeLevel1/*"> 
    <xsl:for-each select="key('kSameNamed', generate-id(preceding-sibling::*[1]))"> 
    <xsl:sort select="rank" data-type="number"/> 
    <xsl:copy-of select="."/> 
    </xsl:for-each> 
</xsl:template> 
</xsl:stylesheet> 

當應用於提供的XML文檔:

<root> 
    <nodeLevel1> 
    <nodeType1>node type 1</nodeType1> 
    <nodeType2><rank>3</rank></nodeType2> 
    <nodeType2><rank>1</rank></nodeType2> 
    <nodeType2><rank>4</rank></nodeType2> 
    <nodeType2><rank>2</rank></nodeType2> 
    <nodeType3>node type 3</nodeType3> 
    </nodeLevel1> 
</root> 

想要的,正確的結果產生:

<root> 
    <nodeLevel1> 
     <nodeType1>node type 1</nodeType1> 
     <nodeType2> 
     <rank>1</rank> 
     </nodeType2> 
     <nodeType2> 
     <rank>2</rank> 
     </nodeType2> 
     <nodeType2> 
     <rank>3</rank> 
     </nodeType2> 
     <nodeType2> 
     <rank>4</rank> 
     </nodeType2> 
     <nodeType3>node type 3</nodeType3> 
    </nodeLevel1> 
</root> 

如果我們現在應用相同的變換到一個完全不同的XML文檔:

<r> 
    <nodeLevel1> 
    <X1>node type 1</X1> 
    <Y2><rank>3</rank></Y2> 
    <Y2><rank>1</rank></Y2> 
    <Y2><rank>4</rank></Y2> 
    <Y2><rank>2</rank></Y2> 
    <Z3>node type 3</Z3> 
    <A4><rank>8</rank></A4> 
    <A4><rank>2</rank></A4> 
    <A4><rank>9</rank></A4> 
    <A4><rank>3</rank></A4> 
    <B5><rank>8</rank></B5> 
    <B5><rank>2</rank></B5> 
    <B5><rank>9</rank></B5> 
    <B5><rank>3</rank></B5> 
    <C7>Node of Type C7</C7> 
    </nodeLevel1> 
</r> 

我們再次得到正確的結果:

<r> 
    <nodeLevel1> 
     <X1>node type 1</X1> 
     <Y2> 
     <rank>1</rank> 
     </Y2> 
     <Y2> 
     <rank>2</rank> 
     </Y2> 
     <Y2> 
     <rank>3</rank> 
     </Y2> 
     <Y2> 
     <rank>4</rank> 
     </Y2> 
     <Z3>node type 3</Z3> 
     <A4> 
     <rank>2</rank> 
     </A4> 
     <A4> 
     <rank>3</rank> 
     </A4> 
     <A4> 
     <rank>8</rank> 
     </A4> 
     <A4> 
     <rank>9</rank> 
     </A4> 
     <B5> 
     <rank>2</rank> 
     </B5> 
     <B5> 
     <rank>3</rank> 
     </B5> 
     <B5> 
     <rank>8</rank> 
     </B5> 
     <B5> 
     <rank>9</rank> 
     </B5> 
     <C7>Node of Type C7</C7> 
    </nodeLevel1> 
</r>