xslt & xpath: match directly preceding comments
I am attempting to apply an XSLT transformation to a batch of XML documents. The main point of the transform is to re-order several elements. I wish to preserve any comments that directly precede an element:
<!-- not this comment -->
<element />
<!-- this comment -->
<!-- and this one -->
<element />
The closest I've come to a solution is to use the expression:
<xsl:template match="element">
<xsl:copy-of select="preceding-sibling::comment()"/>
</xsl:templa开发者_运维技巧te>
which grabs too many comments:
<!-- not this comment -->
<!-- this comment -->
<!-- and this one -->
I understand why the aforementioned XPath does not work correctly, but I don't have any good ideas on how to proceed. What I'm looking for is something to select all preceding comments whose following-sibling is either another comment or the current element being processed:
preceding-sibling::comment()[following-sibling::reference_to_current_element() or following-sibling::comment()]
<xsl:template match="element">
<xsl:copy-of select="preceding-sibling::comment()[
generate-id(following-sibling::*[1]) = generate-id(current())
]"/>
</xsl:template>
More efficient:
<xsl:key
name = "kPrecedingComment"
match = "comment()"
use = "generate-id(following-sibling::*[1])"
/>
<!-- ... -->
<xsl:template match="element">
<xsl:copy-of select="key('kPrecedingComment', generate-id())" />
</xsl:template>
I think the best way of putting it would be as follows:
I want the preciding comments but only those with the current node as the first element to follow them.
Then, in xpath1.0/xslt1.0:
<xsl:template match="element">
<xsl:copy-of select="preceding-sibling::comment()[count(following-sibling::*[1]|current()) = 1]"/>
</xsl:template>
精彩评论