accessing previous context inside apply-templates?

Discussion in 'XML' started by Mike Partridge, Jan 13, 2004.

  1. 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..
     
    Mike Partridge, Jan 13, 2004
    #1
    1. Advertising

  2. "Mike Partridge" <> wrote in message
    news:...
    > 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
     
    Dimitre Novatchev, Jan 13, 2004
    #2
    1. Advertising

  3. Was: accessing previous context... Now: Using the ancestor axis the best way?

    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" <> wrote in message news:<bu1l89$cqdso$-berlin.de>...
    > "Mike Partridge" <> wrote in message
    > news:...

    ....
    > >
    > > 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
     
    Mike Partridge, Jan 14, 2004
    #3
  4. "Mike Partridge" <> wrote in message news:...
    > 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
     
    Dimitre Novatchev, Jan 14, 2004
    #4
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Stefan Siegl
    Replies:
    1
    Views:
    968
    Marrow
    Jul 18, 2003
  2. Cyrille \cns\ Szymanski

    xsl apply-templates select=not(...)

    Cyrille \cns\ Szymanski, Nov 7, 2003, in forum: XML
    Replies:
    4
    Views:
    604
    Cyrille \cns\ Szymanski
    Nov 11, 2003
  3. JKop
    Replies:
    3
    Views:
    484
  4. Ben Pope
    Replies:
    4
    Views:
    367
    Neelesh Bodas
    Dec 6, 2005
  5. recover
    Replies:
    2
    Views:
    822
    recover
    Jul 25, 2006
Loading...

Share This Page