[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message]

Re: how do you count based on the number of preceding

Subject: Re: how do you count based on the number of preceding attributes?
From: "Tony Zanella" <tony.zanella@xxxxxxxxx>
Date: Fri, 6 Jun 2008 22:07:32 -0400
Re:  how do you count based on the number of preceding
Dear Dr. Kay and Readers,
Implementing the changes suggested below as follows, on this markup:

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <div0 type="heading" id="abc.div.1.2.3">
        <div1/><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"/>
        </div1>
    </div0>
</root>

With the sylesheet now reading:

<?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="test_value"
select="string(count(preceding::*[contains(@id, 'div')]))"/>
        <xsl:attribute name="id"  select="replace(., '[0-9]+$', $test_value)"/>
    </xsl:template>

</xsl:stylesheet>

I get the output:

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

The output I want is:
<?xml version="1.0" encoding="UTF-8"?><root>
    <div0 type="heading" id="abc.div.1.2.1">
        <div1/><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"/>
        </div1>
    </div0>
</root>

Any further suggestions?  (If it helps to hear: the test case
represents a file where the last integers in the div @id attributes
are misnumbered, and the goal of the stylesheet is to number them
sequentially...the pb element has an @id attribute, but it's not my
concern here...).
Thanks for your help and patience with my slow learning process,
Tony Zanella




On Fri, Jun 6, 2008 at 4:47 PM, Michael Kay <mike@xxxxxxxxxxxx> wrote:
>> 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:
>>
> [identity template]+
>>
>>     <xsl:template match="*/@id[contains(.,'div')]">
>
> The "*/" adds nothing (well, it says "only match id attributes if they have
> an element as a parent"). You can drop it.
>>
>>         <xsl:variable name="substring"
>> select="substring-after(substring-after(substring-after(substr
>> ing-after(.,'.'),'.'),'.'),'.')"/>
>
> You don't seem to use this variable and I don't think you need it.
>
>>         <xsl:variable name="test_value"><xsl:value-of
>> select="count(preceding::node())"/></xsl:variable>
>
> NEVER write variables like this. It should be
>
> <xsl:variable name="test_value" select="string(count(preceding::node()))"/>
>
> You don't want a document node containing a text node; you want the integer,
> converted to a string.
>
>> 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.
>
> You haven't made it clear whether you want to count all @id attributes, or
> only those that contain 'div'. In the first case it's
> count(preceding::*[@id]), in the second it's
> count(preceding::*[contains(@id, 'div')]).
>
> Alternatively, use <xsl:number level="any" count="*[@id]"/>
>
>>         <xsl:attribute name="id"
>> select="concat(replace(.,'([a-z]{3})\.div\.([0-9]+)\.([0-9]+)\
>> .([0-9]+)','$1.div.$2.$3.'),$test_value)"/>
>
> The seems very cumbersome. To replace the last number in the string, use
>
> replace(., '[0-9]+$', $test_value)
>
> Michael Kay
> http://www.saxonica.com/

Current Thread

PURCHASE STYLUS STUDIO ONLINE TODAY!

Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced!

Buy Stylus Studio Now

Download The World's Best XML IDE!

Accelerate XML development with our award-winning XML IDE - Download a free trial today!

Don't miss another message! Subscribe to this list today.
Email
First Name
Last Name
Company
Subscribe in XML format
RSS 2.0
Atom 0.3
Site Map | Privacy Policy | Terms of Use | Trademarks
Free Stylus Studio XML Training:
W3C Member
Stylus Studio® and DataDirect XQuery ™are products from DataDirect Technologies, is a registered trademark of Progress Software Corporation, in the U.S. and other countries. © 2004-2011 All Rights Reserved.