I have an XML file with (this is simplified from actual):
<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>
Each week has many entrys; each entry has just two data elements, one with name="foo" and the other with name="path", and a single numeric element with name="bar" and value an integer. There can be partial-duplicate entrys, even within a week: entrys can have the same foo or the same path, but no two entrys within a week that have the same foo and the same path.
I'd like to separate my paths into categories. For example, I want all paths matching the regex /ISOcodes/ to be considered separately (as "ISOcodes", say) and all paths matching ^/news as a separate category ("news").
I'm trying to sum the value of bar across multiple entrys within a single week, grouping by foo and by type (as in previous paragraph) of path. That is, for each week, for each value of foo, for each category of path (as in the preceding paragraph), I want the sum() of the values of bar.
Is there a way to do this? How?
An XSLT 2.0 solution:
<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>
On the following input:
<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>
Produces:
[bar-news]
463284
[baz-ISOcodes]
12996
[bar-no_category]
23232
Obviously, you'll need to format additional elements to taste, but this should demonstrate the grouping method.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With