xsl-list
[Top] [All Lists]

Re: Muenchian grouping: help with 'use' and multiple elements

2004-07-09 23:33:28
Hi Justin,
  Please try the XSL -

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
xmlns:xalan="http://xml.apache.org/xalan";>

<xsl:output method="xml" version="1.0"
encoding="UTF-8" indent="yes"/>
                
<xsl:key name="by-restr" match="r_ele" use="restr" />
        
<xsl:template match="/entry">
  <entry>
    <xsl:variable name="rtf">
      <xsl:for-each select="r_ele">
        <r_ele>
          <reb>
            <xsl:value-of select="reb"/>
          </reb>
          <restr>
            <xsl:for-each select="re_restr">
              <xsl:sort select="."/>
              <xsl:value-of select="."/>
              <xsl:if test="position() != last()">
                <xsl:text>,</xsl:text>
              </xsl:if>
            </xsl:for-each>
          </restr>
        </r_ele>
      </xsl:for-each>
    </xsl:variable>
                        
    <xsl:for-each select="xalan:nodeset($rtf)/r_ele">
      <xsl:if test="generate-id(.) =
generate-id(key('by-restr', restr)[1])">
       <group>
        <rebs>
         <xsl:for-each select="key('by-restr',
restr)">
            <reb>                                             <xsl:value-of
select="reb" />
            </reb>
         </xsl:for-each>
        </rebs>
        <re_restrs>
          <xsl:if test="restr != '' ">
            <xsl:call-template name="tokenise-restr">
              <xsl:with-param name="str"
select="restr" />                                     
              <xsl:with-param name="delim"
select="','" />                                       

            </xsl:call-template>
          </xsl:if>
        </re_restrs>                             
       </group>
     </xsl:if>
   </xsl:for-each>
</entry>

</xsl:template>

<xsl:template name="tokenise-restr">
   <xsl:param name="str" />
   <xsl:param name="delim" />
          
   <xsl:if test="not(contains($str, $delim))">
     <re_restr>
       <xsl:value-of select="$str" />
     </re_restr>    
   </xsl:if>          
   <xsl:if test="substring-after($str, $delim) != ''
">             
     <re_restr>
       <xsl:value-of select="substring-before($str,
$delim)" />
     </re_restr>
     <xsl:call-template name="tokenise-restr">
        <xsl:with-param name="str"
select="substring-after($str, $delim)" />
        <xsl:with-param name="delim" select="$delim"
/>
     </xsl:call-template>
   </xsl:if>
</xsl:template>
      
</xsl:stylesheet>

Regards,
Mukul

--- Justin Anderson <justin_anderson(_at_)mac(_dot_)com> wrote:
I'll start this off by mentioning that I started to
learning XSLT a  
week ago, so please don't be too harsh with me if
the answer to this  
question is obvious.

A description of the source and the desired output
in plain english:

The xml file I'm using is an Asian dictionary in
which different  
pronounciations (reb) are limited to specific
characters (re_restr).  
Sometimes certain pronounciations have the same set
of restrictions. In  
those cases, I'd like to group them together. I made
a dummy entry  
below based on numbers. 12 and 21 both contain 'one'
and 'two', so they  
should be grouped together. That's what I'm trying
to do.

I'm trying to do single-level Muenchian grouping of
r_ele elements by  
their re_restr children, of which there can be 0 to
infinity instances  
in any order. I'm not sure if Muenchian grouping
works when the 'use'  
element doesn't exist all the time, and I have no
clue how to make the  
'use' element consider all of the re_restr children
in an r_ele at the  
same time.

I've included a sample of the xml source file, the
xsl file (which I'm  
pretty sure isn't anything like I need it to be),
the desired xml  
output, and the actual xml output.

Thanks in advance for any light shed on this,
Justin Anderson


XML source file:

<?xml version="1.0" encoding="UTF-8"?>
<entry>
      <k_ele>
              <keb>one</keb>
      </k_ele>
      <k_ele>
              <keb>two</keb>
      </k_ele>
      <k_ele>
              <keb>three</keb>
      </k_ele>
      <r_ele>
              <reb>12</reb>
              <re_restr>one</re_restr>
              <re_restr>two</re_restr>
      </r_ele>
      <r_ele>
              <reb>32</reb>
              <re_restr>two</re_restr>
              <re_restr>three</re_restr>
      </r_ele>
      <r_ele>
              <reb>21</reb>
              <re_restr>two</re_restr>
              <re_restr>one</re_restr>
      </r_ele>
</entry>

XSL file:

<?xml version='1.0' encoding='utf-8' ?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform";   
version="1.0">
      <xsl:output method="xml"/>
      
      <xsl:key name="r_ele-by-re_restr" match="r_ele"
use="re_restr"/>
      
      <xsl:template match="/">
              <xsl:apply-templates/>
      </xsl:template>
      
      <xsl:template match="entry">
              <entry>
              <xsl:for-each  

select="r_ele[generate-id(.)=generate-id(key('r_ele-by-

re_restr',re_restr))]">
              <xsl:sort select="reb" order="ascending"/>
                      <group>
                      <xsl:for-each
select="key('r_ele-by-re_restr',re_restr)">
                      <xsl:sort select="reb"/>                                
                                      <rebs>
                                              <reb>
                                                      <xsl:value-of 
select="reb"/>
                                              </reb>
                                      </rebs>
                                      <re_restrs>
                                              <xsl:for-each select="re_restr">
                                              <xsl:sort select="." 
order="ascending" />
                                                      <re_restr>
                                                              <xsl:value-of 
select="."/>
                                                      </re_restr>
                                              </xsl:for-each>
                                      </re_restrs>
                      </xsl:for-each>
                      </group>
              </xsl:for-each>
              </entry>        
      </xsl:template>

</xsl:stylesheet>


Desired results:

<entry>
      <group>
              <rebs>
                      <reb>12</reb>
                      <reb>21</reb>
              </rebs>
              <re_restrs>
                      <re_restr>one</re_restr>
                      <re_restr>two</re_restr>
              </re_restrs>
      </group>
      <group>
              <rebs>
                      <reb>32</reb>
              </rebs>
              <re_restrs>
                      <re_restr>two</re_restr>
                      <re_restr>three</re_restr>
              </re_restrs>
      </group>
</entry>

Current actual results:

<entry>
      <group>
              <rebs>
                      <reb>12</reb>
              </rebs>
              <re_restrs>
                      <re_restr>one</re_restr>
                      <re_restr>two</re_restr>
              </re_restrs>
      </group>
      <group>
              <rebs>
                      <reb>21</reb>
              </rebs>
              <re_restrs>
                      <re_restr>one</re_restr>
                      <re_restr>two</re_restr>
              </re_restrs>
      </group>
      <group>
              <rebs>
                      <reb>32</reb>
              </rebs>
              <re_restrs>
                      <re_restr>two</re_restr>
                      <re_restr>three</re_restr>
              </re_restrs>
      </group>
</entry>



                
__________________________________
Do you Yahoo!?
Yahoo! Mail - 50x more storage than other providers!
http://promotions.yahoo.com/new_mail


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