Subject: Re: [xsl] transform html h1 with a div From: Michael Kay <mike@xxxxxxxxxxxx> Date: Wed, 31 Oct 2012 07:18:55 +0000 |
Michael Kay Saxonica
So, I try to extend this approach:
http://www.xmlplease.com/xhtml/xhtml-hierarchy
in order to work on fragment and, generally, with more "lazy" condition:
* The higher h* level can be any of h1, h2, ... h6 * Not all the intermediate levels are present
Thus, basically, a conservative approach is to consider a section starting from a given Hx and ending to the next Hy, where y>=x. And all the intermediate Hz (with z<x) must be processed in same way...
I write this XSLT and it works fine. But probably this is not so efficient:
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0" xmlns="http://www.w3.org/1999/xhtml" > <xsl:output method="xhtml" indent="yes"/>
<!--identity template --> <xsl:template match="@*|node()" > <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template>
<!-- body of html document --> <xsl:template match="body"> <!-- start of recursion, defining the group by condition on starting element --> <xsl:for-each-group select="element()|comment()|processing-instruction()" group-starting-with="*[local-name()='h1' or (local-name()='h2' and count(preceding-sibling::h1)=0) or (local-name()='h3' and count(preceding-sibling::h1 | preceding-sibling::h2 )=0) or (local-name()='h4' and count(preceding-sibling::h1 | preceding-sibling::h2 | preceding-sibling::h3 )=0) or (local-name()='h5' and count(preceding-sibling::h1 | preceding-sibling::h2 | preceding-sibling::h3 | preceding-sibling::h4 )=0) or (local-name()='h6' and count(preceding-sibling::h1 | preceding-sibling::h2 | preceding-sibling::h3 | preceding-sibling::h4 | preceding-sibling::h5 )=0) ]"> <xsl:message><xsl:text>gruppo (body)= </xsl:text><xsl:value-of select="current-group()/local-name()"/></xsl:message> <xsl:call-template name="gruppo"/> </xsl:for-each-group> </xsl:template>
<!-- template with recursion --> <xsl:template name="gruppo"> <xsl:choose>
<!-- check if the first element og current group is h*. In case the div is required --> <xsl:when test="local-name()='h1' or local-name()='h2' or local-name()='h3' or local-name()='h4' or local-name()='h5' or local-name()='h6'" > <xsl:element name="div">
<!--class attirbute of div element. the header local name is the value --> <xsl:attribute name="class"><xsl:value-of select="local-name()"/></xsl:attribute>
<!-- copy of the header tag --> <xsl:element name="{local-name()}"> <xsl:apply-templates select="@*|node()"/> </xsl:element>
<!-- recursion applied to the current group, removing the first, already processed, element --> <xsl:for-each-group select="current-group() except ." group-starting-with="*[ (local-name()='h1' or (local-name()='h2' and count(preceding-sibling::h1)=0) or (local-name()='h3' and count(preceding-sibling::h1 | preceding-sibling::h2 )=0) or (local-name()='h4' and count(preceding-sibling::h1 | preceding-sibling::h2 | preceding-sibling::h3 )=0) or (local-name()='h5' and count(preceding-sibling::h1 | preceding-sibling::h2 | preceding-sibling::h3 | preceding-sibling::h4 )=0) or (local-name()='h6' and count(preceding-sibling::h1 | preceding-sibling::h2 | preceding-sibling::h3 | preceding-sibling::h4 | preceding-sibling::h5 )=0) ) ]"> <xsl:call-template name="gruppo"/> </xsl:for-each-group> </xsl:element> </xsl:when> <xsl:otherwise> <!-- the first element is not a h*. The div element is not required, simply copy this first element --> <xsl:element name="{local-name()}"> <xsl:apply-templates select="@*|node()"/> </xsl:element>
<!-- recursion applied to the current group, removing the first, already processed, element --> <xsl:for-each-group select="current-group() except ." group-starting-with="*[ (local-name()='h1' or (local-name()='h2' and count(preceding-sibling::h1)=0) or (local-name()='h3' and count(preceding-sibling::h1 | preceding-sibling::h2 )=0) or (local-name()='h4' and count(preceding-sibling::h1 | preceding-sibling::h2 | preceding-sibling::h3 )=0) or (local-name()='h5' and count(preceding-sibling::h1 | preceding-sibling::h2 | preceding-sibling::h3 | preceding-sibling::h4 )=0) or (local-name()='h6' and count(preceding-sibling::h1 | preceding-sibling::h2 | preceding-sibling::h3 | preceding-sibling::h4 | preceding-sibling::h5 )=0) ) ]"> <xsl:call-template name="gruppo"/> </xsl:for-each-group> </xsl:otherwise> </xsl:choose> </xsl:template>
<!-- create some style for html header, to visual evaluate the nested divs --> <xsl:template match="head"> <head> <style type="text/css"> div.h1 {border-width: 1; border: solid; background-color: #FFFF33; width:95%;} div.h2 {border-width: 1; border: solid; background-color: #FF9933; width:95%;} div.h3 {border-width: 1; border: solid; background-color: #FF0033; width:95%;} div.h4 {border-width: 1; border: solid; background-color: #99FFFF; width:95%;} div.h5 {border-width: 1; border: solid; background-color: #9999FF; width:95%;} div.h6 {border-width: 1; border: solid; background-color: #9933FF; width:95%;} </style> <xsl:apply-templates/> </head> </xsl:template>
</xsl:stylesheet>
This work as expected on xml file with lazy condition like this one:
<?xml version="1.0" encoding="UTF-8"?> <html> <head> <title></title> </head> <body> <p>prima riga di testo prima del primo titolo</p> <p>seconda riga di testo prima del primo titolo</p> <h3>titolo h3</h3> <p>testo dopo il titolo h3</p> <h4>titolo h4</h4>
<h6>titolo h6</h6> <p>questo h il testo dopo il titolo h6</p>
<h2>titolo h2</h2> <p>questo h il testo dopo il primo titolo h2</p> <h2>titolo h2</h2> <p>questo h il testo dopo il secondo titolo h2</p> <h4>titolo h4</h4> <p>questo h il testo dopo il titolo h4</p>
<h1>titolo 1B</h1> <p>questo h il 10 testo dopo il <i>titolo 1B</i></p> <p>questo h il 20 testo dopo il <i>titolo 1B</i></p> <p>questo h il 30 testo dopo il <i>titolo 1B</i></p> </body> </html>
But I think that the xslt is not well written... for instance, I think it can be improved by simply copy the <p> elements that appears in the current-group before the first h* element.
Any suggestion?
Thanks in advance...
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: [xsl] transform html h1 with a , Giuseppe Briotti | Thread | [xsl] Re: transform html h1 with a , Giuseppe Briotti |
Re: [xsl] transform html h1 with a , Giuseppe Briotti | Date | Re: [xsl] XSLT whitebox testing, Tony Graham |
Month |