2011-11-10 77 views
0

假設我有下面的XML(這是TEI註釋方案的嵌入到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>

現在我想的是複製所有標註節點到結果的XHTML,但只重命名<title><bibTitle>(如<title><head>只允許),所以就用下面的變換:

<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> 

然而,它不編譯和以下錯誤遊:

Only child:: and attribute:: axes are allowed in match patterns! Offending axes = descendant-or-self

當我改變了比賽規則<xsl:template match="tei:bibl|tei:bibl//*">它開始發揮預期。但是這應該與descendant-or-self::*相同,對吧?我在這裏遇到了變壓器實施限制嗎?

首先我用Mozilla 3.5內部變壓器測試過,然後用Xalan 2.7.1測試 - 結果相同。

回答

2

此限制是模板的匹配模式內的任何位置一步有效。它是由設計(W3C XSLT 1.0XSLT 2.0規範) - 確保有效的XSLT處理。

注意事項:在任何位置步驟之後的謂詞中,可以自由使用任何軸(包括descending-or-self::)。

更新

這裏是在match屬性的xsl:template使用descendant-or-self::軸線的短,完整的例子:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 
<xsl:strip-space elements="*"/> 

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

<xsl:template match="num[descendant-or-self::num > 5]"/> 
</xsl:stylesheet> 

當這種轉變是在下面的XML文檔施加:

<nums> 
<num>1</num> 
<num>2</num> 
<num>3</num> 
<num>4</num> 
<num>5</num> 
<num>6</num> 
<num>7</num> 
<num>8</num> 
<num>9</num> 
<num>10</num> 
</nums> 

想要的結果:任何num元素與值> = 5被刪除:

<nums> 
    <num>1</num> 
    <num>2</num> 
    <num>3</num> 
    <num>4</num> 
    <num>5</num> 
</nums> 
+0

你能否說出你的想法,這個限制究竟是如何影響性能的(通過重寫規則到等同於變壓器必須執行相同的工作)?你能否提供一個例子,說明任何位置步驟後面的*謂詞*(對於我來說,這個斧頭的正確用法是什麼)?謝謝。 –

+0

@dma_k:好的,看我更新的答案。 –

+0

@dma_k:如果您提供了特定的轉換問題(一個XML文檔,所需的結果,規則),那麼我將很高興向您展示如何使用允許的語法指定模板。 –

1

這是由the spec硬性要求:

Although patterns must not use the descendant-or-self axis, patterns may use the // operator as well as the/operator.

+0

你有什麼想法,這個限制的原因是什麼? (無論如何,你可以編寫相應的規則) –

+1

關於「爲什麼」規範的問題表明他們所做的很難回答。準確的答案取決於工作組會議記錄中仔細的歷史研究:是否提供了該設施?如果是,投票結果如何?投票人員是否記錄了他們投票的原因?與其做這項研究,不如提供事後理由:「這就是爲什麼這個決定似乎有意義」。在這種情況下,我認爲唯一的事後理由是,工作組試圖儘可能簡化模式,以提高效率。 –

1

這裏你可以重寫模式變成一個相當於一個不重複的tei:bibl提道:

<xsl:template match="*[ancestor-or-self::tei:bibl]"> 

至於爲什麼限制在那裏,一般的答案是,性能。也許這種限制過於保守,因爲正如你所指出的那樣,在這種情況下重寫後裔或自己是微不足道的。

我經常被這個限制(你可以使用//而不是後代)感到惱火。

+0

謝謝你提供了一個很好的例子,說明如何在謂詞中強迫'祖先或自己::'。我認爲這使得XSLT引擎可以吸引更多:) –

1

這是一個情況下是不夠的:

<a> 
    <b> 
    <c> 
     <c> 
     <c/> 
     </c> 
    </c> 
    </b> 
    <c> 
    <c> 
     <c/> 
    </c> 
    </c> 
</a> 

現在我想只匹配:(。)

*[self::a or self::b][p(.)]/c/descendent-or-self::c 

即如果謂詞p是真實的一個,我想要a/c,a/c/c,a/c/c/c,如果在b上是真的,我想要b/c,b/c/c和b/c/c/c。

但我不想要a/b/c,a/b/c/c等等,只是因爲謂詞匹配a而不匹配b。

如果我做一個匹配模式:

*[self::a or self::b][p(.)]//c 

然後我符合所有的人,我不想。

所以我不得不向後做的支架:

c[ancestor-or-self::c/parent::*[self::a or self::b][p(.)]] 

我想我只是相信自己,這種限制是不是一個真正的合乎邏輯的限制,但是,我認爲理由不進行正確的軸匹配模式的步驟非常蹩腳,因爲當我需要這個時,我需要這個,誰在乎它是否不如我使用更簡單的表達式那樣快。

+0

感謝這個例子。 –

相關問題