Elements to count

Previous examples have implicitly counted occurrences of the current element, using the sibling elements as context. However, it is possible to override this simple behaviour in various ways: only counting the element under certain conditions, adding other elements into the count, or separately counting other elements.

Selective counting

The Count attribute is used in the Number element to control counting. When this attribute is given a value that matches the current element name, this is equivalent to not including the attribute at all. The two examples below are therefore equivalent:

<xsl:template match="item">
  <P><xsl:number/>...</P>
</xsl:template>

<xsl:template match="item">
  <P><xsl:number count="item"/>...</P>
</xsl:template>

But the Count attribute actually contains an XPath pattern, not necessarily just an element name. For example, it would be possible to ignore Item elements that have a Status attribute set to 'ignore':

   <list>
     <item>first</item>
     <item status="ignore">ignore this</item>
     <item>third</item>
   </list>


count="item[not(@status='ignore')]"/>


   <DIV>
     <P>1) first</P>
     <P>ignore this</P>
     <P>2) third</P>
   </DIV>

Including other elements

Because the value of the Count attribute is a pattern, the '|' symbol can be used to include other element names. For now, it will be assumed that the current element matches one of the elements named in the pattern (though this need not be the case). In this scenario, the other element or elements named are included in the count of previous siblings. For example, a step in the procedure that has been removed, but must continue to occupy a place in the sequence, could be represented by a Deleted element. The presence of Deleted elements could then be explicitly included in the calculation for the value of each Item element, by including a Count attribute with values of both 'step' and 'deleted':

<xsl:template match="step">
  <P><xsl:number count="step|deleted"/>...</P>
</xsl:template>

In the following example, as each Step element is processed, all previous Step and Deleted elements are included in the count:

<procedure>
  <title>Getting Through an Unlocked Door</title>
  <step>walk to the door</step>
  <deleted/>
						<deleted/>
  <step>turn the handle</step>
  <step>push</step>
</procedure>


   <P>1) walk to the door</P>
   <P>DELETED ITEM</P>
   <P>DELETED ITEM</P>
   <P>4) turn the handle</P>
   <P>5) push</P>

Taking this example further, it is possible to include the same counter within the template for deleted items, thus recreating the full numbered list:

<xsl:template match="deleted">
  <P><xsl:number count="step|deleted"/>) DELETED ITEM</P>
</xsl:template>


   <P>1) walk to the door</P>
   <P>2) DELETED ITEM</P>
   <P>3) DELETED ITEM</P>
   <P>4) turn the handle</P>
   <P>5) push</P>

Using the value '*', it is possible to include all previous sibling elements in the count without having to list all their possible names.

Note that when counting elements that share the same parent element, as these examples all do, the current element name must be included in the list of elements to count. It is not possible to count only other elements. If the current element type is omitted, this is considered significant and triggers the feature described next.

Counting ancestor elements

It is possible to count occurrences of an ancestor element. One obvious need for this capability is to add a number to the title of each section of a document (such as the numbered chapter titles in this book). Although it is the Title element that is being processed and styled, it is the Section elements that precede (and finally enclose) the Title element that need to be counted. This can be achieved simply by inserting the name of the ancestor element into the Count attribute, in place of the name of the current element. When an XSLT processor analyzes the Count attribute value, it first establishes whether or not the name of the current element appears as a valid match in the pattern. If it does not, then the elements containing the current element are each analyzed until one is found that matches. The counting process then works at that level, generating a value that represents the number of previous siblings in the usual way. In the following example, there are two previous sections, and one enclosing section, so the value for the Title element is '3':

   <book>
     <section>...</section>
						<section>...</section>
						<section><title>Section Three</title>
       ...
     </section>
   </book>


<xsl:template match="title">
  <H1><xsl:number count="section"/>) <apply-templates/>
  </H1>
</xsl:template>


   <H1>3) Section Three</H1>

Note that the first match, working up the ancestor list from the current element, is the one that is used. If the three sections shown were all enclosed within another, outer section, the outer Section element would be ignored:

<book>
  <section>  <!-- IGNORE THIS ENCLOSING SECTION -->
    <section>...</section>
    <section>...</section>
    <section>
      <title>Section Three</title>
      ...
    </section>
  </section>
</book>

The number of levels searched up the ancestor list can be constrained using the From attribute. This attribute holds a pattern, naming the element or elements beyond which searching should not continue. For example, a Part element could be specified, preventing an enclosing section from being selected:

<number count="section" from="part" />


   <book>
     <section>
       <part> <!-- prevents access to Section -->
         <title>

It is difficult to envisage a scenario where this is actually useful. The nearest named element is selected, and so the only outcome of effective use of the From element would be an unsuccessful search. However, this attribute has a more significant purpose in other circumstances.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset