我有一个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通过使用属性进行分组(如this,this和this)。但是,我所有的改编尝试都失败了。
TIA,
鲍勃
答案 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>