accessing previous context inside apply-templates?

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Mike Partridge

    accessing previous context inside apply-templates?

    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">
    ...........<bre ak level="3">
    .............<d etail>
    ............... <row>
    ............... ..<field position="1">Te xt1</field>
    ............... ..<field position="2">34 </field>
    ............... ..<field position="3">34 00.00</field>
    ............... ..<field position="4">0. 00</field>
    ............... ..<field position="5">34 00.00</field>
    ............... </row>
    ............... <row>
    ............... ..<field position="1">Te xt2</field>
    ............... ..<field position="2">96 </field>
    ............... ..<field position="3">96 00</field>
    ............... ..<field position="4">0. 00</field>
    ............... ..<field position="5">96 00.00</field>
    ............... </row>
    .............</detail>
    ...........</break>
    ...........<bre ak level="3">
    .............<d etail>
    ............... <row>
    ............... ..<field position="1">Te xt1</field>
    ............... ..<field position="2">13 </field>
    ............... ..<field position="3">13 00.00</field>
    ............... ..<field position="4">-1300.00</field>
    ............... ..<field position="5">0. 00</field>
    ............... </row>
    ............... <row>
    ............... ..<field position="1">Te xt2</field>
    ............... ..<field position="2">13 </field>
    ............... ..<field position="3">26 00</field>
    ............... ..<field position="4">0. 00</field>
    ............... ..<field position="5">26 00.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

    #2
    Re: accessing previous context inside apply-templates?


    "Mike Partridge" <halfu.groups@e arthlink.net> wrote in message
    news:615b1253.0 401131204.217d3 f56@posting.goo gle.com...[color=blue]
    > 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">
    > ..........<brea k level="3">
    > ............<de tail>
    > ..............< row>
    > ............... .<field position="1">Te xt1</field>
    > ............... .<field position="2">34 </field>
    > ............... .<field position="3">34 00.00</field>
    > ............... .<field position="4">0. 00</field>
    > ............... .<field position="5">34 00.00</field>
    > ..............</row>
    > ..............< row>
    > ............... .<field position="1">Te xt2</field>
    > ............... .<field position="2">96 </field>
    > ............... .<field position="3">96 00</field>
    > ............... .<field position="4">0. 00</field>
    > ............... .<field position="5">96 00.00</field>
    > ..............</row>
    > ............</detail>
    > ..........</break>
    > ..........<brea k level="3">
    > ............<de tail>
    > ..............< row>
    > ............... .<field position="1">Te xt1</field>
    > ............... .<field position="2">13 </field>
    > ............... .<field position="3">13 00.00</field>
    > ............... .<field position="4">-1300.00</field>
    > ............... .<field position="5">0. 00</field>
    > ..............</row>
    > ..............< row>
    > ............... .<field position="1">Te xt2</field>
    > ............... .<field position="2">13 </field>
    > ............... .<field position="3">26 00</field>
    > ............... .<field position="4">0. 00</field>
    > ............... .<field position="5">26 00.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..[/color]


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

    This transformation:

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

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

    <xsl:template match="row">
    <xsl:value-of select="sum(fie ld[key('kDetail',
    count(preceding-sibling::*)+1)/@sum_fg = 1])"/>
    <xsl:text>&#xA; </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">Te xt1</field>
    <field position="2">34 </field>
    <field position="3">34 00.00</field>
    <field position="4">0. 00</field>
    <field position="5">34 00.00</field>
    </row>
    <row>
    <field position="1">Te xt2</field>
    <field position="2">96 </field>
    <field position="3">96 00</field>
    <field position="4">0. 00</field>
    <field position="5">96 00.00</field>
    </row>
    </detail>
    </break>
    <break level="3">
    <detail>
    <row>
    <field position="1">Te xt1</field>
    <field position="2">13 </field>
    <field position="3">13 00.00</field>
    <field position="4">-1300.00</field>
    <field position="5">0. 00</field>
    </row>
    <row>
    <field position="1">Te xt2</field>
    <field position="2">13 </field>
    <field position="3">26 00</field>
    <field position="4">0. 00</field>
    <field position="5">26 00.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


    Comment

    • Mike Partridge

      #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="descriptio n" 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" <dnovatchev@yah oo.com> wrote in message news:<bu1l89$cq dso$1@ID-152440.news.uni-berlin.de>...[color=blue]
      > "Mike Partridge" <halfu.groups@e arthlink.net> wrote in message
      > news:615b1253.0 401131204.217d3 f56@posting.goo gle.com...[/color]
      ....[color=blue][color=green]
      > >
      > > 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..[/color]
      >
      >
      > I am not sure what you exactly want, but if I guess well, this will answer
      > your question.
      >
      > This transformation:
      >
      > <xsl:styleshe et version="1.0"
      > xmlns:xsl="http ://www.w3.org/1999/XSL/Transform">
      > <xsl:output method="text"/>
      > <xsl:strip-space elements="*"/>
      >
      > <xsl:key name="kDetail" match="detail-column" use="@position"/>
      >
      > <xsl:template match="row">
      > <xsl:value-of select="sum(fie ld[key('kDetail',
      > count(preceding-sibling::*)+1)/@sum_fg = 1])"/>
      > <xsl:text>&#xA; </xsl:text>
      > </xsl:template>
      > </xsl:stylesheet>
      >
      >
      >
      > when applied on your source.xml:
      >[/color]
      -- snip --[color=blue]
      >
      > 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[/color]

      Comment

      • Dimitre Novatchev

        #4
        Re: accessing previous context inside apply-templates?

        "Mike Partridge" <halfu.groups@e arthlink.net> wrote in message news:615b1253.0 401132300.4af4b afa@posting.goo gle.com...[color=blue]
        > 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?[/color]

        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.

        [color=blue]
        > 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.[/color]

        There's no problem -- just use:

        ancestor::repor t[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

        Comment

        Working...