accessing previous context inside apply-templates?

Mike Partridge

Usenet Archive
Joined
Jan 13, 2004
Messages
6
Reaction score
0
Is it possible to access your caller's (not parent) context while inside a <xsl:template match...> or <xsl:for-each...>? Here is the xml I'm using:

<report-set>
...<report>
.....<detail-data>
.......<detail-column position="1" dsc="col1" sum_fg="0"/> .......<detail-column position="2" dsc="col2" sum_fg="1"/> .......<detail-column position="3" dsc="col3" sum_fg="1"/> .......<detail-column position="4" dsc="col4" sum_fg="1"/> .......<detail-column position="5" dsc="col5" sum_fg="1"/> .....</detail-data> .....<invoice inv_id="232243"> .......<break level="1"> .........<break level="2"> ...........<break level="3"> .............<detail> ...............<row> .................<field position="1">Text1</field> .................<field position="2">34</field> .................<field position="3">3400.00</field> .................<field position="4">0.00</field> .................<field position="5">3400.00</field> ...............</row> ...............<row> .................<field position="1">Text2</field> .................<field position="2">96</field> .................<field position="3">9600</field> .................<field position="4">0.00</field> .................<field position="5">9600.00</field> ...............</row> .............</detail> ...........</break> ...........<break level="3"> .............<detail> ...............<row> .................<field position="1">Text1</field> .................<field position="2">13</field> .................<field position="3">1300.00</field> .................<field position="4">-1300.00</field> .................<field position="5">0.00</field> ...............</row> ...............<row> .................<field position="1">Text2</field> .................<field position="2">13</field> .................<field position="3">2600</field> .................<field position="4">0.00</field> .................<field position="5">2600.00</field> ...............</row> .............</detail> ...........</break> .........</break> .......</break> .....</invoice> ...</report> </report-set>

When I am in the <break> context (of which there can be any number), I want to output a sum of each field based on the <detail-data> from the top. I've tried to apply-templates on the /report-set/report/detail-data/detail-column which can give me a column for each <detail-column>, but I need to sum from the context where the apply-templates was called. Is this possible? I've hacked a way by passing my context position and break level and going back to look for the break i want, but it's inefficient and hard to read, not to mention ugly.

Does anyone have any ideas? Please tell me there's an easier way!

Mike Partridge..
 

Dimitre Novatchev

Usenet Archive
Joined
Nov 7, 2000
Messages
737
Reaction score
0
Mike Partridge said:
Is it possible to access your caller's (not parent) context while inside a <xsl:template match...> or <xsl:for-each...>? Here is the xml I'm using:

<report-set>
..<report>
....<detail-data>
......<detail-column position="1" dsc="col1" sum_fg="0"/> ......<detail-column position="2" dsc="col2" sum_fg="1"/> ......<detail-column position="3" dsc="col3" sum_fg="1"/> ......<detail-column position="4" dsc="col4" sum_fg="1"/> ......<detail-column position="5" dsc="col5" sum_fg="1"/> ....</detail-data> ....<invoice inv_id="232243"> ......<break level="1"> ........<break level="2"> ..........<break level="3"> ............<detail> ..............<row> ................<field position="1">Text1</field> ................<field position="2">34</field> ................<field position="3">3400.00</field> ................<field position="4">0.00</field> ................<field position="5">3400.00</field> ..............</row> ..............<row> ................<field position="1">Text2</field> ................<field position="2">96</field> ................<field position="3">9600</field> ................<field position="4">0.00</field> ................<field position="5">9600.00</field> ..............</row> ............</detail> ..........</break> ..........<break level="3"> ............<detail> ..............<row> ................<field position="1">Text1</field> ................<field position="2">13</field> ................<field position="3">1300.00</field> ................<field position="4">-1300.00</field> ................<field position="5">0.00</field> ..............</row> ..............<row> ................<field position="1">Text2</field> ................<field position="2">13</field> ................<field position="3">2600</field> ................<field position="4">0.00</field> ................<field position="5">2600.00</field> ..............</row> ............</detail> ..........</break> ........</break> ......</break> ....</invoice> ..</report> </report-set>

When I am in the <break> context (of which there can be any number), I want to output a sum of each field based on the <detail-data> from the top. I've tried to apply-templates on the /report-set/report/detail-data/detail-column which can give me a column for each <detail-column>, but I need to sum from the context where the apply-templates was called. Is this possible? I've hacked a way by passing my context position and break level and going back to look for the break i want, but it's inefficient and hard to read, not to mention ugly.

Does anyone have any ideas? Please tell me there's an easier way!

Mike Partridge..

I am not sure what you exactly want, but if I guess well, this will answer your question.

This transformation:

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:eek:utput method="text"/> <xsl:strip-space elements="*"/>

<xsl:key name="kDetail" match="detail-column" use="@position"/>

<xsl:template match="row">
<xsl:value-of select="sum(field[key('kDetail',
count(preceding-sibling::*)+1)/@sum_fg = 1])"/>
<xsl:text>
</xsl:text>
</xsl:template>
</xsl:stylesheet>

when applied on your source.xml:

<report-set>
<report>
<detail-data>
<detail-column position="1" dsc="col1" sum_fg="0"/>
<detail-column position="2" dsc="col2" sum_fg="1"/>
<detail-column position="3" dsc="col3" sum_fg="1"/>
<detail-column position="4" dsc="col4" sum_fg="1"/>
<detail-column position="5" dsc="col5" sum_fg="1"/>
</detail-data>
<invoice inv_id="232243">
<break level="1">
<break level="2">
<break level="3">
<detail>
<row>
<field position="1">Text1</field>
<field position="2">34</field>
<field position="3">3400.00</field>
<field position="4">0.00</field>
<field position="5">3400.00</field>
</row>
<row>
<field position="1">Text2</field>
<field position="2">96</field>
<field position="3">9600</field>
<field position="4">0.00</field>
<field position="5">9600.00</field>
</row>
</detail>
</break>
<break level="3">
<detail>
<row>
<field position="1">Text1</field>
<field position="2">13</field>
<field position="3">1300.00</field>
<field position="4">-1300.00</field>
<field position="5">0.00</field>
</row>
<row>
<field position="1">Text2</field>
<field position="2">13</field>
<field position="3">2600</field>
<field position="4">0.00</field>
<field position="5">2600.00</field>
</row>
</detail>
</break>
</break>
</break>
</invoice>
</report>
</report-set>

produces this output:

6834
19296
13
5213

In case my guess about the real meaning of your message was unsuccessful, could you, please, describe it in a correct and unambiguous way?

Dimitre Novatchev.
FXSL developer, XML Insider,

http://fxsl.sourceforge.net/ -- the home of FXSL
Resume: http://fxsl.sf.net/DNovatchev/Resume/Res.html
 

Mike Partridge

Usenet Archive
Joined
Jan 13, 2004
Messages
6
Reaction score
0
No, you guessed perfectly! Thanks so much for your help, and I'm sorry that my description was difficult to fathom. I see what you're doing, but can you clarify something? How is count(preceding-sibling::*)+1 different than position in this case? I have limited understanding of how to use axes, so please bear with me. If there are multiple <report> elements that need different sets of <detail-column>s in <report-set> (see example xml below), how can I reference the detail-column data from the current report only? If the xml structure was static I could back up through parent nodes, but I don't know how many <break>s there are so I can't hardcode the xpath. I have a feeling there is a relatively simple way to do this using the ancestor axis, but I'm not sure how. If I were to create a key as you defined it for the following example xml, they would conflict correct? That is why I think using the ancestor axis is the best way.

<report-set>
<report>
<detail-data>
<detail-column position="1" dsc="col1" sum_fg="0"/>
<detail-column position="2" dsc="col2" sum_fg="1"/>
<detail-column position="3" dsc="col3" sum_fg="1"/>
<detail-column position="4" dsc="col4" sum_fg="1"/>
<detail-column position="5" dsc="col5" sum_fg="1"/>
</detail-data>
<invoice inv_id="232243">
<break level="1">
<break level="2">
<break level="3">
...
</break>
</break>
</break>
</invoice>
</report>
<report>
<detail-data>
<detail-column position="1" dsc="name" sum_fg="0"/>
<detail-column position="2" dsc="description" sum_fg="0"/> <detail-column position="3" dsc="amount" sum_fg="1"/> </detail-data> <invoice inv_id="232244"> <break level="1"> <break level="2"> ... </break> </break> </invoice> </report> </report-set>

Thanks again for your help!

Mike Partridge

Dimitre Novatchev said:
When I am in the <break> context (of which there can be any number), I want to output a sum of each field based on the <detail-data> from the top. I've tried to apply-templates on the /report-set/report/detail-data/detail-column which can give me a column for each <detail-column>, but I need to sum from the context where the apply-templates was called. Is this possible? I've hacked a way by passing my context position and break level and going back to look for the break i want, but it's inefficient and hard to read, not to mention ugly.

Does anyone have any ideas? Please tell me there's an easier way!

Mike Partridge..

I am not sure what you exactly want, but if I guess well, this will answer your question.

This transformation:

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:eek:utput method="text"/> <xsl:strip-space elements="*"/>

<xsl:key name="kDetail" match="detail-column" use="@position"/>

<xsl:template match="row">
<xsl:value-of select="sum(field[key('kDetail',
count(preceding-sibling::*)+1)/@sum_fg = 1])"/>
<xsl:text>
</xsl:text>
</xsl:template>
</xsl:stylesheet>

when applied on your source.xml:
-- snip --

produces this output:

6834
19296
13
5213

In case my guess about the real meaning of your message was unsuccessful, could you, please, describe it in a correct and unambiguous way?

Dimitre Novatchev.
FXSL developer, XML Insider,

http://fxsl.sourceforge.net/ -- the home of FXSL
Resume: http://fxsl.sf.net/DNovatchev/Resume/Res.html
 

Dimitre Novatchev

Usenet Archive
Joined
Nov 7, 2000
Messages
737
Reaction score
0
Mike Partridge said:
No, you guessed perfectly! Thanks so much for your help, and I'm sorry that my description was difficult to fathom. I see what you're doing, but can you clarify something? How is count(preceding-sibling::*)+1 different than position in this case?

In this case using either of them will produce the same results.

I wanted somehow to express that there's no need for the "position" attribute on field elements and even that one can do without a position function.

There are other scenarios (e.g. when position is not used within a location step) , when position will only return the position of the current node in the current node-list -- this is *not* the same as count(preceding-sibling::*)+1 and depends on the way the xsl:apply-templates or the xsl:for-each were specified.

I have limited understanding of how to use axes, so please bear with me. If there are multiple <report> elements that need different sets of <detail-column>s in <report-set> (see example xml below), how can I reference the detail-column data from the current report only? If the xml structure was static I could back up through parent nodes, but I don't know how many <break>s there are so I can't hardcode the xpath. I have a feeling there is a relatively simple way to do this using the ancestor axis, but I'm not sure how. If I were to create a key as you defined it for the following example xml, they would conflict correct? That is why I think using the ancestor axis is the best way.

There's no problem -- just use:

ancestor::report[1]/detail-data

Dimitre Novatchev.
FXSL developer, XML Insider,

http://fxsl.sourceforge.net/ -- the home of FXSL
Resume: http://fxsl.sf.net/DNovatchev/Resume/Res.html
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
548,042
Messages
3,104,223
Members
248,131
Latest member
Tonypshaw1

Latest Threads

Top