如何使用XSLT对RSS源进行分组

时间:2011-07-01 20:47:26

标签: xml xslt rss

我有一个XML文件,其中的数据通过互联网从供稿中读取。 XML是标准的RSS 2.0文件。它看起来像(我省略了一些标签来缩短帖子):

<?xml version="1.0" encoding="ISO-8859-1"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title/>
    <item>
      <title>Blah</title>
      <category>CAT1</category>
    </item>
    <item>
      <title>Blah2</title>
      <category>CAT2</category>
    </item>
    <item>
      <title>Blah3</title>
      <category>CAT1</category>
    </item>
  </channel>
</rss>

我要做的是使用XSLT创建HTML文件。我的问题是我需要按CATEGORY标签对项目进行分组。为了生成类似的东西:

<div>
  <span>CAT1</span>
  <div>
    <span>Blah</span>
    <span>Blah3</span>
  </div>
</div>
<div>
  <span>CAT2</span>
  <div>
    <span>Blah2</span>
  </div>
</div>

到目前为止,我发现了一些os帖子,教授如何使用XSLT通过使用属性进行分组(如thisthisthis)。但是,我所有的改编尝试都失败了。

TIA,

鲍勃

4 个答案:

答案 0 :(得分:2)

使用Muenchian分组方法可以简单地解决这个问题。这个样式表:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:key name="byCategory" match="item" use="category" />
    <xsl:template match="/">
        <html><xsl:apply-templates /></html>
    </xsl:template>
    <xsl:template
        match="item[generate-id()=generate-id(key('byCategory', category)[1])]">
        <div>
            <span><xsl:apply-templates select="category" /></span>
            <xsl:apply-templates select="key('byCategory', category)" 
                mode="out" />
        </div>
    </xsl:template>
    <xsl:template match="item"/>
    <xsl:template match="item" mode="out">
        <div><xsl:apply-templates select="title" /></div>
    </xsl:template>
</xsl:stylesheet>

应用于此输入:

<?xml version="1.0" encoding="ISO-8859-1"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/"
    xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title />
        <item>
            <title>Blah</title>
            <category>CAT1</category>
        </item>
        <item>
            <title>Blah2</title>
            <category>CAT2</category>
        </item>
        <item>
            <title>Blah3</title>
            <category>CAT1</category>
        </item>
    </channel>
</rss>

产地:

<html>
    <div>
        <span>CAT1</span>
        <div>Blah</div>
        <div>Blah3</div>
    </div>
    <div>
        <span>CAT2</span>
        <div>Blah2</div>
    </div>
</html>

答案 1 :(得分:1)

这应该让你入门

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

>
    <xsl:output method="html" indent="yes" omit-xml-declaration="yes"/>

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

    <xsl:template match="item[not(category = preceding-sibling::item/category)]">
        <xsl:variable name="category" select="category"/>
        <div>
            <span>
                <xsl:value-of select="category"/>
            </span>
            <div>
            <span>
                <xsl:value-of select="title"/>
            </span>
            <xsl:apply-templates select="following-sibling::item[category=$category]" mode="extra"/>
            </div>
        </div>
    </xsl:template>

    <xsl:template match="item" mode="extra">
        <span>
            <xsl:value-of select="title"/>
        </span>
    </xsl:template>
</xsl:stylesheet>

答案 2 :(得分:1)

如果您能够使用XSLT 2.0,则应该可以使用for-each-group对所有内容进行分组。

例如,使用您的示例XML输入,此XSLT 2.0样式表:

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

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

  <xsl:template match="rss">
    <html>
      <xsl:apply-templates/>
    </html>
  </xsl:template>

  <xsl:template match="channel">
      <xsl:for-each-group select="item" group-by="category">
        <xsl:variable name="catType" select="category"/>
        <div>
          <span>
            <xsl:value-of select="$catType"/>
          </span>
          <div>
            <xsl:apply-templates select="../item[category=$catType]/title"/>
          </div>
        </div>
      </xsl:for-each-group>
  </xsl:template>

  <xsl:template match="title">
    <span>
      <xsl:apply-templates/>
    </span>
  </xsl:template>

  <xsl:template match="category"/>

  <xsl:template match="item">
    <xsl:apply-templates/>
  </xsl:template>

</xsl:stylesheet>

产生以下输出:

<html>
   <div>
      <span>CAT1</span>
      <div>
         <span>Blah</span>
         <span>Blah3</span>
      </div>
   </div>
   <div>
      <span>CAT2</span>
      <div>
         <span>Blah2</span>
      </div>
   </div>
</html>

答案 3 :(得分:1)

使用xsl:for-each-group工具

XSLT 2.0

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:template match="/*/*">
        <xsl:for-each-group select="item" group-by="category">
            <div>
                <span>
                    <xsl:value-of select="category"/>
                </span>
                <div>
                    <xsl:apply-templates select="current-group()/title"/>
                </div>
            </div>
        </xsl:for-each-group>
    </xsl:template>

    <xsl:template match="title">
        <span>
            <xsl:value-of select="."/>
        </span>
    </xsl:template>

</xsl:stylesheet>