xsl-list
[Top] [All Lists]

[xsl] Grouping to Separate Out Block Level Elements from Mixed Content

2022-02-05 09:20:07
The sample XML file has two paragraphs ("p" element) that contain mixed 
content. However, some of the child elements of "p" are block level elements. I 
need to separate these block level elements out from the mixed content and 
place each component of the paragraph content in their own consecutive blocks, 
as appropriate. So, in the first example input paragraph (see attached for 
complete input file): <p>In Boolean algebra, the algebraic normal form 
<i>(ANF)</i> is a way of writing logical formulas in    one of three subforms: 
<list list-type="simple">     <list-item>      <p>The entire formula is purely 
true or false</p>     </list-item>     <list-item>      <p>One or more 
variables are ANDed together into a term</p>     </list-item>     <list-item>   
   <p>The previous subform with a purely true term</p>     </list-item>    
</list>Formulas written in ANF are also known as Zhegalkin polynomials and 
Positive Polarity (or    Parity) Reed–Muller expressions (PPRM).</p>
Should on output be:
<p>In Boolean algebra, the algebraic normal form <i>(ANF)</i> is a way of 
writing logical formulas in    one of three subforms:<p> <list 
list-type="simple">     <list-item>      <p>The entire formula is purely true 
or false</p>     </list-item>     <list-item>      <p>One or more variables are 
ANDed together into a term</p>     </list-item>     <list-item>      <p>The 
previous subform with a purely true term</p>     </list-item>    
</list><p>Formulas written in ANF are also known as Zhegalkin polynomials and 
Positive Polarity (or    Parity) Reed–Muller expressions (PPRM).</p>
You'll note in the second example input paragraph a more complex scenario where 
there are two nested block elements. I think a recursive solution is needed for 
that but so far I've had no success in achieving it.
The XSLT I've written so far (attached) accomplishes the first needed part by 
separating the block elements from the mixed content that comes before the 
block using for-each-group and group-starting-with. But attempts to achieve the 
same result on mixed content that follows the block using  for-each-group and 
group-ending-with have not succeeded. I think it's close but am just missing a 
crucial detail. And, as noted already, the solution does need to account for 
the possibility of nested blocks.
Embedded XSLT:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" ;   
xmlns:xs="http://www.w3.org/2001/XMLSchema" ;   
xmlns:xlink="http://www.w3.org/1999/xlink"  ;   
xmlns:mml="http://www.w3.org/1998/Math/MathML" ;   exclude-result-prefixes="xs"  
  version="2.0">            <xsl:template match="p">        <xsl:for-each-group 
select="node()" group-starting-with="list | disp-formula | mml:math">           
 <xsl:variable name="group1" as="element()">                <GROUP1>            
        <xsl:apply-templates select="current-group()"></xsl:apply-templates>    
            </GROUP1>            </xsl:variable>            <xsl:choose>        
        <xsl:when test="$group1/list |                     $group1/disp-formula 
|                    $group1/mml:math">                    <xsl:call-template 
name="end_group">                        <xsl:with-param name="input" 
select="$group1"/>                    </xsl:call-template>                
</xsl:when>                <xsl:otherwise>                    <xsl:copy-of 
select="$group1"/>                                    </xsl:otherwise>          
  </xsl:choose>        </xsl:for-each-group>    </xsl:template>       
<xsl:template name="end_group">        <xsl:param name="input" 
default</xsl:param>        <xsl:variable name="group2" as="element()" >        
    <xsl:for-each-group select="$input" group-ending-with="list | disp-formula 
| mml:math">                  <PGROUP2>                    <xsl:apply-templates 
select="current-group()"></xsl:apply-templates>                </PGROUP2>       
                         </xsl:for-each-group>        </xsl:variable>        
<xsl:copy-of select="$group2"/>            </xsl:template>
    <xsl:template match="/">        <output>            <xsl:apply-templates/>  
      </output>    </xsl:template>        <xsl:template match="*">        
<xsl:variable name="name" as="xs:string" select="name()"/>        <xsl:element 
name="{$name}">            <xsl:apply-templates/>                    
</xsl:element>    </xsl:template>        </xsl:stylesheet>
Thanks in advance,
Don
--~----------------------------------------------------------------
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
EasyUnsubscribe: http://lists.mulberrytech.com/unsub/xsl-list/1167547
or by email: xsl-list-unsub(_at_)lists(_dot_)mulberrytech(_dot_)com
--~--

Attachment: Grouping_Nested_Blocks.xsl
Description: XML document

Attachment: Nested_Blocks.xml
Description: XML document

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