I need an XSL stylesheet that lets me move an XML element to print before the preceding-sibling’s last element
Please, I need your help!!
I need an XSL stylesheet that lets me move an XML element to print before the preceding-sibling’s last element (<tools> or it could be <parts>). My if statement is:
IF (<tools> or <parts>) and <planning> exist in the XML, then MOVE <planning> to print BEFORE (<tools> or <parts>) OTHERWISE just <apply-templates />.
I've tried several things, but I just can't get it to print before <tools> or in some files, it's <parts>.
XML is as follows:
<work>
<prelim>
<code>ABC</code>
<source>DEF</source>
<tools>Includes codes for a table</tools>
</prelim>
<main>
<planning>Text for Planning</planning>
<p>blah blah blah<开发者_Python百科;/p>
</main>
</work>
I want my output to be if the above condition exists:
<work>
<prelim>
<code>ABC</code>
<source>DEF</source>
<planning>Text for Planning</planning>
<tools>Includes codes for a table</tools>
</prelim>
<main>
<p>blah blah blah</p>
</main>
</work>
Can anyone help me on how to achieve this?
Thanks in advance!!
Linda
This stylesheet:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="node()|@*" name="identity">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="tools[not(preceding-sibling::parts)]|
parts[not(preceding-sibling::tools)]">
<xsl:for-each select="../../main/planning">
<xsl:call-template name="identity"/>
</xsl:for-each>
<xsl:call-template name="identity"/>
</xsl:template>
<xsl:template match="planning"/>
</xsl:stylesheet>
Output:
<work>
<prelim>
<code>ABC</code>
<source>DEF</source>
<planning>Text for Planning</planning>
<tools>Includes codes for a table</tools>
</prelim>
<main>
<p>blah blah blah</p>
</main>
</work>
Other approach with modes:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="node()|@*" name="identity">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="tools[not(preceding-sibling::parts)]|
parts[not(preceding-sibling::tools)]">
<xsl:apply-templates select="../../main/planning" mode="copy"/>
<xsl:call-template name="identity"/>
</xsl:template>
<xsl:template match="planning"/>
<xsl:template match="node()|@*" mode="copy">
<xsl:call-template name="identity"/>
</xsl:template>
</xsl:stylesheet>
This transformation:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|@*" name="identity">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match=
"/*/*[1]/*[not(self::tools or self::parts)]
[not(preceding-sibling::*[self::tools or self::parts])]
[last()]">
<xsl:call-template name="identity"/>
<xsl:copy-of select="../following-sibling::*[1]/planning"/>
</xsl:template>
<xsl:template match="planning"/>
</xsl:stylesheet>
when applied on the provided XML document:
<work>
<prelim>
<code>ABC</code>
<source>DEF</source>
<tools>Includes codes for a table</tools>
</prelim>
<main>
<planning>Text for Planning</planning>
<p>blah blah blah</p>
</main>
</work>
produces exactly the wanted, correct result:
<work>
<prelim>
<code>ABC</code>
<source>DEF</source>
<planning>Text for Planning</planning>
<tools>Includes codes for a table</tools>
</prelim>
<main>
<p>blah blah blah</p>
</main>
</work>
Explanation:
The identity rule (template) copies every node "as-is".
Two templates override the identity rule -- one to prevent the "copy inplace" of
planning
, the other to do the actual move operation.The overriding template that performs the move operation has the following properties:
It matches any element that: 1) is a child of the first child of the top element, and 2) is not a
tool
orparts
, and 3) has no preceding sibling that is atool
or aparts
, and 4) is the last of any element that satisfies 1), 2), and 3).The action is simple: this template copies the current node by calling the identity rule by name. Then it copies its "cousin" -- the
planning
child` of the first following sibling of its parent element.
精彩评论