XSLT排序子节点

时间:2012-01-22 12:54:59

标签: xml xslt sorting xpath

抱歉我的英文。 我需要这个XML数据的排序节点

<root>
  <section id="1">
    <news-item id="1" pub-date="2012-01-03" />
    <news-item id="2" pub-date="2012-01-04" />
    <news-item id="3" pub-date="2011-12-21" />
  </section>

  <section id="2">
    <news-item id="4" pub-date="2012-01-05" />
    <news-item id="5" pub-date="2012-01-06" />
    <news-item id="6" pub-date="2012-01-07" />
  </section>

  <section id="3">
    <news-item id="7" pub-date="2012-02-10" />
    <news-item id="8" pub-date="2012-02-11" />
    <news-item id="9" pub-date="2012-02-12" />
  </section>
</root>

到这个

<root>
  <section id="3">
    <news-item id="9" pub-date="2012-02-12" />
    <news-item id="8" pub-date="2012-02-11" />
    <news-item id="7" pub-date="2012-02-10" />
  </section>

  <section id="2">
    <news-item id="6" pub-date="2012-01-07" />
    <news-item id="5" pub-date="2012-01-06" />
    <news-item id="4" pub-date="2012-01-05" />
  </section>

  <section id="1">
    <news-item id="2" pub-date="2012-01-04" />
    <news-item id="1" pub-date="2012-01-03" />
    <news-item id="3" pub-date="2011-12-21" />
  </section>
</root>

即。我需要首先按 pub-date pub-date 中对新闻项元素进行排序,然后按新闻项中的max pub-date对 section 元素进行排序。 (带有lastes新闻的部分必须在顶部)。

非常感谢!

2 个答案:

答案 0 :(得分:2)

这是您的pastebin,其名称已修复且各部分的排序不同:

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

<xsl:template match="section">
    <xsl:copy>
        <xsl:apply-templates select="@*"/>
        <xsl:apply-templates select="news-item">
            <xsl:sort select="@pub-date" data-type="text" order="descending" />
        </xsl:apply-templates>
    </xsl:copy>
</xsl:template>

<xsl:template match="root">
    <xsl:copy>
        <xsl:apply-templates select="@*"/>
        <xsl:variable name="sectionOrder">
            <xsl:text>|</xsl:text>
            <xsl:for-each select="section/news-item">
                <xsl:sort select="@pub-date" data-type="text" order="descending" />
                <xsl:value-of select="generate-id(..)"/>
                <xsl:text>|</xsl:text>
            </xsl:for-each>
        </xsl:variable>
        <xsl:apply-templates select="section">
            <xsl:sort select="string-length(substring-before($sectionOrder, concat('|',generate-id(),'|')))" data-type="number" />
        </xsl:apply-templates>
    </xsl:copy>
</xsl:template>

您的pastebin中的名称不匹配(newsitemnews-itempubdatepub-date),因此我修复了该问题。我得到的输出似乎是正确的(也是你在评论中添加的测试用例):

<root>
    <section id="2">
        <news-item id="7" pub-date="2222-12-22" />
        <news-item id="6" pub-date="2012-01-07" />
        <news-item id="5" pub-date="2012-01-06" />
        <news-item id="4" pub-date="2012-01-05" />
    </section>
    <section id="3">
        <news-item id="10" pub-date="2012-02-12" />
        <news-item id="9" pub-date="2012-02-11" />
        <news-item id="8" pub-date="2012-02-10" />
    </section>
    <section id="1">
        <news-item id="2" pub-date="2012-01-04" />
        <news-item id="1" pub-date="2012-01-03" />
        <news-item id="3" pub-date="2011-12-21" />
    </section>
</root>

答案 1 :(得分:0)

另一种更简单的2遍解决方案(无xsl:variable,无generate-id(),无管道分隔值,但使用msxsl:node-set()

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:msxsl="urn:schemas-microsoft-com:xslt"
 exclude-result-prefixes="msxsl">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:variable name="vrtfPass1">
  <xsl:apply-templates mode="pass1"/>
 </xsl:variable>

 <xsl:template match="/*">
  <root>
   <xsl:for-each select=
   "msxsl:node-set($vrtfPass1)/*/*">
     <xsl:sort select="*[1]/@pub-date" order="descending"/>
       <xsl:copy-of select="."/>
   </xsl:for-each>
  </root>
 </xsl:template>

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

 <xsl:template match="section" mode="pass1">
  <section id="{@id}">
   <xsl:apply-templates select="*" mode="pass1">
    <xsl:sort select="@pub-date" order="descending"/>
   </xsl:apply-templates>
  </section>
 </xsl:template>
</xsl:stylesheet>

应用于以下XML文档(基于提供的,但更加“有趣”):

<root>
    <section id="1">
        <news-item id="1" pub-date="2012-01-03" />
        <news-item id="2" pub-date="2012-01-04" />
        <news-item id="3" pub-date="2011-12-21" />
    </section>
    <section id="2">
        <news-item id="4" pub-date="2012-01-05" />
        <news-item id="5" pub-date="2012-01-06" />
        <news-item id="6" pub-date="2012-01-07" />
        <news-item id="7" pub-date="2222-12-22" />
    </section>
    <section id="3">
        <news-item id="7" pub-date="2012-02-10" />
        <news-item id="8" pub-date="2012-02-11" />
        <news-item id="9" pub-date="2012-02-12" />
    </section>
</root>

产生了想要的正确结果

<root>
   <root>
      <section id="2">
         <news-item id="7" pub-date="2222-12-22"/>
         <news-item id="6" pub-date="2012-01-07"/>
         <news-item id="5" pub-date="2012-01-06"/>
         <news-item id="4" pub-date="2012-01-05"/>
      </section>
      <section id="3">
         <news-item id="9" pub-date="2012-02-12"/>
         <news-item id="8" pub-date="2012-02-11"/>
         <news-item id="7" pub-date="2012-02-10"/>
      </section>
      <section id="1">
         <news-item id="2" pub-date="2012-01-04"/>
         <news-item id="1" pub-date="2012-01-03"/>
         <news-item id="3" pub-date="2011-12-21"/>
      </section>
   </root>
</root>