Re: [xsl] Issue with nested grouping

Subject: Re: [xsl] Issue with nested grouping
From: Florent Georges <lists@xxxxxxxxxxxx>
Date: Sun, 2 Dec 2007 20:49:43 +0100 (CET)
Geert Bormans wrote:

  Hi Geert,

> I have been looking at this for too long now, and I am
> still not sure why this doesn't work

> I have an XML (stripped down version of a word XML
> document) That requires (nested) grouping, based on the
> text content of some paragraphs.

  Personally, I wouldn't use for-each-group, but I would
traverse the W:P elements one by one, starting at the first
and then chaining the following sibling.

  If a W:P is starting a group, I create the group element
and I apply the next sibling as content of the group, then I
apply the next sibling of the corresponding ending group
(with the same id) after the newly created group element.

  If a W:P is ending a group, I do nothing (that's the end
recursion condition).

  In any other case I copy the node then I continue to the
next following sibling.

  Here below is a complete stylesheet that shows that.  Is
it what you are looking for?

  Regards,

--drkm


Welcome to the Emacs shell

~/xslt/tests $ cat geert.xsl
<xsl:stylesheet
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
    xmlns:xs="http://www.w3.org/2001/XMLSchema";
    xmlns:w="http://schemas.microsoft.com/office/word/2003/wordml";
    xmlns:wx="http://schemas.microsoft.com/office/word/2003/auxHint";
    xmlns:my="my:geert.xsl"
    version="2.0"
    exclude-result-prefixes="my xs">

   <!-- ...........................................................
       Constant variables.
   -->
   <!-- RE matching the text of a group starting W:P/W:R/W:T. -->
   <xsl:variable name="group-start-re" select="
       '^\[start\s+pgroup\s+id=&quot;([^&quot;]+)&quot;.*$'"/>

   <!-- RE matching the text of a group ending W:P/W:R/W:T. -->
   <xsl:variable name="group-end-re" select="
       '^\[end\s+pgroup\s+id=&quot;([^&quot;]+)&quot;.*$'"/>

   <!-- ...........................................................
       Utility functions.
   -->
   <!-- Return the group id of a group starting W:P, may be (). -->
   <xsl:function name="my:group-start-id" as="xs:string?">
      <xsl:param name="p" as="element(w:p)"/>
      <xsl:analyze-string select="$p/w:r/w:t"
                          regex="{ $group-start-re }">
         <xsl:matching-substring>
            <xsl:sequence select="regex-group(1)"/>
         </xsl:matching-substring>
      </xsl:analyze-string>
   </xsl:function>

   <!-- Return the group id of a group ending W:P, may be (). -->
   <xsl:function name="my:group-end-id" as="xs:string?">
      <xsl:param name="p" as="element(w:p)"/>
      <xsl:analyze-string select="$p/w:r/w:t"
                          regex="{ $group-end-re }">
         <xsl:matching-substring>
            <xsl:sequence select="regex-group(1)"/>
         </xsl:matching-substring>
      </xsl:analyze-string>
   </xsl:function>

   <!-- Return the group ending W:P corresponding to a group starting
        W:P, may be (). -->
   <xsl:function name="my:group-closer" as="element(w:p)?">
      <xsl:param name="p" as="element(w:p)"/>
      <xsl:variable name="id" select="my:group-start-id($p)"/>
      <xsl:if test="exists($id)">
         <xsl:sequence select="
             $p/following-sibling::w:p[my:group-end-id(.) eq $id]"/>
      </xsl:if>
   </xsl:function>

   <!-- ...........................................................
       Main template rules.
   -->
   <!-- Identity template. -->
   <xsl:template match="node()">
      <xsl:copy>
         <xsl:copy-of select="@*"/>
         <xsl:apply-templates select="node()"/>
      </xsl:copy>
   </xsl:template>

   <!-- Handle a WX:SUB-SECTION, start the grouping recursion over
        following siblings.  Launches the mode MY:GROUP. -->
   <xsl:template match="wx:sub-section">
      <xsl:copy>
         <xsl:copy-of select="@*"/>
         <xsl:apply-templates select="w:p[1]" mode="my:group"/>
      </xsl:copy>
   </xsl:template>

   <!-- ...........................................................
       Mode: group.
   -->
   <!-- Handle a group starting W:P. -->
   <xsl:template match="w:p[exists(my:group-start-id(.))]"
                 mode="my:group">
      <pgroup id="{ my:group-start-id(.) }">
         <xsl:apply-templates mode="my:group" select="
             following-sibling::node()[1]"/>
      </pgroup>
      <xsl:apply-templates mode="my:group" select="
          my:group-closer(.)/following-sibling::node()[1]"/>
   </xsl:template>

   <!-- Handle a group ending W:P. -->
   <xsl:template match="w:p[exists(my:group-end-id(.))]"
                 mode="my:group"/>

   <!-- Identity template then recurse on the following sibling. -->
   <xsl:template match="node()" mode="my:group">
      <xsl:copy>
         <xsl:copy-of select="@*"/>
         <xsl:apply-templates select="node()"/>
      </xsl:copy>
      <xsl:apply-templates mode="my:group" select="
          following-sibling::node()[1]"/>
   </xsl:template>

</xsl:stylesheet>

~/xslt/tests $ cat geert.xml 
<?xml version="1.0" encoding="UTF-8"?>
<w:wordDocument
    xmlns:w="http://schemas.microsoft.com/office/word/2003/wordml";
    xmlns:wx="http://schemas.microsoft.com/office/word/2003/auxHint";>
   <w:body>
      <wx:sect>
         <wx:sub-section>
            <w:p>
               <w:r><w:t>Text before first pgroup</w:t></w:r>
            </w:p>
            <w:p>
               <w:r><w:t>[start pgroup id="43210023"</w:t></w:r>
            </w:p>
            <w:p>
               <w:r><w:t>First P in pgroup</w:t></w:r>
            </w:p>
            <w:p>
               <w:r><w:t>Second P in pgroup.</w:t></w:r>
            </w:p>
            <w:p>
               <w:r><w:t>[start pgroup id="54320024"</w:t></w:r>
            </w:p>
            <w:p>
               <w:r><w:t>P in nested pgroup</w:t></w:r>
            </w:p>
            <w:p>
               <w:r><w:t>[end pgroup id="54320024"</w:t></w:r>
            </w:p>
            <w:p>
               <w:r><w:t>First P after nested group</w:t></w:r>
            </w:p>
            <w:p>
               <w:r><w:t>[end pgroup id="43210023"</w:t></w:r>
            </w:p>
            <w:p>
               <w:r><w:t>In between</w:t></w:r>
            </w:p>
            <w:p>
               <w:r><w:t>Other In between</w:t></w:r>
            </w:p>
            <w:p>
               <w:r><w:t>[start pgroup id="43210025"</w:t></w:r>
            </w:p>
            <w:p>
               <w:r><w:t>[start pgroup id="54320026"</w:t></w:r>
            </w:p>
            <w:p>
               <w:r><w:t>Isolated nested pgroup</w:t></w:r>
            </w:p>
            <w:p>
               <w:r><w:t>[end pgroup id="54320026"</w:t></w:r>
            </w:p>
            <w:p>
               <w:r><w:t>[end pgroup id="43210025"</w:t></w:r>
            </w:p>
         </wx:sub-section>
      </wx:sect>
   </w:body>
</w:wordDocument>

~/xslt/tests $ saxon geert.xml geert-my.xsl
<?xml version="1.0" encoding="UTF-8"?><w:wordDocument
xmlns:w="http://schemas.microsoft.com/office/word/2003/wordml";
xmlns:wx="http://schemas.microsoft.com/office/word/2003/auxHint";>
   <w:body>
      <wx:sect>
         <wx:sub-section><w:p>
               <w:r><w:t>Text before first pgroup</w:t></w:r>
            </w:p>
            <pgroup id="43210023">
            <w:p>
               <w:r><w:t>First P in pgroup</w:t></w:r>
            </w:p>
            <w:p>
               <w:r><w:t>Second P in pgroup.</w:t></w:r>
            </w:p>
            <pgroup id="54320024">
            <w:p>
               <w:r><w:t>P in nested pgroup</w:t></w:r>
            </w:p>
            </pgroup>
            <w:p>
               <w:r><w:t>First P after nested group</w:t></w:r>
            </w:p>
            </pgroup>
            <w:p>
               <w:r><w:t>In between</w:t></w:r>
            </w:p>
            <w:p>
               <w:r><w:t>Other In between</w:t></w:r>
            </w:p>
            <pgroup id="43210025">
            <pgroup id="54320026">
            <w:p>
               <w:r><w:t>Isolated nested pgroup</w:t></w:r>
            </w:p>
            </pgroup>
            </pgroup>
         </wx:sub-section>
      </wx:sect>
   </w:body>
</w:wordDocument>

~/xslt/tests $ 





      _____________________________________________________________________________ 
Ne gardez plus qu'une seule adresse mail ! Copiez vos mails vers Yahoo! Mail 

Current Thread