XSLT Сортировка подузлов - PullRequest
       17

XSLT Сортировка подузлов

1 голос
/ 22 января 2012

Извините за мой английский. Мне нужны узлы сортировки этих данных 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>

т.е. Мне нужно сначала отсортировать news-item элементов по pub-date в секции, а затем отсортировать section элемент по максимальной дате публикации в news-item. (Раздел с последними новостями должен быть сверху).

Большое спасибо!

Ответы [ 2 ]

2 голосов
/ 22 января 2012

Это ваш 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>

Имена в вашем каталоге не совпадают (newsitem против news-item, pubdate против pub-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>
0 голосов
/ 22 января 2012

Альтернативное, несколько более простое, двухпроходное решение (без 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>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...