使用XSL按每个名称对元素进行排序

时间:2016-09-04 06:50:12

标签: xml sorting xslt

我想创建一个XSL样式表来转换xml,其中的元素按文本排序。

来源xml:

<package>
  <name>awesome-name</name>
  <version>1.0.6</version>
  <description>
    here is description
  </description>
  <maintainer email="foo@bar.com">Jon S.</maintainer>
  <maintainer email="aaa@bbb.com">George A.</maintainer>
  <license>BSD</license>
  <url>http://aaa.bbb.com/</url>
  <buildtool_depend>aaaaaaa</buildtool_depend>
  <!-- build depend -->
  <build_depend>aaaa</build_depend>
  <build_depend>dddd</build_depend>
  <build_depend>bbbb</build_depend>
  <build_depend>cccc</build_depend>
  <!-- run depend -->
  <run_depend>aaaa</run_depend>
  <run_depend>dddd</run_depend>
  <run_depend>cccc</run_depend>
  <run_depend>bbbb</run_depend>
  <export>
    <foo bar="aaa"></foo>
  </export>

  <!-- large
       footer
       comment -->
</package>

预期输出xml(*_depend按字母顺序排序,其他元素只是通过):

<package>
  <name>awesome-name</name>
  <version>1.0.6</version>
  <description>
    here is description
  </description>
  <maintainer email="foo@bar.com">Jon S.</maintainer>
  <maintainer email="aaa@bbb.com">George A.</maintainer>
  <license>BSD</license>
  <url>http://aaa.bbb.com/</url>
  <buildtool_depend>aaaaaaa</buildtool_depend>
  <!-- build depend -->
  <build_depend>aaaa</build_depend>
  <build_depend>bbbb</build_depend>
  <build_depend>cccc</build_depend>
  <build_depend>dddd</build_depend>
  <!-- run depend -->
  <run_depend>aaaa</run_depend>
  <run_depend>bbbb</run_depend>
  <run_depend>cccc</run_depend>
  <run_depend>dddd</run_depend>
  <export>
    <foo bar="aaa"></foo>
  </export>

  <!-- large
       footer
       comment -->
</package>

但输出是:

<package>
  <name>awesome-name</name>
  <version>1.0.6</version>
  <description>
    here is description
  </description>
  <maintainer email="foo@bar.com">Jon S.</maintainer>
  <maintainer email="aaa@bbb.com">George A.</maintainer>
  <license>BSD</license>
  <url>http://aaa.bbb.com/</url>
  <buildtool_depend>aaaaaaa</buildtool_depend>
  <build_depend>aaaa</build_depend>
  <build_depend>dddd</build_depend>
  <build_depend>bbbb</build_depend>
  <build_depend>cccc</build_depend>
  <run_depend>aaaa</run_depend>
  <run_depend>dddd</run_depend>
  <run_depend>cccc</run_depend>
  <run_depend>bbbb</run_depend>
  <export>
    <foo/>
  </export>
</package>

此处,注释已删除,导出的内部元素(foo)未正确传递。

我创建的XSL样式表如下:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">                                     
  <xsl:preserve-space elements="description export"/>                                                               
  <xsl:template match="*">                                                                                          
    <xsl:element name="{name()}">                                                                                   
      <xsl:apply-templates select="node()|@*" />                                                                    
    </xsl:element>                                                                                                  
  </xsl:template>                                                                                                   

  <xsl:template match="@*|comment()">                                                                               
    <xsl:copy-of select="." />                                                                                      
  </xsl:template>                                                                                                   

  <xsl:template match="/package">                                                                                   
    <xsl:copy>                                                                                                      
      <xsl:copy-of select="*[self::name]" />                                                                        
      <xsl:copy-of select="*[self::version]" />                                                                     
      <xsl:copy-of select="*[self::description]" />                                                                 
      <xsl:copy-of select="*[self::maintainer]" />                                                                  
      <xsl:copy-of select="*[self::license]" />                                                                     
      <xsl:copy-of select="*[self::url]" />                                                                         
      <xsl:copy-of select="*[self::author]" />                                                                      
      <xsl:copy-of select="*[self::buildtool_depend]" />                                                            
      <xsl:copy-of select="*[self::buildtool_export_depend]" />                                                     
      <xsl:for-each select="build_depend">                                                                          
        <xsl:sort data-type="string" />                                                                             
        <xsl:copy-of select="." />                                                                                  
      </xsl:for-each>                                                                                               
      <xsl:for-each select="run_depend" >                                                                           
        <xsl:sort data-type="string" />                                                                             
        <xsl:copy-of select="." />                                                                                  
      </xsl:for-each>                                                                                               
      <xsl:for-each select="exec_depend" >                                                                          
        <xsl:sort data-type="string" />                                                                             
        <xsl:copy-of select="." />                                                                                  
      </xsl:for-each>                                                                                               
      <xsl:for-each select="test_depend">                                                                           
        <xsl:sort data-type="string" />                                                                             
        <xsl:copy-of select="." />                                                                                  
      </xsl:for-each>                                                                                               
      <xsl:for-each select="doc_depend">                                                                            
        <xsl:sort data-type="string" />                                                                             
        <xsl:copy-of select="." />                                                                                  
      </xsl:for-each>                                                                                               
      <xsl:for-each select="conflict">                                                                              
        <xsl:sort data-type="string" />                                                                             
        <xsl:copy-of select="." />                                                                                  
      </xsl:for-each>                                                                                               
      <xsl:for-each select="replace">                                                                               
        <xsl:sort data-type="string" />                                                                             
        <xsl:copy-of select="." />                                                                                  
      </xsl:for-each>                                                                                               
      <xsl:copy-of select="*[self::export]" />                                                                      
    </xsl:copy>                                                                                                     
  </xsl:template>                                                                                                   
</xsl:stylesheet>

我的样式表或更好的解决方案有什么问题?

1 个答案:

答案 0 :(得分:0)

这是你可以看到它的一种方式:

XSLT 1.0

<div class="gallery__wrapper">
 <div class="image-main__wrapper">
 <img class="image-main" src="https://unsplash.it/g/1000/400?image=0">
    <div id="arrows">
      <i class='material-icons left-btn'>chevron_left</i>
      <i class='material-icons right-btn'>chevron_right</i>
    </div>
    <div class="image-thumbnails__wrapper">
      <ul class="thumbnails">
        <li><img id="thumb-1" class="gallery__img" src="https://unsplash.it/g/150/100?image=1"></li>
        <li><img id="thumb-2" class="gallery__img" src="https://unsplash.it/g/150/100?image=2"></li>
        <li><img id="thumb-3" class="gallery__img" src="https://unsplash.it/g/150/100?image=3"></li>
        <li><img id="thumb-4" class="gallery__img" src="https://unsplash.it/g/150/100?image=4"></li>
        <li><img id="thumb-5" class="gallery__img" src="https://unsplash.it/g/150/100?image=5"></li>
        <li><img id="thumb-6" class="gallery__img" src="https://unsplash.it/g/150/100?image=6"></li>
        <li><img id="thumb-7" class="gallery__img" src="https://unsplash.it/g/150/100?image=7"></li>
        <li><img id="thumb-8" class="gallery__img" src="https://unsplash.it/g/150/100?image=8"></li>
      </ul>
    </div>
  </div>
</div>

然而,这仍然相当尴尬,必须列出所有可能的元素名称。请考虑改为Muenchian grouping

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

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

<xsl:template match="/package">
    <xsl:copy>  
        <xsl:apply-templates select="node()[not(contains(name(), '_depend'))] 
                                   | buildtool_depend[1]
                                   | build_depend[1] 
                                   | run_depend[1]"/>       
    </xsl:copy>
</xsl:template>

<xsl:template match="*[contains(name(), '_depend')]">
    <xsl:for-each select="../*[name()=name(current())]" >                                                                           
        <xsl:sort/>                                                                             
        <xsl:copy-of select="." />                                                                                  
    </xsl:for-each>
</xsl:template>


</xsl:stylesheet>