Subject: Re: [xsl] Dealing without global counters From: Jeni Tennison <jeni@xxxxxxxxxxxxxxxx> Date: Wed, 12 Nov 2003 07:11:10 +0000 |
Hi Robert, > Output (this output is a javascript array for an expandable TOC) > db[1]=new dbRecord(chapter stuff) > db[2]=new dbRecord(first para stuff) > db[3]=new dbRecord(second para stuff) > db[4]=new dbRecord(third para stuff) > db[5]=new dbRecord(fourth para stuff) > db[6]=new dbRecord(first image stuff) > db[7]=new dbRecord(second image stuff) > db[8]=new dbRecord(first table stuff) > > What I want to do is output a chapter, all text in a chapter, then > all images for a chapter, and lastly all tables for a chapter. This > is done repetitively for each chapter. A simple-minded solution might be the following. You can calculate the number for a chapter using <xsl:number> with level="any" (counting elements at any level in the document) and with the count attribute matching those elements you're interested in counting: chapter, paras, tables and images. Once you've output the line for the chapter, you can go on to process its <para> children, then its <image> children, then its <table> children. When processing the <para> elements, you want to start counting from the number for the chapter; when processing the <image> elements, you want to start counting from the number for the chapter plus the number of <para> children the chapter has; similarly, when processing the <table> children, you want to start counting from the number for the chapter plus the number of <para> or <image> children the chapter has: <xsl:template match="chapter"> <xsl:variable name="number"> <xsl:number level="any" count="chapter | para | table | image" /> </xsl:variable> <xsl:value-of select="concat('db[', $number, ']=new dbRecord(chapter stuff)
')" /> <xsl:apply-templates select="para"> <xsl:with-param name="start" select="$number" /> </xsl:apply-templates> <xsl:apply-templates select="image"> <xsl:with-param name="start" select="$number + count(para)" /> </xsl:apply-templates> <xsl:apply-templates select="table"> <xsl:with-param name="start" select="$number + count(para | image)" /> </xsl:apply-templates> </xsl:template> When it comes to processing the <para>, <image> and <table> elements, the $start parameter gives you the starting number. The number for the <para>, <image> or <table> is this starting number plus the number for the particular <para>, <image> or <table>, which you can again get via the <xsl:number> instruction: <xsl:template match="para | image | table"> <xsl:param name="start" select="0" /> <xsl:variable name="number"><xsl:number /></xsl:variable> <xsl:value-of select="concat('db[', $start + $number, ']=new dbRecord(', name(), ' stuff)
')" /> </xsl:template> This approach isn't very efficient -- numbering with <xsl:number> seldom is, especially with level="any" -- but that might not be a problem for you. In XSLT 2.0, you can create a sequence that contains the elements that you want to process in the correct order, and then iterate over that sequence, using the position() function to provide the relevant numbers. The code would look something like: <xsl:variable name="elements" as="element()*"> <xsl:for-each select="chapter"> <xsl:sequence select="(., para, image, table)" /> </xsl:for-each> </xsl:variable> <xsl:for-each select="$elements"> <xsl:value-of select="concat('db[', xs:string(position()), ']=new dbRecord(', name(), ' stuff)
')" /> </xsl:for-each> Cheers, Jeni --- Jeni Tennison http://www.jenitennison.com/ XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
RE: [xsl] xsl:message usage in xsl, Michael Kay | Thread | Re: [xsl] Dealing without global co, M. David Peterson |
Re: [xsl] xsl:message usage in xsl, ARULRAJ | Date | Re: [xsl] Transforming problem, fstorr |
Month |