xsl-list
[Top] [All Lists]

RE: grouping sequence question

2002-11-29 09:59:27
Hey Tom

Thanks you for yr interesting solution !! 

Paul

--- TSchutzerWeissmann(_at_)uk(_dot_)imshealth(_dot_)com wrote:
Sorry - sent the last one prematurely...

[...]
what if I can't evaluate by string->
not(start-with(@ref, 'GRP')), but need to judge
from
whether the element can apply another templates.
because there are lots different groups, and
naming by
different people, etc.
such as , I add a GRP xs:element in the schema
which
is tailor for this 'GRP2'
<xs:element name="GRP2">
    <xs:complexType>
            <xs:sequence>
                    <xs:element ref="GRP-for-mail"
maxOccurs="unbounded"/>
            </xs:sequence>
    </xs:complexType>
</xs:element>

Nested groups are a bit more complicated, so I'm
going to stick with
defining group elements as having a ref attribute
that begins with "GRP". 

Let's say you want to output this:
Group starts
---> apply templates to any child group (ie,
recurse)
Group ends
Group members.

Since a "child group" isn't going to be a direct
child node, you can either
set up an XPath that can cope with the hierarchy of
xs:complexType,
xs:sequence, whatever, or you could use a key -

<xsl:key name="childGRPs"
match="xs:element[starts-with(@ref, 'GRP')]"
 

use="generate-id(ancestor::xs:element[starts-with(@ref,
'GRP')][1])"/>

The [1] makes sure that you only recurse one level
at a time, giving you
child groups but no grandchild groups.

The real complication though, is the first key. This
is because you don't
want to associate elements with a preceding group
that's nested deeper than
they are, so you need to alter the preceding axis
and only consider
preceding-siblings or ancestors of
preceding-siblings...

<xsl:key name="byGRP" 
match="xs:element[not(starts-with(@ref, 'GRP'))]"
 

use="generate-id(ancestor-or-self::*/preceding-sibling::xs:element
       [starts-with(@ref, 'GRP')][1])"/>
 
Then you just need to set the recursive template
going by sending the first
level of groups to it:
(email resumes...)

<xsl:template match="/xs:schema/xs:element">
  <xsl:apply-templates
select="//xs:element[starts-with(@ref, 'GRP')]
                
[not(ancestor::xs:element[starts-with(@ref,
'GRP')])]"
    mode="recurse"/>
</xsl:template>

The whole thing looks like this:

<xsl:key name="childGRPs"
match="xs:element[starts-with(@ref, 'GRP')]"
 

use="generate-id(ancestor::xs:element[starts-with(@ref,
'GRP')][1])"/>

<xsl:key name="byGRP" 
match="xs:element[not(starts-with(@ref, 'GRP'))]"
  use="generate-id(
      
ancestor-or-self::*/preceding-sibling::xs:element
       [starts-with(@ref, 'GRP')][1])"/>

<xsl:template match="/xs:schema/xs:element">
  <xsl:apply-templates
select="//xs:element[starts-with(@ref, 'GRP')]
                
[not(ancestor::xs:element[starts-with(@ref,
'GRP')])]"
    mode="recurse"/>
</xsl:template>

<xsl:template match="xs:element" mode="recurse">
  <!-- for each group -->
    <xsl:variable name="me" select="generate-id()"/>

    Group <xsl:value-of select="@ref"/> Starts     
    
    <xsl:apply-templates
select="key('childGRPs',$me)" mode="recurse"/>
   
    Group <xsl:value-of select="@ref"/> Ends.
                                        
    <xsl:for-each select="key('byGRP',$me)">
      <xsl:value-of select="@ref"/> Starts
    </xsl:for-each>
    
    <xsl:for-each select="key('byGRP',$me)">
      <xsl:value-of select="@ref"/> Ends
    </xsl:for-each>

</xsl:template>


 XSL-List info and archive: 
http://www.mulberrytech.com/xsl/xsl-list



__________________________________________________
Do you Yahoo!?
Yahoo! Mail Plus - Powerful. Affordable. Sign up now.
http://mailplus.yahoo.com

 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list



<Prev in Thread] Current Thread [Next in Thread>