开发者

using parentheses in xpath/xslt

开发者 https://www.devze.com 2023-03-08 08:32 出处:网络
I\'m trying to use parentheses to override default operator precedence in an xpath expression within an xslt with no luck. For example:

I'm trying to use parentheses to override default operator precedence in an xpath expression within an xslt with no luck. For example:

<?xml version="1.0" encoding="UTF-8" ?>

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:exsl="http://exslt.org/common"
                extension-element-prefixes="exsl"
                version="1.0">

   <xsl:output encoding="utf-8" standalone="yes"/>

   <xsl:template match="/">
      <xsl:apply-templates select="*"/>
   </xsl:template>

   <xsl:template match="@* | node()">
      <xsl:copy>
         <xsl:apply-templates select="@* | node()"/>
      </xsl:copy>
   </xsl:template>

   <!--these should work but don't-->
   <xsl:template match="//(X|Y|Z)/AABBCC"/>
   <xsl:template match="(book/author)[last()]"/>

</xsl:stylesheet>

Visual Studio 2010 won't compile this returning:

Unexpected token '(' in the expression. // -->(<-- X|Y|Z)/AABBCC

Unexpected token '(' in the expression. -->(<-- book/author)[last()]

开发者_C百科

Yet the second example is from MSDN:

http://msdn.microsoft.com/en-us/library/ms256086.aspx

and numerous references say you can use parentheses in this way:

http://saxon.sourceforge.net/saxon6.5.3/expressions.html

http://www.stylusstudio.com/xsllist/200207/post90450.html

http://www.mulberrytech.com/quickref/XSLT_1quickref-v2.pdf

Is this an xpath 1.0 vs 2.0 thing...or is there something else i'm missing? If it's an xpath 2.0 thing, is there a nice xpath 1.0 way to do the same thing?


See @Martin's answer for the key point: that valid patterns are only a subset of valid XPath expressions. In other words, there are many XPath expressions that cannot be used as patterns. (This is something about XSLT that it took me a long time to realize.)

As for valid alternatives:

//(X|Y|Z)/AABBCC

is a valid expression in XPath 2.0, but not in 1.0, because the parentheses cannot begin immediately after the // axis. But in 1.0,

(//X|//Y|//Z)/AABBCC

is a valid alternative expression (but still not a valid pattern). A valid but somewhat awkward pattern would be

*[contains('X Y Z', local-name())]/AABBCC

or

*[self::X | self::Y | self::Z]/AABBCC

As for

(book/author)[last()]

a valid pattern would be

(book/author)[not(following::author[parent::book])]

(But of course

(book/author)[not(following::book/author)]

would not be equivalent, because it would match all <author> children of the last <book> that had any.)


You have to understand that a match attribute of an xsl:template does not allow any XPath expression but rather only so called patterns: https://www.w3.org/TR/1999/REC-xslt-19991116#patterns, a subset of XPath expressions.

So while (book/author)[last()] is a syntactically correct XPath 1.0 expression I don't think it is a syntactically correct XSLT 1.0 pattern, the parentheses are not allowed.

I don't think //(X|Y|Z)/AABBCC is an allowed XPath 1.0 expression (nor a pattern of course) but match="X/AABBCC | Y/AABBCC | Z/AABBCC" should do.

0

精彩评论

暂无评论...
验证码 换一张
取 消