Reputation:
I'm trying to match all a/c
elements that have a b
sibling. I've tried:
<xsl:template match="a/b/../c">
but I get "Cannot convert the expression {..} to a pattern" from Saxon.
My XSLT/XPath skills are basic at best...
Upvotes: 4
Views: 518
Reputation: 28014
<xsl:template match="a[b]/c">
Explanation: match any c
element that is a child of an a
element that has a b
child.
You should also be able to use ..
in a predicate:
<xsl:template match="a/c[../b]">
which is similar to what you were trying.
The reason you can't use ..
directly in a match pattern (i.e. outside of a predicate) is that patterns are not XPath expressions, even though they look and behave very similarly. In particular, only "downward" axes (child::
, descendant::
, and attribute::
) are allowed directly in patterns. (The only explicit axes allowed by the spec are child::
and attribute::
. descendant::
is implicitly allowed via the //
between pattern steps. Saxon seems to bend the rules a bit here, allowing an explicit descendant::
axis, and even descendant-or-self::
!)
The reason given for the restriction on axes is that (a) other axes are rarely needed in patterns, and (b) this allows XSLT processors to be much more efficient in testing for matches.
But predicates in patterns are defined with the same syntax rules as in XPath expressions (with some restrictions in XSLT 1.0, like not allowing variable references or current()
). So you can use other axes, like parent::
, or the abbreviation ..
.
Upvotes: 5
Reputation: 65871
This XPath expression seems to do the job (may be not optimal):
//a|//c[following-sibling::b or preceding-sibling::b]
Edit:
In case LarsH is right, it should be //a/c
instead of //a|//c
.
Upvotes: 1