473,322 Members | 1,614 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,322 software developers and data experts.

xsl -- using math in element subscripts?

I am writing an XSL transform that converts XML data about vehicles
into XML data that will fill printed forms.

The default form can handle up to 5 vehicles which I handle using
subscripts...

<xsl:for-each select="VEHICLE[1]">
<!-- spit out some stuff about this vehicle -->
</xsl:for-each>
<xsl:for-each select="VEHICLE[2]">
<!-- spit out some stuff about this vehicle -->
</xsl:for-each>
<xsl:for-each select="VEHICLE[3]">
<!-- spit out some stuff about this vehicle -->
</xsl:for-each>
<xsl:for-each select="VEHICLE[4]">
<!-- spit out some stuff about this vehicle -->
</xsl:for-each>
<xsl:for-each select="VEHICLE[5]">
<!-- spit out some stuff about this vehicle -->
</xsl:for-each>

Then, if there are more than 5 vehicles, I need to output them, 5 at a
time, onto one or more "extension" forms as needed. Note that the
extra vehicles will not always be in multiples of 5.

I'm at a loss as to how to handle this in a generic way without
hardcoding conditional forms for every multiple of 5 up to some
arbitrary maximum.

I'm thinking that to handle it generically, I'd need to do something
tricky with math in the subscripts possibly using the mod operator but
I'm not sure if that's even possible.

Has anyone dealt with a similar problem?

I can post more detailed examples if my description isn't clear. Just
ask.

Aug 21 '06 #1
10 1883
William Krick wrote:
I am writing an XSL transform that converts XML data about vehicles
into XML data that will fill printed forms.

The default form can handle up to 5 vehicles which I handle using
subscripts...

<xsl:for-each select="VEHICLE[1]">
<!-- spit out some stuff about this vehicle -->
</xsl:for-each>
....

Yes, copy and paste is not the best solution...
Then, if there are more than 5 vehicles, I need to output them, 5 at a
time, onto one or more "extension" forms as needed. Note that the
extra vehicles will not always be in multiples of 5.

I'm at a loss as to how to handle this in a generic way without
hardcoding conditional forms for every multiple of 5 up to some
arbitrary maximum.

I'm thinking that to handle it generically, I'd need to do something
tricky with math in the subscripts possibly using the mod operator but
I'm not sure if that's even possible.
You are right.

I fooled around with it a little. You can use this (I hope) as a template:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">

<xsl:template match="cars">
<report>
<xsl:apply-templates select="car[(position()-1) mod 5 = 0]"/>
</report>
</xsl:template>

<xsl:template match="car[1]">
<first-page>
<xsl:apply-templates select=". | following-sibling::car[position()
&lt; 5]" mode="info"/>
</first-page>
</xsl:template>

<xsl:template match="car[(position()-1)!=0]">
<extra-page>
<xsl:apply-templates select=". | following-sibling::car[position()
&lt; 5]" mode="info"/>
</extra-page>
</xsl:template>

<xsl:template match="car" mode="info">
<carinfo car="{@id}"/>
</xsl:template>

</xsl:stylesheet>
With the input

<cars>
<car id="1"/>
<car id="2"/>
<car id="3"/>
<car id="4"/>
<car id="5"/>
<car id="6"/>
<car id="7"/>
<car id="8"/>
<car id="9"/>
<car id="10"/>
<car id="11"/>
</cars>

you get (after formatting)

[dongfang@skodspand tmp]$ xsltproc car.xsl car.xml | xmllint --format -
<?xml version="1.0"?>
<report>
<first-page>
<carinfo car="1"/>
<carinfo car="2"/>
<carinfo car="3"/>
<carinfo car="4"/>
<carinfo car="5"/>
</first-page>
<extra-page>
<carinfo car="6"/>
<carinfo car="7"/>
<carinfo car="8"/>
<carinfo car="9"/>
<carinfo car="10"/>
</extra-page>
<extra-page>
<carinfo car="11"/>
</extra-page>
</report>
Hope that helped ;)

(you can experiment it yourself to see how it works. This was just to
get you started)

Søren
Aug 21 '06 #2
Soren Kuula wrote:
William Krick wrote:
I am writing an XSL transform that converts XML data about vehicles
into XML data that will fill printed forms.

I fooled around with it a little. You can use this (I hope) as a template:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">

<xsl:template match="cars">
<report>
<xsl:apply-templates select="car[(position()-1) mod 5 = 0]"/>
</report>
</xsl:template>

<xsl:template match="car[1]">
<first-page>
<xsl:apply-templates select=". | following-sibling::car[position()
&lt; 5]" mode="info"/>
</first-page>
</xsl:template>

<xsl:template match="car[(position()-1)!=0]">
<extra-page>
<xsl:apply-templates select=". | following-sibling::car[position()
&lt; 5]" mode="info"/>
</extra-page>
</xsl:template>

<xsl:template match="car" mode="info">
<carinfo car="{@id}"/>
</xsl:template>

</xsl:stylesheet>
Well, it does seem to work but I'm not sure I understand how.

I don't understand the syntax.

<xsl:apply-templates select="car[(position()-1) mod 5 = 0]"/>

How does "(position()-1) mod 5 = 0" evaluate to a subscript?
It seems like it would evaluate to true/false.

<xsl:apply-templates select=". | following-sibling::car[position() &lt;
5]" mode="info"/>

Then I don't understand what ". |" means. I assume it means: "the
current node boolean OR the thing that follows it".

Regardless, it *does* seem to work. The only issue now is that the
first vehicle in each "page" has to be treated slightly different
because of the morons who created the original XML spec I'm trying to
meet. On each page, there are "year" and "age group" fields for the
vehicles. Notice that the name of the age group on the first vehicle
isn't "AGE GROUP #001" as you'd expect. It's simply "AGE GROUP".
Here's some sample XML output that is very close to the output I'm
generating (with a lot of stuff omitted for brevity). This example has
12 cars...

<FORM>
<FIRST-PAGE>
<FIELD NAME="YEAR #001">1991</FIELD>
<FIELD NAME="AGE GROUP">5</FIELD>
<FIELD NAME="YEAR #002">2007</FIELD>
<FIELD NAME="AGE GROUP #002">3</FIELD>
<FIELD NAME="YEAR #003">1997</FIELD>
<FIELD NAME="AGE GROUP #003">2</FIELD>
<FIELD NAME="YEAR #004">2001</FIELD>
<FIELD NAME="AGE GROUP #004">8</FIELD>
<FIELD NAME="YEAR #005">2003</FIELD>
<FIELD NAME="AGE GROUP #005">6</FIELD>
</FIRST-PAGE>
<EXTRA-PAGE>
<FIELD NAME="COVERED AUTO #01A">6</FIELD>
<FIELD NAME="YEAR #001">1992</FIELD>
<FIELD NAME="AGE GROUP">5</FIELD>
<FIELD NAME="COVERED AUTO #02A">7</FIELD>
<FIELD NAME="YEAR #002">2008</FIELD>
<FIELD NAME="AGE GROUP #002">3</FIELD>
<FIELD NAME="COVERED AUTO #03A">8</FIELD>
<FIELD NAME="YEAR #003">1996</FIELD>
<FIELD NAME="AGE GROUP #003">2</FIELD>
<FIELD NAME="COVERED AUTO #04A">9</FIELD>
<FIELD NAME="YEAR #004">2002</FIELD>
<FIELD NAME="AGE GROUP #004">8</FIELD>
<FIELD NAME="COVERED AUTO #05A">10</FIELD>
<FIELD NAME="YEAR #005">2004</FIELD>
<FIELD NAME="AGE GROUP #005">6</FIELD>
</EXTRA-PAGE>
<EXTRA-PAGE>
<FIELD NAME="COVERED AUTO #01A">11</FIELD>
<FIELD NAME="YEAR #001">1993</FIELD>
<FIELD NAME="AGE GROUP">5</FIELD>
<FIELD NAME="COVERED AUTO #02A">12</FIELD>
<FIELD NAME="YEAR #002">1999</FIELD>
<FIELD NAME="AGE GROUP #002">3</FIELD>
</EXTRA-PAGE>
</FORM>

....the AGE GROUP field is the only one that is different. All the rest
have the correct numbers in their name. Note that the number is the
position of the vehicle on the page, not it's position in the original
XML document.

Aug 22 '06 #3
William Krick wrote:
Well, it does seem to work but I'm not sure I understand how.

I don't understand the syntax.

<xsl:apply-templates select="car[(position()-1) mod 5 = 0]"/>

How does "(position()-1) mod 5 = 0" evaluate to a subscript?
It seems like it would evaluate to true/false.
What you call a subscript is actually not. It is a predicate (which is
exactly something that, as you say, 'would evaluate to true/false').

The way XPath path evaluation works is a litte bit unlike other things,
but still worth understanding.

In each complete XPath path step:
-- first there is an axis step, like parent::, or following-sibling::,
etc. This will map oen node to a list of nodes (default is child::)

-- Then, there is a node test. This will kick out of the list any nodes
that fail the test

-- Then, there are zero or more predicates. Each will kick out of the
list any nodes that make the predicate eval to false.

So, the step:

child::foo[position()>2][position()<2]

it seems to never find any nodes, right? Greater than 2 and smaller than
2 ... sometimes, it does. Say:

Evaluation starts from bar, in
<bar>
<foo/>
<foo/>
<foo/>
<foo/>
</bar>

Ok, first the axis step; it will result in a list of all 3 foo's
Then, the node test. If will (in this example) leave that list as is.
Then, the first predicate. It will result in a new list, of the last 2
orignal foo's.
Then, the last predicate. It will result in a new list, of the first 1
of the last 2 orignal foo's.

The net result is a list of the 3rd foo. The exp. could have been
simplified to

child::foo[position()=3]

which has an abbreviated form:

foo[3]

So, predicates are not subscripts. They are node removers.
How does "(position()-1) mod 5 = 0" evaluate to a subscript?
It seems like it would evaluate to true/false.
Now maube you can see that it kicks out all nodes of a list, except
those whose (index minus one) are divisible by 5. That will be no. 1,
no. 6, ....
<xsl:apply-templates select=". | following-sibling::car[position() &lt;
5]" mode="info"/>

Then I don't understand what ". |" means. I assume it means: "the
current node boolean OR the thing that follows it".
Not quite; it means: The list resulting from evaluating the left hand
side exp, merged with the list resulting from evaluating the right hand
side exp; merging preserves the doc order and does not duplicate any
nodes in both lists.
Regardless, it *does* seem to work. The only issue now is that the
first vehicle in each "page" has to be treated slightly different
because of the morons who created the original XML spec I'm trying to
meet. On each page, there are "year" and "age group" fields for the
vehicles. Notice that the name of the age group on the first vehicle
isn't "AGE GROUP #001" as you'd expect. It's simply "AGE GROUP".
Ouch. Tell me this isn't a government operation ;)
Here's some sample XML output that is very close to the output I'm
generating (with a lot of stuff omitted for brevity). This example has
12 cars...
....
...the AGE GROUP field is the only one that is different. All the rest
have the correct numbers in their name. Note that the number is the
position of the vehicle on the page, not it's position in the original
XML document.
OK .. modolo will do it again....

In my example, it can be done by replacing the last template by:

<xsl:template match="car" mode="info">

<xsl:variable name="silly-field-thing">
<xsl:value-of select="(position() - 1) mod 5"/>
</xsl:variable>

<xsl:variable name="silly-field-value">
<xsl:choose>
<xsl:when test="$silly-field-thing=0">AGE GROUP</xsl:when>
<xsl:otherwise>AGE GROUP #00<xsl:value-of
select="$silly-field-thing"/></xsl:otherwise>
</xsl:choose>
</xsl:variable>

<carinfo car="{@id}">
<FIELD NAME="{$silly-field-value}"/>
</carinfo>

</xsl:template>

The central idea is to, once again, use modolo .. for the x'th car, x
mod 5 IS the position of the car's date RELATIVE to the top of each page.

It will spew out:

<?xml version="1.0"?>
<report>
<first-page>
<carinfo car="1">
<FIELD NAME="AGE GROUP"/>
</carinfo>
<carinfo car="2">
<FIELD NAME="AGE GROUP #001"/>
</carinfo>
<carinfo car="3">
<FIELD NAME="AGE GROUP #002"/>
</carinfo>
<carinfo car="4">
<FIELD NAME="AGE GROUP #003"/>
</carinfo>
<carinfo car="5">
<FIELD NAME="AGE GROUP #004"/>
</carinfo>
</first-page>
<extra-page>
<carinfo car="6">
<FIELD NAME="AGE GROUP"/>
</carinfo>
<carinfo car="7">
<FIELD NAME="AGE GROUP #001"/>
</carinfo>
<carinfo car="8">
<FIELD NAME="AGE GROUP #002"/>
</carinfo>
<carinfo car="9">
<FIELD NAME="AGE GROUP #003"/>
</carinfo>
<carinfo car="10">
<FIELD NAME="AGE GROUP #004"/>
</carinfo>
</extra-page>
<extra-page>
<carinfo car="11">
<FIELD NAME="AGE GROUP"/>
</carinfo>
</extra-page>
</report>
-- Søren ;)
Aug 22 '06 #4
Soren Kuula wrote:
OK .. modolo will do it again....

In my example, it can be done by replacing the last template by:

<xsl:template match="car" mode="info">

<xsl:variable name="silly-field-thing">
<xsl:value-of select="(position() - 1) mod 5"/>
</xsl:variable>

<xsl:variable name="silly-field-value">
<xsl:choose>
<xsl:when test="$silly-field-thing=0">AGE GROUP</xsl:when>
<xsl:otherwise>AGE GROUP #00<xsl:value-of
select="$silly-field-thing"/></xsl:otherwise>
</xsl:choose>
</xsl:variable>

<carinfo car="{@id}">
<FIELD NAME="{$silly-field-value}"/>
</carinfo>

</xsl:template>

The central idea is to, once again, use modolo .. for the x'th car, x
mod 5 IS the position of the car's date RELATIVE to the top of each page.

It will spew out:

<?xml version="1.0"?>
<report>
<first-page>
<carinfo car="1">
<FIELD NAME="AGE GROUP"/>
</carinfo>
<carinfo car="2">
<FIELD NAME="AGE GROUP #001"/>
</carinfo>
<carinfo car="3">
<FIELD NAME="AGE GROUP #002"/>
</carinfo>
<carinfo car="4">
<FIELD NAME="AGE GROUP #003"/>
</carinfo>
<carinfo car="5">
<FIELD NAME="AGE GROUP #004"/>
</carinfo>
</first-page>
<extra-page>
<carinfo car="6">
<FIELD NAME="AGE GROUP"/>
</carinfo>
<carinfo car="7">
<FIELD NAME="AGE GROUP #001"/>
</carinfo>
<carinfo car="8">
<FIELD NAME="AGE GROUP #002"/>
</carinfo>
<carinfo car="9">
<FIELD NAME="AGE GROUP #003"/>
</carinfo>
<carinfo car="10">
<FIELD NAME="AGE GROUP #004"/>
</carinfo>
</extra-page>
<extra-page>
<carinfo car="11">
<FIELD NAME="AGE GROUP"/>
</carinfo>
</extra-page>
</report>
Thanks for your help. It's like a crash course in XPath.

Unfortunately, I need to go back to my original plan to handle the cars
5 at a time. In addition to the stupid "AGE GROUP", "AGE GROUP #002",
etc.. problem, we've just discovered that the first vehicle has "GVW
#001" but the second vehicle has "GVW #006" (!!!), followed by "GVW
#003" for the third vehicle. As far as we can tell, only the second
vehicle overall is handled this way and I'm sure it's a bug in their
software. The 7th, 12th, etc... are "GVW #002" as as expected. These
people are morons. Unfortunately, we're just a software vendor that
needs to connect two systems and we don't have control over the target
XML format.

Another reason I need to do 5 cars at a time is that I need to generate
sub-totals for certain fields on each "page".

I'm hoping I can figure out how to modify your original code to process
vehicles 5 at a time.

Aug 24 '06 #5
William Krick wrote:
Thanks for your help. It's like a crash course in XPath.

Unfortunately, I need to go back to my original plan to handle the cars
5 at a time. In addition to the stupid "AGE GROUP", "AGE GROUP #002",
etc.. problem, we've just discovered that the first vehicle has "GVW
#001" but the second vehicle has "GVW #006" (!!!), followed by "GVW
#003" for the third vehicle. As far as we can tell, only the second
vehicle overall is handled this way and I'm sure it's a bug in their
software. The 7th, 12th, etc... are "GVW #002" as as expected. These
people are morons. Unfortunately, we're just a software vendor that
needs to connect two systems and we don't have control over the target
XML format.
I'd advise you not to copy code... never (almost).

What you need is a MAP from one set of value to another: Like:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">

<xsl:template match="cars">
<report>
<xsl:apply-templates select="car[(position()-1) mod 5 = 0]"/>
</report>
</xsl:template>

<xsl:template match="car[1]">
<first-page>
<xsl:apply-templates select=". | following-sibling::car[position()
&lt; 5]" mode="info"/>
<xsl:apply-templates select="." mode="page-summary"/>
</first-page>
</xsl:template>

<xsl:template match="car[position()!=1]">
<extra-page>
<xsl:apply-templates select=". | following-sibling::car[position()
&lt; 5]" mode="info"/>
<xsl:apply-templates select="." mode="page-summary"/>
</extra-page>
</xsl:template>

<xsl:template match="car" mode="info">
<xsl:variable name="silly-field-thing">
<xsl:value-of select="(position() - 1) mod 5"/>
</xsl:variable>

<xsl:variable name="silly-field-value">
<xsl:choose>
<xsl:when test="$silly-field-thing=0">AGE GROUP</xsl:when>
<xsl:otherwise>AGE GROUP #00<xsl:value-of
select="$silly-field-thing"/></xsl:otherwise>
</xsl:choose>
</xsl:variable>
<!-- compute the position of the car in the whole list -->
<!-- (position() in here would just get the position in the
list of nodes, of which one is the context node .... -->

<xsl:variable name="total-position">
<xsl:value-of select="count(preceding-sibling::car) + 1"/>
</xsl:variable>

<xsl:variable name="buggy-and-silly-field-value">
<xsl:value-of select="'GVW #'"/>
<xsl:choose>
<xsl:when test="$total-position=2"><xsl:value-of
select="006"/></xsl:when>
<xsl:otherwise><xsl:value-of
select="format-number($total-position, '###')"/></xsl:otherwise>
</xsl:choose>
</xsl:variable>

<carinfo car="{@id}">
<FIELD NAME="{$silly-field-value}"/>
<FIELD NAME="{$buggy-and-silly-field-value}"/>
</carinfo>
</xsl:template>

<xsl:template match="car" mode="page-summary">
<sum-of-ids-of-cars-on-this-page>
<xsl:value-of select="sum(./@id | following-sibling::car[position()
&lt; 5]/@id)"/>
</sum-of-ids-of-cars-on-this-page>
</xsl:template>

</xsl:stylesheet>
will (with the original input) produce

<?xml version="1.0"?>
<report>
<first-page>
<carinfo car="1">
<FIELD NAME="AGE GROUP"/>
<FIELD NAME="GVW #1"/>
</carinfo>
<carinfo car="2">
<FIELD NAME="AGE GROUP #001"/>
<FIELD NAME="GVW #6"/>
</carinfo>
<carinfo car="3">
<FIELD NAME="AGE GROUP #002"/>
<FIELD NAME="GVW #3"/>
</carinfo>
<carinfo car="4">
<FIELD NAME="AGE GROUP #003"/>
<FIELD NAME="GVW #4"/>
</carinfo>
<carinfo car="5">
<FIELD NAME="AGE GROUP #004"/>
<FIELD NAME="GVW #5"/>
</carinfo>
<sum-of-ids-of-cars-on-this-page>15</sum-of-ids-of-cars-on-this-page>
</first-page>
<extra-page>
<carinfo car="6">
<FIELD NAME="AGE GROUP"/>
<FIELD NAME="GVW #6"/>
</carinfo>
<carinfo car="7">
<FIELD NAME="AGE GROUP #001"/>
<FIELD NAME="GVW #7"/>
</carinfo>
<carinfo car="8">
<FIELD NAME="AGE GROUP #002"/>
<FIELD NAME="GVW #8"/>
</carinfo>
<carinfo car="9">
<FIELD NAME="AGE GROUP #003"/>
<FIELD NAME="GVW #9"/>
</carinfo>
<carinfo car="10">
<FIELD NAME="AGE GROUP #004"/>
<FIELD NAME="GVW #10"/>
</carinfo>
<sum-of-ids-of-cars-on-this-page>40</sum-of-ids-of-cars-on-this-page>
</extra-page>
<extra-page>
<carinfo car="11">
<FIELD NAME="AGE GROUP"/>
<FIELD NAME="GVW #11"/>
</carinfo>
<sum-of-ids-of-cars-on-this-page>11</sum-of-ids-of-cars-on-this-page>
</extra-page>
</report>
Another reason I need to do 5 cars at a time is that I need to generate
sub-totals for certain fields on each "page".
No problem.

Søren
Aug 24 '06 #6

Soren Kuula wrote:
>
No problem.
Amazing. I hope you do this for a living and are well paid for it
because you're really good.

Ok, I've managed to modify your example to do what I need it to do but
I've run into one more situation I'm not sure how to handle. The data
for each vehicle object in the source XML needs to be split across
multple pages in the output XML.

For example, given this XML with 6 cars (3-5 omitted for clarity)...

<cars>
<car id="1" agegroup="5" gvw="5,000" collprem="300" compprem="100" />
<car id="2" agegroup="6" gvw="10,000" collprem="250" compprem="75" />
...
<car id="6" agegroup="4" gvw="20,000" collprem="200" compprem="125"
/>
</cars>

....the output needs to look something like this...

<?xml version="1.0"?>
<report>
<main-section>
<first-page>
<FIELD NAME="AGE GROUP">5</FIELD>
<FIELD NAME="AGE GROUP #002">6</FIELD>
<FIELD NAME="GVW #001">5,000</FIELD>
<FIELD NAME="GVW #006">10,000</FIELD>
...
</first-page>
<second-page>
<FIELD NAME="COLL PREM #001">300</FIELD>
<FIELD NAME="COLL PREM #002">250</FIELD>
<FIELD NAME="COMP PREM #001">100</FIELD>
<FIELD NAME="COMP PREM #002">75</FIELD>
...
</second-page>
</main-section>
<extra-section>
<first-page>
<FIELD NAME="AGE GROUP">4</FIELD>
<FIELD NAME="GVW #001">20,000</FIELD>
</first-page>
<second-page>
<FIELD NAME="COLL PREM #001">200</FIELD>
<FIELD NAME="COMP PREM #001">125</FIELD>
</second-page>
</extra-section>
</report>

I'm pretty sure I need to use "apply-templates" twice, once for each
page but I'm not sure how to distinguish between the two calls. Is
that "mode" attribute in the templates the secret?

Aug 24 '06 #7
William Krick wrote:
Amazing. I hope you do this for a living and are well paid for it
because you're really good.
Why, didn't you receive my invoice yet ;)?

Yes I hsould suggest my manager that we (www.aragost.com) also should do
XSL meta-consulting. If you like to, you can use / recommend me for your
next project.
Ok, I've managed to modify your example to do what I need it to do but
I've run into one more situation I'm not sure how to handle. The data
for each vehicle object in the source XML needs to be split across
multple pages in the output XML.
<extra-section>
<first-page>
<FIELD NAME="AGE GROUP">4</FIELD>
<FIELD NAME="GVW #001">20,000</FIELD>
</first-page>
<second-page>
<FIELD NAME="COLL PREM #001">200</FIELD>
<FIELD NAME="COMP PREM #001">125</FIELD>
</second-page>
</extra-section>
I guess that the extra-section does some summarization (or whatever that
is called ;) ), and its content's structure is not driven by the order
and number of cars, ain the same extent as in the first-page /
extra-page case.

What you may want to do is to take a look at xsl:key. This can be used
for rounding up all car nodes with the property that ... whatever -- for
example, that they belong to a specific age group. Then, you can add
some templates (maybe named templates, see the XSLT 1 spec) that use the
key() function to extract the nodes that you rounded up before, and do
some math (summartion) on them.

The mode feature is for enabling the same nodes to be processed in
different ways, while still using patterns (match="..."). An
apply-templates with mode="x" will only invoke templates with mode="x".
An apply-templates with no mode will only invoke templates with no mode.

Happy hackin'

Søren
Aug 25 '06 #8

Soren Kuula wrote:
I guess that the extra-section does some summarization (or whatever that
is called ;) ), and its content's structure is not driven by the order
and number of cars, ain the same extent as in the first-page /
extra-page case.
I'm sorry, I think I confused things by changing the tags from your
original example. Basically, on each "page" there are two "sections".
The first section has half of the attributes about the first 5 cars,
the second section has the rest of the attributes about the first 5
cars. The extra page is the same except it's the next group of 5 cars.
There are sub-totals within each section for certain attributes.
Maybe this will make things clearer...

<?xml version="1.0"?>
<report>
<first-page>
<section-one>
<!-- stuff about cars 1-5 goes here -->
</section-one>
<section-two>
<!-- other stuff about cars 1-5 goes here -->
</section-two>
</first-page>
<extra-page>
<section-one>
<!-- stuff about cars 6-10 goes here -->
</section-one>
<section-two>
<!-- other stuff about cars 6-10 goes here -->
</section-two>
</extra-page>
</report>

Again, I think that matching in groups of 5 cars might be the easiest
way to handle this.

Aug 25 '06 #9

William Krick wrote:
Soren Kuula wrote:
I guess that the extra-section does some summarization (or whatever that
is called ;) ), and its content's structure is not driven by the order
and number of cars, ain the same extent as in the first-page /
extra-page case.

Again, I think that matching in groups of 5 cars might be the easiest
way to handle this.

Nevermind, I figured it out. I was right with my thinking in my
earlier post. I needed to use "apply-templates" twice to the same
batch of vehicles, once in each section using the mode parameter to
distinguish between the "calls".

I've got the XML skeleton and the logic all working. Now it's a matter
of brute forcing my way through all the data and formatting to fill the
fields correctly.

Thank you so much again for your help. I've really learned a lot more
than I ever thought I would about XSL and XPath.

Aug 26 '06 #10
William Krick wrote:
Nevermind, I figured it out. I was right with my thinking in my
earlier post. I needed to use "apply-templates" twice to the same
batch of vehicles, once in each section using the mode parameter to
distinguish between the "calls".
Yes, got it now.
Thank you so much again for your help. I've really learned a lot more
than I ever thought I would about XSL and XPath.
Always nice to help ;)

BTW, you can use node-set typed variables to make the code appear
cleaner, like:

<xsl:template match="car" mode="page-summary">
<xsl:variable name="five-cars" select=". |
following-sibling::car[position() &lt; 5]"/>
<sum-of-ids-of-cars-on-this-page>
<xsl:value-of select="sum($five-cars/@id)"/>
</sum-of-ids-of-cars-on-this-page>
<average>
<xsl:value-of select="sum($five-cars/@id) div count($five-cars)"/>
</average>
</xsl:template>

Søren
Aug 26 '06 #11

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

0
by: Bo Peng | last post by:
Dear list, I am writing a manual for my python extension using Python (2.4) latex classes. Everything seems to be fine except that the subscripts are as big as normal text ( see page 55 of...
14
by: Randell D. | last post by:
Folks, Here's my problem: I am createing an array in a file using the reslut of some PHP and MySQL processing. An example of my array would be examlpe="example one"; examlpe="example...
10
by: Cam | last post by:
Hi all, The code below is a practical exercise and works well running in the debug environment but fails when being compiled for a release build. I believe this is because the debug environment...
4
by: Sehri | last post by:
Hi all, I have just started developing a math companion tool with VS2005 and I just ran into a problem when trying to add the description of a formula. Doed anyone know how can I add math...
138
by: ambika | last post by:
Hello, Am not very good with pointers in C,but I have a small doubt about the way these pointers work.. We all know that in an array say x,x is gonna point to the first element in that...
6
by: sales | last post by:
Hello, I am trying to get my website checkout page to rotate / take turns displaying shopping comparison engine surveys rather than display them all 4 at the same time, thus overwhelming &...
22
by: spam.noam | last post by:
Hello, I discovered that I needed a small change to the Python grammar. I would like to hear what you think about it. In two lines: Currently, the expression "x" is a syntax error. I suggest...
2
by: ChrisO | last post by:
I've been pretty infatuated with JSON for some time now since "discovering" it a while back. (It's been there all along in JavaScript, but it was just never "noticed" or used by most until...
5
by: thatcollegeguy | last post by:
Below are my 3php and 2js files. I create a table using ajax/php and then want to change the values in the tables add(+ number for teamid) id's for each specific td in the table. I don't know...
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: Vimpel783 | last post by:
Hello! Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
1
by: PapaRatzi | last post by:
Hello, I am teaching myself MS Access forms design and Visual Basic. I've created a table to capture a list of Top 30 singles and forms to capture new entries. The final step is a form (unbound)...
1
by: Defcon1945 | last post by:
I'm trying to learn Python using Pycharm but import shutil doesn't work
1
by: Shællîpôpï 09 | last post by:
If u are using a keypad phone, how do u turn on JavaScript, to access features like WhatsApp, Facebook, Instagram....
0
by: af34tf | last post by:
Hi Guys, I have a domain whose name is BytesLimited.com, and I want to sell it. Does anyone know about platforms that allow me to list my domain in auction for free. Thank you
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.