Re: [xsl] XSL counting node by inheritable attribute

Subject: Re: [xsl] XSL counting node by inheritable attribute
From: Michael Kay <mike@xxxxxxxxxxxx>
Date: Wed, 17 Nov 2010 09:07:08 +0000
You can use (ancestor-or-self::*/@type)[last()] to access the innermost attribute named @type on this element or a containing element.

Michael Kay
Saxonica


On 17/11/2010 05:01, paavali muurahainen wrote:
Hello,

I'm creating an XSL transformation to show my XML file in a web
browser. I want to view the data, and then finally create a matrix
that calculates number of nodes matching certain criteria. The problem
is, that the criteria can be inherited. I'm using XSLT 1.0 due to
browsers not often supporting anything else.

The XML document I have looks like this (the static items):
<root>
   <level1 feature="XXX">
      <level2>
         <level3/>
      </level2>
   </level1>
</root>

Now, all level-nodes can have an attribute called type. The attribute
is inherited and can be overridden, which is the root cause of my
current problem when I want to create the matrix. The matrix, ie. a
table, would contain columns for all different types found, and rows
for features, and the value of each cell would be the number of level3
items that match the type and feature of that particular cell.

After giving this a long thought I've come up with two solutions:
1) Loop over the list of features, and inside it the list of types,
and create a very complex math operation counting the items
2) Somehow set the attribute type for each level3 item so that I could
just write<xsl:value-of
select="count(level1[@feature='XXX']/level2/level3[@type='YYY'])"/>

The option 1 is something I know how to do but don't want to because
of the number of different scenarios that should be included and
excluded.

The XSL structure now goes like this:
<xsl:stylesheet>
   <xsl:template match="/">
     <here some general HTML output>
     <xsl:apply-templates />
     <xsl:call-template name="matrix"/>
   </xsl:template>

   <xsl:template match="level1">
     <again, HTML>
     <xsl:for-each select="level2">
       <xsl:apply-templates select="."/>
     </xsl:for-each>
  </xsl:template>

   <xsl:template match="level2">
     <again, HTML>
     <xsl:for-each select="level3">
       <xsl:apply-templates select="."/>
     </xsl:for-each>
  </xsl:template>

   <xsl:template match="level3">
     <again, HTML>
  </xsl:template>

  <xsl:template name="matrix">
    <here I want to create the matrix>
  </xsl:template>
</xsl:stylesheet>

How could I achieve option number 2, ie. setting the type attribute
for all level3 items?

BR,
Paavali

Current Thread