Testing for preceding-sibling and matching descendant using xsl:key
I have a problem that I believe I need to use grouping using xsl:key to solve, but I am at a loss as to the correct syntax. For the following XML, when I process each <a/>
element I need to test to see if
the element has a preceding-sibling
<markerStart/>
element and a descendant</markerEnd>
element with the same id.- By "p开发者_StackOverflow中文版receding-sibling" I mean that there must not be an
<a/>
between the current element and the<markerStart/>
, so the<a/>
marked<!-- # 5 -->
should return false, while the<a/>
marked<!-- # 1 -->
and the first<a/>
following the element marked<!-- # 2a -->
should return true. - By "descendant" I mean that there must not be an
<a/>
descendant before the<markerEnd/>
, so the<a/>
marked<!-- # 0 -->
and the first<a/>
following the element marked<!-- # 2b -->
should return false.
- By "p开发者_StackOverflow中文版receding-sibling" I mean that there must not be an
OR the element has a descendant
<markerStart/>
element and a descendant</markerEnd>
element with the same id.- By "descendant" I mean that there must not be an
<a/>
descendant before the<markerEnd/>
.
- By "descendant" I mean that there must not be an
For the following XML, I would expect the nodes marked with <!-- # 1 -->
, <!-- # 2a -->
, and <!-- # 4 -->
to return true.
<root>
<a><!-- # 0 -->
<b>
<c>
<markerStart id="a1"/>
<a> <!-- # 1 -->
<b>
<c>
<markeEnd id="a1"/>
</c>
</b>
</a>
<markerStart id="a2"/><!-- # 2a -->
<markerStart id="a3"/><!-- # 2b -->
<a><!-- # 2 -->
<b>
<c>
<markeEnd id="a2"/>
<a><!-- # 3 -->
<b>
<c>
<markeEnd id="a3"/>
</c>
</b>
</a>
</c>
</b>
</a>
<markerStart id="a5"/>
<a><!-- # 4 -->
<markerStart id="a4"/>
<b>
<c>
<markeEnd id="a4"/>
</c>
</b>
</a>
<a><!-- # 5 -->
<b>
<c>
<markeEnd id="a5"/>
</c>
</b>
</a>
</c>
</b>
</a>
</root>
I need to used XSL 1.0 for this problem. Any help is more than appreciated.
This stylesheet:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:key name="kMarkerStartByFollowingMarkeEnd"
match="markerStart"
use="generate-id(following::markeEnd[1])"/>
<xsl:key name="kMarkeEndByAncestorA"
match="markeEnd"
use="generate-id(ancestor::a[1])"/>
<xsl:template match="a[key('kMarkeEndByAncestorA',
generate-id()
)[1]/@id =
key('kMarkerStartByFollowingMarkeEnd',
generate-id(key('kMarkeEndByAncestorA',
generate-id()
)[1])
)/@id]">
<xsl:copy-of select="comment()"/>
<xsl:apply-templates/>
</xsl:template>
</xsl:stylesheet>
Output:
<!-- # 1 --><!-- # 2 --><!-- # 4 -->
精彩评论