2011-05-26 81 views
10

我想用括號在xslt中重寫xpath中的默認運算符優先級,但沒有運氣。例如:在xpath/xslt中使用圓括號

<?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不會編譯該返回:

意外標記 '(' 在表達// - >(< - X | Y | Z)/ AABBCC 。

意外標記 '(' 在表達 - >(< - 書/作者)[最後()]

然而,第二個例子是從MSDN:

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

,並多次提到說,你可以以這種方式使用括號:

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

這是一個XPath 1.0 VS 2.0的事情...或者是有我失蹤的其他東西?如果它是一個xpath 2.0的東西,是否有一個很好的xpath 1.0方法來做同樣的事情?

回答

9

您必須明白,xsl:templatematch屬性不允許任何XPath表達式,而只允許所謂的模式:http://www.w3.org/TR/xslt#patterns,XPath表達式的子集。

因此,雖然(book/author)[last()]是一個語法正確的XPath 1.0表達式,但我不認爲它是一個語法正確的XSLT 1.0模式,但不允許使用括號。

我不認爲//(X|Y|Z)/AABBCC是允許的XPath 1.0表達式(當然也不是模式),但match="X/AABBCC | Y/AABBCC | Z/AABBCC"應該這樣做。

+0

感謝Martin和Lars ......我現在明白 – user109078 2011-05-26 17:18:11

10

見@馬丁的答案的關鍵點:即有效模式僅適用XPath表達式的一個子集。 (這是一些關於XSLT我花了很長的時間來實現。)

至於有效的替代方案:

//(X|Y|Z)/AABBCC 

是XPath 2.0中有效表達,而不是在1.0,因爲括號不能在//軸後立即開始。但在1.0中,

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

是一個有效的替代表達式(但仍然不是有效的模式)。一個有效的,但有點尷尬模式

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

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

至於

(book/author)[last()] 

一個有效的模式將是

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

(當然

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

不會是等價的,因爲它會匹配最後<book>認爲有任何的所有<author>孩子。)