http://www.perlmonks.org?node_id=363839

Dall' XML:
<?xml version="1.0"?> <body> testo<i>it</i> <div>div</div> <p>testo2<i>altro</i></p> altro2<i>ot</i> <td><p>qualcosa</p></td> <td>senza</td> </body>
e XSLT:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE xsl:stylesheet [ <!ENTITY bl-e "name()='p' or name()='div' or name='td'"> ]> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Tr +ansform"> <xsl:output method="xml" indent="yes"/> <xsl:template match="/body"> <doc> <xsl:call-template name="scorri"> <xsl:with-param name="nodi" select="child::node()"/> </xsl:call-template> </doc> </xsl:template> <xsl:template name="scorri"> <xsl:param name="nodi"/> <xsl:param name="comincia" select="false()"/> <xsl:choose> <xsl:when test="not($comincia) and count($nodi[&bl-e;])>0"> <xsl:variable name="primo" select="$nodi[&bl-e;][1]"/> <xsl:call-template name="make-block"><xsl:with-param name="nodi" s +elect="$primo/preceding-sibling::node()"/></xsl:call-template> <xsl:apply-templates select="$primo"/> <xsl:call-template name="scorri"><xsl:with-param name="nodi" selec +t="$primo/following-sibling::node()"/><xsl:with-param name="comincia" + select="$primo"/></xsl:call-template> </xsl:when> <xsl:when test="count($nodi[&bl-e;])>0"> <xsl:variable name="primo" select="$nodi[&bl-e;][1]"/> <xsl:call-template name="make-block"><xsl:with-param name="nodi" s +elect="$primo/preceding-sibling::node()[count(.|$comincia)=2][count(. +/following-sibling::node()|$comincia)=count(./following-sibling::node +())+1]"/></xsl:call-template> <xsl:apply-templates select="$primo"/> <xsl:call-template name="scorri"><xsl:with-param name="nodi" selec +t="$primo/following-sibling::node()"/><xsl:with-param name="comincia" + select="$primo"/></xsl:call-template> </xsl:when> <xsl:otherwise> <xsl:call-template name="make-block"><xsl:with-param name="nodi" s +elect="$nodi"/></xsl:call-template> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template name="make-block"> <xsl:param name="nodi"/> <xsl:if test="normalize-space($nodi)"> <block><xsl:apply-templates select="$nodi"/></block> </xsl:if> </xsl:template> <xsl:template match="td"> <cella> <xsl:call-template name="scorri"> <xsl:with-param name="nodi" select="child::node()"/> </xsl:call-template> </cella> </xsl:template> <xsl:template match="p|div"> <block><xsl:apply-templates/></block> </xsl:template> <xsl:template match="i"> <italic><xsl:apply-templates/></italic> </xsl:template> <xsl:template match="text()"> <xsl:value-of select="."/> </xsl:template> </xsl:stylesheet>
Esce:
$ xsltproc a.xsl a.xml <?xml version="1.0"?> <doc> <block> testo<italic>it</italic> </block> <block>div</block> <block>testo2<italic>altro</italic></block> <block> altro2<italic>ot</italic> </block> <cella> <block>qualcosa</block> </cella> <cella> <block>senza</block> </cella> </doc>