Home. 
.

transparent

transparent

transparent

Altova Mailing List Archives


Re: [xsl] Issue with nested grouping

From: Florent Georges <lists@------------>
To:
Date: 12/2/2007 7:51:00 PM
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


transparent
Print
Mail
Like It
Disclaimer
.

These Archives are provided for informational purposes only and have been generated directly from the Altova mailing list archive system and are comprised of the lists set forth on www.altova.com/list/index.html. Therefore, Altova does not warrant or guarantee the accuracy, reliability, completeness, usefulness, non-infringement of intellectual property rights, or quality of any content on the Altova Mailing List Archive(s), regardless of who originates that content. You expressly understand and agree that you bear all risks associated with using or relying on that content. Altova will not be liable or responsible in any way for any content posted including, but not limited to, any errors or omissions in content, or for any losses or damage of any kind incurred as a result of the use of or reliance on any content. This disclaimer and limitation on liability is in addition to the disclaimers and limitations contained in the Website Terms of Use and elsewhere on the site.

.
.

transparent

transparent