2009-12-29 55 views
21

我對XSLT應用模板聲明感到困惑。例如,在w3school中。XSLT應用模板問題

http://www.w3schools.com/xsl/xsl_apply_templates.asp

對於報表,

<xsl:template match="/"> 
    <html> 
    <body> 
    <h2>My CD Collection</h2> 
    <xsl:apply-templates/> 
    </body> 
    </html> 
</xsl:template> 

我的困惑是,

(1)什麼是<xsl:apply-templates/>功能?它不包含任何特定的模板來調用。我認爲它會匹配(返回)當前元素的所有直接子元素(當前節點的非直接子元素不會返回,當前節點是根節點),不知道我是否正確? (2)在(1)中返回所有匹配的節點之後,XSLT處理器將執行的下一步是什麼?

(3)在這個特定的示例中,根節點是根目錄還是另一個更高級別的根?爲什麼?

由於事先 喬治

回答

47

一些事情,這將使這些答案的理解您可以更容易:

首先,節點和元素是不一樣的東西。元素是節點,但節點不一定是元素。您經常會發現人們交替使用這些術語。 XML中實際上有四種節點:元素,文本節點,處理指令和註釋。 (屬性並不是真正的節點,我將在第二時間完成。)

在XSLT中,XML文檔的根不是它的頂層元素;根是一種實際上並不存在的抽象。頂層元素是根的孩子。例如,這裏有一個良好的XML文檔,其根有五個子節點,包括頂級元素:

<?xml-stylesheet href="mystyle.css" type="text/css"?> 
<!-- this is a perfectly legitimate XML document --> 
<top_level_element/> 

五?看起來只有三個。我想我會讓你弄清楚其他兩個是你自己的。提示:在這個例子中實際上可能有七個節點。

XPath表達式/找到文檔根,而不是頂級元素。在上述情況下,要查找頂級元素,請使用/top_level_element/*。 (使用/*來查找頂級元素總是安全的,因爲文檔根目錄必須有一個元素子元素。)

因此,我們來看看apply-templates的功能。它基本上執行兩個步驟:首先,它構建一組節點。然後,對於每一個,它都會找到一個匹配的模板(從XSLT文件中的模板中找到)並將模板應用到它。正如您在其中一條評論中觀察到的那樣,它在概念上與循環非常相似。

select屬性用於第一步。它提供了一個XPath表達式,用於構建將要應用模板的節點集。如果沒有提供select屬性,則它構建的列表是上下文節點的所有子節點。 (「上下文節點」是當前模板正在應用的節點。)

template元素上的match屬性用於第二步。樣式表處理器查找所有模板,其match屬性與其嘗試應用模板的節點相匹配。如果它找到多於一個,則它選擇它可以最特定的一個,例如,考慮到這些模板:

<xsl:template match="*"/> 
<xsl:template match="foo"/> 
<xsl:template match="foo[bar]"/> 

bar子元素foo元素將第三匹配,沒有bar一個foo元素將被第二匹配,和一個baz元素將通過首次匹配。 (XSLT使用的實際方法定義爲here;實際上,我已經使用XSLT將近十年了,但我從未需要知道它是如何工作的,儘管它很有趣。)

如果它找到匹配,它將使用內置的默認模板爲節點的類型 - 基本上,你可以假設任何XSLT轉換隱含地包含了這些模板:

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

<xsl:template match="text()"> 
    <xsl:copy/> 
</xsl:template> 

<xsl:template match="processing-instruction() | comment() | @*"/> 

武裝用這些知識,你現在可以瞭解身份變換:

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

匹配任何節點或屬性(請注意,屬性不是節點,這就是爲什麼需要@*),複製它,然後將模板應用於其所有子節點和屬性。 (只有文檔根目錄和元素纔會有子節點,並且只有元素將具有屬性。)由於它是變換中唯一的模板,並且它匹配所有節點和屬性,所以它將自身應用於所有子節點和屬性。因此,它將源樹中的所有內容複製到輸出樹中。

如果這個模板添加到識別轉換:

<xsl:template match="foo"/> 

你現在有一個變換拷貝源代碼樹每個節點除了foo元素 - 這第二個模板匹配foo元素(第一個也是如此,但由於第二個屬性更具體,它是XSLT選擇的一個),並且對它們不做任何處理。

鑑於這一切,在回答您的具體問題:

  1. <xsl:apply-templates>適用模板上下文節點的孩子。

  2. 在步驟1中不匹配匹配的節點; XSLT處理器爲每個處理器找到一個模板並應用它。

  3. 在此示例中,上下文節點是文檔根,頂層元素以及其外部的任何註釋或處理指令都是子級的抽象節點。

+0

聲明「屬性不是真正的節點」是不正確的。屬性是節點,但屬性不是元素的子節點。有關更多詳細信息,請參閱下面的答案。 只爲兒童執行模板(axis child :),但不能用於屬性(axis attribute :): – 2017-11-27 18:48:27

1

XSL:申請模板指導XSLT引擎來匹配做進一步處理樣式模板的電流源文檔的子節點。

+0

「匹配當前源文檔子節點」 - 在w3school示例中,什麼是「當前源文檔子節點」?並且將搜索xslt文件中定義的哪些模板以匹配「當前源文檔子節點」? – George2 2009-12-29 17:56:00

+1

由於到目前爲止只有根目錄已經匹配,所以它將是所有的cd節點。示例中的所有模板都是匹配的候選對象。 – 2009-12-29 18:02:18

1

1)<xsl:apply-templates/>調用遍歷所有子節點(子節點)並調用匹配模板(如果有的話)。

2)之後的所有節點都匹配之後的行被輸出在這種情況下是

</body> 
</html> 

3)在這個例子中的目錄爲根節點。

+0

1。對於1,我能理解它是在兩層循環(外循環+內循環)中實現的嗎?外循環是foreach子節點,內循環是針對當前xslt文件中定義的每個模板(即對於每個子節點,處理引擎將嘗試查找當前xslt文件中定義的匹配模板)? 2.如果發現多個模板匹配,會發生什麼? – George2 2009-12-29 17:58:19

+1

您可以舉一個例子,其中多個模板可以匹配一個節點嗎?據我所知,這將是一個xslt錯誤,你的xslt不會在這種情況下編譯。 – 2009-12-30 04:07:38

3
  1. <xsl:apply-templates />將嘗試找到匹配當前節點及其子節點的模板。
  2. 所有匹配的節點之後返回,XSL處理器將輸出那些結束標記(即</body></html>
  3. 有一個根節點,只是目錄之前,通過"/"

EDIT匹配:一種例子來澄清1.;考慮your provided sample

<?xml version="1.0"?> 
<xsl:stylesheet version="1.0" 
       xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

    <xsl:template match="/"> 
     Here we're at "root" node, just before "catalog" element.<br /> 
     Let's enumerate this child nodes: 
     <ul> 
     <xsl:for-each select="*"> 
      <li><xsl:value-of select="name()" /></li> 
     </xsl:for-each> 
     </ul> 
     <!-- Now, process "catalog" and ALL his child nodes --> 
     <xsl:apply-templates/> 
    </xsl:template> 

    <xsl:template match="cd"> 
     <p> 
     <!-- Find a template ONLY for title element --> 
     <xsl:apply-templates select="title"/> 
     <xsl:apply-templates select="artist"/> 
     </p> 
    </xsl:template> 
</xsl:stylesheet> 
+0

「將嘗試找到匹配當前節點的模板」 - 當前節點或當前節點?哪些模板將被搜索匹配?所有在xslt文件或? – George2 2009-12-29 17:54:06

+0

「結束標籤」 - 什麼是結束標籤?你能用其他一些詞來形容嗎? – George2 2009-12-29 17:54:40

0
  • XML元素有孩子屬性。對於下面的XML,元素孩子::作者(不久作者)和屬性::第一(不久@First

    <?xml version="1.0" encoding="UTF-8"?> <book> <author first="tom">Smith</author> </book>

  • 的xsl:申請-templates意味着爲所有匹配節點的孩子執行模板,所以對於下面的模板,執行模板作者,但不適用於@firs t

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

  • 文本()節點史密斯是件作者的孩子,所以XSL:申請模板將調用模板的文本()節點:

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