xsl - tag position with text mixed in parent
In XSL 1.0, I am trying to distinguish between the following 2 scenarios which both occur within the input XML I need to process and each to be handled differently.
Scenario 1
<tag1><tag2/> some text</tag1>
Scenario 2
<tag1>some text <tag2/></tag1>
I have a template which matches at the <tag2/>
level, within this I want scenario 1 to ignore <tag2/>
, in scenario 2 I want to insert a <br/>
in place of <tag2/>
.
I have searched on here and on google but can't seem to figure out how to distinguish based on the position of <tag2/>
within <tag1>
.
I have looked into preceding-sibling and generate-id and tried to use something like:-
not(
generate-id(
preceding-sibling::nod开发者_运维技巧e()[1]
)
= generate-id(
preceding-sibling::text()[1]
)
)
and the
position()
of <tag2/>
doesn't seem to help here either as both appear to be operating at the node level??
Any ideas would be welcomed?
Thanks Roger
Look at these patterns:
node()[1]
This match first node child.
node()[1][self::tag2]
This match first node child which is also a tag2
element.
node()[not(self::text()[not(normalize-space())])][1][self::tag2]
This match first node child which is not a whitespace only text node and also a tag2
element (in case you preserve whitespace only text node as you should with XHTML input).
I give you this approach because the first and second patterns are streamable (preceding
axis is not streamable).
Note: The second must be rewrite as node()[position() = 1 and self::tag2]
.
The following stylesheet:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="tag2[preceding-sibling::text()]">
<br/>
</xsl:template>
</xsl:stylesheet>
On this input:
<items>
<tag1><tag2/>some text</tag1>
<tag1>some text <tag2/></tag1>
</items>
Produces:
some text
some text <br/>
A more complex solution would require additional information about the desired output.
A simpler and more fundamental solution:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match=
"node()[self::tag2 and position()=1]"/>
<xsl:template match=
"node()[self::tag2 and position()=2]">
<br/>
</xsl:template>
</xsl:stylesheet>
When applied on this XML document:
<tag1><tag2/> some text</tag1>
produces the wanted, correct result:
<tag1> some text</tag1>
When applied on this document:
<tag1>some text <tag2/></tag1>
again the wanted, correct answer is produced:
<tag1>some text <br/>
</tag1>
Explanation:
The identity rule (template) copies every node as-is.
The first template that is overriding the identity rule matches any node whose name is
tag2
and whose position in the node-list is 1. It has no body so thetag2
element is ignored.The second template that overrides the identity rule is similar to the first, but the position of the matched
tag2
node has to be 2. In this case it is replaced by<br/>
.
精彩评论