0

多くの同様の質問が寄せられていることは承知していますが、約 12 の優れた例を読みましたが、それらをすべて組み合わせて実用的なソリューションにすることはできませんでした。

次の構造の RSS フィードがあります。

<root>
    <pubDate>Tue, 03 Sep 2013 15:15:00 +0000</pubDate>
    <title>Title 1</title>
    <pubDate>Tue, 02 Mar 2013 15:15:00 +0000</pubDate>
    <title>Title 2</title>
    <pubDate>Tue, 02 Sep 2012 15:15:00 +0000</pubDate>
    <title>Title 3</title>
    ...
</root>

フィードにはいくつかの非常に大きなノードがあり、ページが読み込まれると非常に遅くなるため、平坦化されますtitleしたがって、それを取り込むときは、選択するデータをフィールドとフィールドのみに制限しpubDate、階層を削除します。(ここで他の提案はありますか?)

年ごとにグループ化されたデータを表示したい:

<year handle="2013">
    <date>Tue, 03 Sep 2013 15:15:00 +0000</date>
    <title>Title 1</title>
    <date>Tue, 02 Mar 2013 15:15:00 +0000</date>
    <title>Title 2</title>
</year>
<year handle="2012">
    <date>Tue, 02 Sep 2012 15:15:00 +0000</date>
    <title>Title 3</title>
    ...
</year>
...

で年を解析できます。次の方法substring-before(substring-after(substring-after(substring-after(pubDate, ' '), ' '), ' '), ' ')でキーを作成しようとしました。

<xsl:key name="years" match="/root/pubDate" use="substring-before(substring-after(substring-after(substring-after(/root/pubDate, ' '), ' '), ' '), ' ')" />

次に使用したもの:

<xsl:template match="root">
<rss>
    <xsl:apply-templates mode="year" select="pubDate[
      generate-id()
      =
      generate-id(key('years', substring-before(substring-after(substring-after(substring-after(/root/pubDate, ' '), ' '), ' '), ' '))[1])
    ]"/>
</rss>
</xsl:template>

<xsl:template match="root/pubDate" mode="year">
    <xsl:variable name="year" select="substring-before(substring-after(substring-after(substring-after(., ' '), ' '), ' '), ' ')"/>
    <year handle="{$year}">
         <xsl:apply-templates mode="final" select="key('years', $year)"/>
    </year>
</xsl:template>

<xsl:template match="root/pubDate" mode="final">
    <date>
        <xsl:value-of select="." />
    </date> 
    <title><xsl:value-of select="./following-sibling::*[1]" /></title>
</xsl:template>

しかし、私の出力は次のとおりです。

<year handle="2013">
    <date>Tue, 03 Sep 2013 15:15:00 +0000</date>
    <title>Title 1</title>
    <date>Tue, 02 Mar 2013 15:15:00 +0000</date>
    <title>Title 2</title>
    <date>Tue, 02 Sep 2012 15:15:00 +0000</date>
    <title>Title 3</title>
    ...
</year>

この問題の個々の部分を解決できるようですが、すべてを一緒に機能させることはできませんでした。RSS を年と月でグループ化する例はたくさんありますが、それは私の問題 (特にフラット化された RSS を考えると) とはまったく異なり、それらの例をエミュレートすることはできません。

PHP の libxslt に依存する Symphony CMS を使用しているため、XSLT / XPath 1.0 を使用しています。

どんな助けでも大歓迎です、読んでくれてありがとう。

4

2 に答える 2

0

/root/pubDate(正しい) 現在のノードの代わりに使用して、コードに 2 つの XPath の間違いがあります。この固定スタイルシートは、目的の出力を提供します。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:key name="years" match="/root/pubDate" use="substring-before(substring-after(substring-after(substring-after(., ' '), ' '), ' '), ' ')" />

  <xsl:template match="root">
    <rss>
      <xsl:apply-templates mode="year" select="pubDate[
        generate-id()
        =
        generate-id(key('years', substring-before(substring-after(substring-after(substring-after(., ' '), ' '), ' '), ' '))[1])
        ]"/>
    </rss>
  </xsl:template>

  <xsl:template match="root/pubDate" mode="year">
    <xsl:variable name="year" select="substring-before(substring-after(substring-after(substring-after(., ' '), ' '), ' '), ' ')"/>
    <year handle="{$year}">
      <xsl:apply-templates mode="final" select="key('years', $year)"/>
    </year>
  </xsl:template>

  <xsl:template match="root/pubDate" mode="final">
    <date>
      <xsl:value-of select="." />
    </date>
    <title><xsl:value-of select="./following-sibling::*[1]" /></title>
  </xsl:template>

</xsl:stylesheet>

より短いソリューションもあります。この場合、別のテンプレートを使用することは得策ではありません。コードが読みやすくならないためです (また、テンプレートの再利用性は必要ありません)。さらに、詳細を別の方法で解決します。次のコード、またはその一部を検討してください。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:key name="pubdates-by-year" match="/root/pubDate" use="substring-before(substring-after(substring-after(substring-after(., ' '), ' '), ' '), ' ')" />

  <xsl:template match="root">
    <rss>
      <xsl:for-each select="pubDate[count(. | key('pubdates-by-year', substring-before(substring-after(substring-after(substring-after(., ' '), ' '), ' '), ' '))[1]) = 1]">
        <xsl:variable name="year" select="substring-before(substring-after(substring-after(substring-after(., ' '), ' '), ' '), ' ')"/>
        <year handle="{$year}">
          <xsl:for-each select="key('pubdates-by-year', $year)">
            <xsl:copy-of select="."/>
            <xsl:copy-of select="following-sibling::title[1]"/>
          </xsl:for-each>
        </year>
      </xsl:for-each>
    </rss>
  </xsl:template>

</xsl:stylesheet>
于 2016-12-03T20:11:43.830 に答える