XSL to organize nodes in a predefined order in XHTML

I need to arrange nodes in XHTML in a specific predefined order using XSL, while preserving all other transformations inside the nodes. Input file:

<html xmlns="http://www.w3.org/1999/xhtml" lang="en"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> </head> <body class="hresume"> <div id="sec 1"> <div> text 1 <span class="summary">position 1</span> </div> </div> <div id="sec 2"> <div> text 2 <span class="summary">position 2</span> </div> </div> </body> </html> 

XML conversion:

 <?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns="http://www.w3.org/1999/xhtml" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- the identity template --> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <!-- remove summary --> <xsl:template match="xhtml:span[@class='summary']"/> <!-- arrange nodes --> <do-something match="id('sec 2')"/> <do-something match="id('sec 1')"/> </xsl:stylesheet> 

The expected result is simply replacing the "sec 1" and "sec 2" nodes and deleting the "collective" positions. What should be used instead of do-something ?

+4
source share
2 answers

This conversion is :

 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:x="http://www.w3.org/1999/xhtml" > <xsl:output omit-xml-declaration="yes" indent="yes"/> <xsl:strip-space elements="*"/> <xsl:template match="node()|@*"> <xsl:copy> <xsl:apply-templates select="node()|@*"/> </xsl:copy> </xsl:template> <xsl:template match= "*[x:div[@id='sec 1'] and x:div[@id='sec 2']]"> <xsl:copy> <xsl:apply-templates select="@*"/> <xsl:variable name="vDivs" select="x:div"/> <xsl:apply-templates select="$vDivs[2]"/> <xsl:apply-templates select="$vDivs[1]"/> </xsl:copy> </xsl:template> <xsl:template match="x:span[@class='summary']"/> </xsl:stylesheet> 

when applied to the provided XML document :

 <html xmlns="http://www.w3.org/1999/xhtml" lang="en"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> </head> <body class="hresume"> <div id="sec 1"> <div> text 1 <span class="summary">position 1</span> </div> </div> <div id="sec 2"> <div> text 2 <span class="summary">position 2</span> </div> </div> </body> </html> 

produces exactly the necessary, correct result :

 <html xmlns="http://www.w3.org/1999/xhtml" lang="en"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> </head> <body class="hresume"> <div id="sec 2"> <div> text 2 </div> </div> <div id="sec 1"> <div> text 1 </div> </div> </body> </html> 

Please note :

  • The desired special effect is achieved due to the presence of two separate <xsl:apply-templates> instructions specified in the desired order.

  • The required switching of places between two div elements is achieved, even if the second precedes the first - as a result, always the one that was the second (out of two) in the order of the document, now first (out of two) in the order of the document.

+3
source

This solution uses xsl:key and switches the divs, whatever order they provide:

 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:x="http://www.w3.org/1999/xhtml" > <xsl:output omit-xml-declaration="yes" indent="yes"/> <xsl:strip-space elements="*"/> <xsl:key name="sec" match="x:body/x:div[@id]" use="@id"/> <xsl:template match="node()|@*"> <xsl:copy> <xsl:apply-templates select="node()|@*"/> </xsl:copy> </xsl:template> <xsl:template match="x:div[@id='sec 1']"> <xsl:element name="{local-name()}" xmlns="http://www.w3.org/1999/xhtml"> <xsl:apply-templates select="key('sec','sec 2')/*|key('sec','sec 2')/@*"/> </xsl:element> </xsl:template> <xsl:template match="x:div[@id='sec 2']"> <xsl:element name="{local-name()}" xmlns="http://www.w3.org/1999/xhtml"> <xsl:apply-templates select="key('sec','sec 1')/*|key('sec','sec 1')/@*"/> </xsl:element> </xsl:template> <xsl:template match="x:div[@id='sec 2']/*"> <xsl:element name="{local-name()}" xmlns="http://www.w3.org/1999/xhtml"> <xsl:apply-templates select="node()|@*"/> </xsl:element> </xsl:template> <xsl:template match="x:div[@id='sec 1']/*"> <xsl:element name="{local-name()}" xmlns="http://www.w3.org/1999/xhtml"> <xsl:apply-templates select="node()|@*"/> </xsl:element> </xsl:template> <xsl:template match="x:span[@class='summary']"/> </xsl:stylesheet> 
0
source

All Articles