[xsl] how do you count based on the number of preceding attributes?

Subject: [xsl] how do you count based on the number of preceding attributes?
From: "Tony Zanella" <tony.zanella@xxxxxxxxx>
Date: Fri, 6 Jun 2008 15:43:31 -0400
Hello Everyone,

Using xsl processor: Saxon 8B, here's my test data:

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <div0 type="heading" id="abc.div.1.2.3">
        <div1 type="article" id="abc.div.1.2.6">
            <div2 type="subsection" id="abc.div.1.2.1"/>
            <pb n="1" id="abc.1.2.2"/>
            <div2 type="subsection" id="abc.div.1.2.64"/>
        </div1>
    </div0>
</root>

Here's the stylesheet I'm working on:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"; version="2.0">

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="*/@id[contains(.,'div')]">

        <xsl:variable name="substring"
select="substring-after(substring-after(substring-after(substring-after(.,'.'),'.'),'.'),'.')"/>
        <xsl:variable name="test_value"><xsl:value-of
select="count(preceding::node())"/></xsl:variable>
        <xsl:attribute name="id"
select="concat(replace(.,'([a-z]{3})\.div\.([0-9]+)\.([0-9]+)\.([0-9]+)','$1.div.$2.$3.'),$test_value)"/>


    </xsl:template>

</xsl:stylesheet>

What I want is to take all @id values (of any element) containing the
string 'div', keep everything but the last integer in
the string, and replace that last integer with the value of
$test_value. I want the value of $test_value to be, for example,
1 if the @id containing the string 'div' is the first @id, 2 if it is
the second, and so on. That way, when we get to <div0
type="heading" id="abc.div.1.2.3">, the count is 1 and the output will
be <div0 type="heading" id="abc.div.1.2.1">, when we
get to <div1 type="article" id="abc.div.1.2.6"> the count is 2, and
the output <div1 type="article" id="abc.div.1.2.2">, and
so on. When I run this transformation, I get this output:

<?xml version="1.0" encoding="UTF-8"?><root>
    <div0 type="heading" id="abc.div.1.2.1">
        <div1 type="article" id="abc.div.1.2.2">
            <div2 type="subsection" id="abc.div.1.2.3"/>
            <pb n="1" id="abc.1.2.2"/>
            <div2 type="subsection" id="abc.div.1.2.7"/>
        </div1>
    </div0>
</root>

I see that I'm getting a count, but not on the basis I want, since the
count function is returning its value based on the
number of preceding nodes of whatever type. I want it to return its
value based on the number of preceding id attributes
containing the string 'div'. Clearly the stylesheet doesn't work for
my purpose, but it's the closest I've been able to get.
I hope I've described my problem with enough clarity for your generous help!
Thanks,
Tony Zanella

Current Thread