我有一个XML文件(这是从实际中简化的):
<feeds xmlns...>
<feed>
<week>
<start-date>...</start-date>
<end-date>...</end-date>
<entry>
<data name="foo" value="bar"/>
<data name="path" value="/news/releases/2011-12-05/xyzzy"/>
<numeric name="bar" value="463284">
</entry>
<entry>
<data name="foo" value="baz"/>
<data name="path" value="/pages/ISOcodes/en-US"/>
<numeric name="bar" value="4332">
</entry>
<entry>
<data name="foo" value="bar"/>
<data name="path" value="/"/>
<numeric name="bar" value="23232">
</entry>
</week>
...
</feed>
...
</feeds>
每个week
都有很多entry
个;每个entry
只有两个data
个元素,一个包含name="foo"
,另一个包含name="path"
,另一个numeric
元素包含name="bar"
和{ {1}}一个整数。即使在value
内,也可能存在部分重复的entry
:week
s可以具有相同的entry
或相同的foo
,但没有两个path
{1}}在一周内具有相同的entry
和相同的foo
。
我想将path
分为几类。例如,我希望与正则表达式path
匹配的所有path
分别考虑(例如“ISO代码”)和匹配/ISOcodes/
作为单独类别的所有paths
( “新闻”)。
我正在尝试将^/news
value
bar
加到一个entry
中的多个week
中,按foo
和进行分组类型(如前一段所述)path
。也就是说,对于week
的每个value
,foo
的每个path
,sum()
的每个类别(如前一段所述),我希望value
bar
的{{1}}个。{/ p>
有办法做到这一点吗?怎么样?
答案 0 :(得分:3)
XSLT 2.0解决方案:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="week">
<xsl:for-each-group select="entry"
group-by="concat(data[@name='foo']/@value, '-',
if (matches(data[@name='path']/@value, '/ISOcodes/'))
then 'ISOcodes'
else if (matches(data[@name='path']/@value, '^/news'))
then 'news'
else 'no_category')">
[<xsl:value-of select="current-grouping-key()"/>]
<xsl:value-of select="sum(current-group()/numeric/@value)"/>
</xsl:for-each-group>
</xsl:template>
</xsl:stylesheet>
在以下输入中:
<feeds>
<feed>
<week>
<start-date>...</start-date>
<end-date>...</end-date>
<entry>
<data name="foo" value="bar"/>
<data name="path" value="/news/releases/2011-12-05/xyzzy"/>
<numeric name="bar" value="463284"/>
</entry>
<entry>
<data name="foo" value="baz"/>
<data name="path" value="/pages/ISOcodes/test"/>
<numeric name="bar" value="4332"/>
</entry>
<entry>
<data name="foo" value="baz"/>
<data name="path" value="/pages/ISOcodes/en-US"/>
<numeric name="bar" value="4332"/>
</entry>
<entry>
<data name="foo" value="baz"/>
<data name="path" value="/pages/ISOcodes/japan"/>
<numeric name="bar" value="4332"/>
</entry>
<entry>
<data name="foo" value="bar"/>
<data name="path" value="/"/>
<numeric name="bar" value="23232"/>
</entry>
</week>
</feed>
</feeds>
产地:
[bar-news]
463284
[baz-ISOcodes]
12996
[bar-no_category]
23232
显然,您需要格式化其他元素,但这应该展示分组方法。
答案 1 :(得分:3)
XSLT 2.0解决方案:
<xsl:template match="/">
<xsl:for-each select="//week">
<xsl:for-each-group select="entry" group-by="./data[@name = 'foo']/@value">
<xsl:for-each-group select="current-group()" group-by="data[@name = 'path']/@value">
<xsl:message>
<xsl:choose>
<xsl:when test="current-group()/data[@name = 'path' and matches(@value, '/ISOcodes/')]">
Sum of ISO codes : <xsl:value-of select="sum(current-group()/numeric/@value)"/>
</xsl:when>
<xsl:when test="current-group()/data[@name = 'path' and matches(@value, '^/news')]">
Sum of news : <xsl:value-of select="sum(current-group()/numeric/@value)"/>
</xsl:when>
<xsl:otherwise>
Sum of other categories : <xsl:value-of select="sum(current-group()/numeric/@value)"/>
</xsl:otherwise>
</xsl:choose>
</xsl:message>
</xsl:for-each-group>
</xsl:for-each-group>
</xsl:for-each>
</xsl:template>
应用于此.xml文件时:
<feeds>
<feed>
<week>
<start-date>...</start-date>
<end-date>...</end-date>
<entry>
<data name="foo" value="bar"/>
<data name="path" value="/news/releases/2011-12-05/xyzzy"/>
<numeric name="bar" value="463284"/>
</entry>
<entry>
<data name="foo" value="baz"/>
<data name="path" value="/pages/ISOcodes/en-US"/>
<numeric name="bar" value="4332"/>
</entry>
<entry>
<data name="foo" value="bar"/>
<data name="path" value="/"/>
<numeric name="bar" value="23232"/>
</entry>
</week>
...
</feed>
...
</feeds>
输出为:
[xslt] Sum of news : 463284
[xslt]
[xslt] Sum of other categories : 23232
[xslt]
[xslt] Sum of ISO codes : 4332
修改强>
我以为你想要总和?所以我的代码打印了总和:)
<xsl:template match="/">
<xsl:for-each select="//week">
<xsl:for-each-group select="entry" group-by="./data[@name = 'foo']/@value">
<xsl:variable name="foo" select="current-grouping-key()"/>
<xsl:for-each-group select="current-group()" group-by="data[@name = 'path']/@value">
<xsl:message>
<xsl:choose>
<xsl:when test="current-group()/data[@name = 'path' and matches(@value, '/ISOcodes/')]">
Sum of <xsl:value-of select="$foo"/>-<xsl:value-of select="current-grouping-key()"/> : <xsl:value-of select="sum(current-group()/numeric/@value)"/>
</xsl:when>
<xsl:when test="current-group()/data[@name = 'path' and matches(@value, '^/news')]">
Sum of <xsl:value-of select="$foo"/>-<xsl:value-of select="current-grouping-key()"/> : <xsl:value-of select="sum(current-group()/numeric/@value)"/>
</xsl:when>
<xsl:otherwise>
Sum of other categories : <xsl:value-of select="sum(current-group()/numeric/@value)"/>
</xsl:otherwise>
</xsl:choose>
</xsl:message>
</xsl:for-each-group>
</xsl:for-each-group>
</xsl:for-each>
</xsl:template>
这也打印了所有的铃声和口哨声:)