I have an XML file with thousands of prisons like this:
<bases xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<marker>
<name>United States Penitentiary, Canaan</name>
<adr>Canaan</adr>
<state>Pennsylvania</state>
<geo>41.562778, -75.421389</geo>
<tag>Federal</tag>
<wiki>United_States_Penitentiary,_Canaan</wiki>
</marker>
<marker>
<name>Mohawk Correctional Facility</name>
<adr>Rome</adr>
<state>New York</state>
<geo>43.184511, -75.483992</geo>
<tag>State</tag>
<wiki>Mohawk_Correctional_Facility</wiki>
</marker>
...
</bases>
I want to produce counts of the number of prisons whose <tag> is "Federal". I need to produce totals for eight values. I'm using an XSLT v1.0 processor (xmlstarlet) and I'm new to count().
I have so many examples of XSL that haven't worked, I'm not sure which to include here. (I've been at this for hours.) Here's one that doesn't work:
<xsl:template match="/bases/marker[tag='Federal']">
TOTAL = <xsl:value-of select="count(.)"/>
</xsl:template>
Help, please.
Here's the solution from Sebastien that solves the count() problem:
<xsl:template match="/">
TOTAL = <xsl:value-of select="count(//bases/marker[tag='Federal']) "/>
</xsl:template>
But I have multiple values of <tag> to process, and this doesn't work - States is equal to zero when there are hundreds:
<xsl:template match="/">
Federal = <xsl:value-of select="count(//bases/marker[tag='Federal']) "/>
State = <xsl:value-of select="count(//bases/marker[tag='Statel']) "/>
</xsl:template>
Here's an example of Muenchian grouping in XSLT 1.0 to go along with the link in the comments.
Input (added another marker
to show proper counting of State
)
<bases xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<marker>
<name>United States Penitentiary, Canaan</name>
<adr>Canaan</adr>
<state>Pennsylvania</state>
<geo>41.562778, -75.421389</geo>
<tag>Federal</tag>
<wiki>United_States_Penitentiary,_Canaan</wiki>
</marker>
<marker>
<name>Mohawk Correctional Facility</name>
<adr>Rome</adr>
<state>New York</state>
<geo>43.184511, -75.483992</geo>
<tag>State</tag>
<wiki>Mohawk_Correctional_Facility</wiki>
</marker>
<marker>
<name>Casa Bonita</name>
<adr>Lakewood</adr>
<state>CO</state>
<geo>39.741927, -105.070828</geo>
<tag>State</tag>
<wiki>Casa_Bonita</wiki>
</marker>
</bases>
XSLT 1.0
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:strip-space elements="*"/>
<xsl:key name="marker_by_tag" match="marker" use="tag"/>
<xsl:template match="/*">
<xsl:for-each select="marker[count(.|key('marker_by_tag',tag)[1])=1]">
<xsl:value-of select="concat(tag,' = ',count(key('marker_by_tag',tag)),'
')"/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Output
Federal = 1
State = 2