I have to apply templates for the node present in between two nodes
Ex..
<w:p w:rsidR="00EF034A" w:rsidRDefault="00360D3B">
<w:commentRangeStart w:id="0"/>
<w:r>
<w:t>Comments</w:t>
</w:r>
<w:commentRangeEnd w:id="0"/>
<w:r>
<w:rPr>
<w:rStyle w:val="CommentReference"/>
</w:rPr>
<w:commentReference w:id="0"/>
</w:r>
</w:p>
i have to apply-templates for the nodes present in between commentRangeStart
an开发者_开发问答d commentRangeEnd
. Please help me in writing xslt template. Thanks in advance
Here is a simple XPath 1.0 (XSLT 1.0) solution in addition to the complete answer of Dr. Kay:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:w="w:w">
<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="/">
<xsl:apply-templates select=
"*/w:p/w:commentRangeStart[@w:id=0]
/following-sibling::node()
[following-sibling::w:commentRangeEnd[@w:id=0] ]
"/>
</xsl:template>
</xsl:stylesheet>
when this transformation is applied on the provided XML document (wrapped into a top element, to be well-formed):
<t xmlns:w="w:w">
<w:p w:rsidR="00EF034A" w:rsidRDefault="00360D3B">
<w:commentRangeStart w:id="0"/>
<w:r>
<w:t>Comments</w:t>
</w:r>
<w:commentRangeEnd w:id="0"/>
<w:r>
<w:rPr>
<w:rStyle w:val="CommentReference"/>
</w:rPr>
<w:commentReference w:id="0"/>
</w:r>
</w:p>
</t>
the wanted, correct result (applying the identity template to the selected nodes) is produced:
<w:r xmlns:w="w:w">
<w:t>Comments</w:t>
</w:r>
It looks like you're dealing with parallel/overlapping markup, where the "commentrangestart" and "commentrangeend" elements act as "milestone" tags. There's an extensive literature on handling overlapping markup, and it would be worth your while to spend some time studying the subject.
The details depend a little on whether there is only one commentrange within a parent element, whether the range always starts and ends within the same element, and so on.
In XSLT 2.0 you can often handle such constructs using <xsl:for-each-group group-starting-with="commentrangestart">
or <xsl:for-each-group group-ending-with="commentrangeend">
. You can also use the << and >> operators, for example <xsl:for-each select="*[. >> $start and . << $end]">
.
If you're stuck with XSLT 1.0 it's a lot more difficult, but not impossible. The technique to use (which is worth learning because it's also useful with XSLT 2.0) is called "sibling recursion". You write a template that matches the commentrangestart element and does <xsl:apply-templates mode="sibling" select="following-sibling::*[1]"/>
; you have two template rules in mode="sibling", one which matches the commentrangeend element and terminates the recursion, the other processes the elements in between, and concludes by doing a recursive call <xsl:apply-templates mode="sibling" select="following-sibling::*[1]"/>
精彩评论