Suppose I have the following XML (which is the embedding of TEI annotation scheme into HTML):
<p>(See, for example, <bibl type="journal" xmlns="http://www.tei-c.org/ns/1.0"><author>Greger IH, et al.</author> <date>2007</date>, <title>Trends Neurosci.</title> <biblScope type="vol">30</biblScope> (<biblScope type="issue">8</biblScope>): <biblScope type="pp">407-16</biblScope></bibl>).</p>
Now I want to copy all annotation nodes as is into resulting XHTML but only rename <title>
to <bibTitle>
(as <title>
is only allowed in <head>
), so I used the following transformation:
<xsl:template match="tei:bibl/descendant-or-self::*">
<xsl:variable name="nodeName">
<xsl:choose>
<xsl:when test="name() = 'title'">bibTitle</xsl:when>
<xsl:otherwise><xsl:value-of select="name()" /></xsl:otherwise>
</xsl:choose>
</xsl:variable>
<!-- Changing of the namespace occurs here, but we don't care -->
<xsl:element name="{$nodeName}">
<xsl:copy-of select="@*" />
<xsl:apply-templates />
</xsl:element>
</xsl:template>
<xsl:template match="p/text()|tei:bibl//text()">
<xsl:copy-of select="." />
</xsl:template>
However it does not compile and breaks with following error:
Only child:: and attribute:: axes are allowed in match patterns! Offending axes = descendant-or-self
When I change the match rule to <xsl:template match="tei:bibl|tei:bibl//*">
it starts working as intended. But that should be identical to descendant-or-self::*
, right? Have I hit the transformer implementation limitation here?
First I've tested with Mozilla 3.5 internal transformer, then with Xalan 2.7.1 – same negative result.
It's a hard requirement by the spec:
This limitation is valid only for any location step within the template's match pattern. It is by design (mandated by the W3C XSLT 1.0 and XSLT 2.0 specifications) -- to ensure efficient XSLT processing.
Do note: One can freely use any axis (including
descending-or-self::
) withinin the predicates that follow any location step.Update:
Here is a short, complete example of using the
descendant-or-self::
axis in thematch
attribute ofxsl:template
:when this transformation is applied on the following XML document:
the wanted result: any
num
elements with value >= 5 are deleted:Here's a way you can rewrite the pattern into an equivalent one that doesn't repeat mention of
tei:bibl
:As to why the limitation is there, the general answer, yes, is for performance. Perhaps the limitations are overly conservative, because, as you pointed out, the rewrite of descendant-or-self in this case is trivial.
I regularly get annoyed by this limitation (that you can use // but not descendant).
Here is a case where it is not enough:
now I want to match only:
i.e., if the predicate p(.) is true on a, I want a/c, a/c/c, a/c/c/c and if it is true on b, I want b/c, b/c/c, and b/c/c/c.
But I do not want a/b/c, a/b/c/c, etc. just because the predicate matches on a and not on b.
If I make a match pattern:
then I match all of them which I do not want.
So I have to do it backwards in the bracket:
I think I just convinced myself that this restriction isn't really a logical restriction, however, I think the excuse not to allow proper axis steps in match patterns is pretty lame, because when I need this, I need this, who cares if it is not as fast as if I use simpler expressions.