XML 命名空間以及它們如何影響 XPath 和 XSLT (Extreme XML)

Dare Obasanjo

Microsoft Corporation

2002 年 5 月 20 日

本文是有望長期發表的系列文章的第一篇,這些文章專門闡釋由 Microsoft 支持的 W3C XML 技術的更微妙的內容。盡管 XML 的核心仍相當簡單,但是圍繞它的技術已經變得日益復雜,而且其中的一些技術需要相當多的專業知識才能掌握。本文以及隨后的其他文章旨在將各種 W3C XML 建議中的信息提取為便于理解的信息,供 XML 用戶和開發人員使用。

在這一系列文章中,第一篇是有關 XML— 命名空間常被誤解的方面。XML 命名空間是 W3C 的大部分 XML 建議和工作草案(包括 XPath、XML 架構、XSLT、XQuery、SOAP、RDF、DOM 和 XHTML)中不可缺少的一方面。對于任何使用 XML 的人來說,了解命名空間如何工作以及它們如何與依賴它們的許多其他 W3C 技術進行交互非常重要。

本文介紹 XML 命名空間的詳細內容,以及它們在支持命名空間的許多 XML 技術上的分支。

本頁內容
XML 命名空間概述XML 命名空間概述
XPath、XSLT 和命名空間XPath、XSLT 和命名空間
XML 命名空間警告XML 命名空間警告
命名空間的未來命名空間的未來

XML 命名空間概述

隨著 XML 在 Internet 上的使用日益廣泛,能夠創建可組合和重用的標記詞匯表(方法類似于軟件模塊的組合和重用)這一優勢變得日益重要。如果已經存在一個定義完善的標記詞匯表,用于描述硬幣集合、程序配置文件或快餐店的菜單,則重用它會比從頭設計一個更有意義。將多個現有的詞匯表組合在一起,以便創建“事物的整體比它各個部分的總和還大”的新詞匯表,也成為 XML 用戶開始需要的一個功能。

但是,在同一個文檔中,來自不同詞匯表的同一個標記(特別是 XML 元素和屬性)可能具有不同的語義,這最終會產生問題。XML 的高度擴展性以及它在 Internet 上的廣泛應用排除了只是將保留的元素或屬性名稱指定為此問題的解決方案。

W3C XML命名空間建議旨在創建一個機制,以便 XML 文檔中來自不同標記詞匯表的元素和屬性可以被明確標識和組合,而無需處理所產生的問題。XML 命名空間建議提供了一種方法,以便基于處理要求對 XML 文檔中的各個項目進行分區,而無需針對應當如何命名這些項目設置過多的限制。例如,名為 <template><output><stylesheet> 的元素可以出現在 XSLT 樣式表中,而對于它們是轉換指令還是轉換的可能輸出沒有二義性。

XML 命名空間是一組由 統一資源標識符 (URI) 引用標識的名稱,這些名稱在 XML 文檔中用作元素名稱和屬性名稱。

命名空間聲明


圖 1. 利用命名空間的 XML 代碼片段

命名空間聲明通常用于將命名空間 URI 映射到特定的前綴。前綴-命名空間映射的作用域包括命名空間聲明作用的元素及其所有的子級。前綴為 xmlns: 的屬性聲明是命名空間聲明。類似屬性聲明的值應當是作為命名空間名稱的命名空間 URI。

在下面的示例 XML 文檔中,根元素包含一個將前綴 bk 映射到命名空間名稱 urn:xmlns:25hoursaday-com:bookstore 的命名空間聲明,它的子元素包含一個 inventory 元素,inventory 元素中包含一個將前綴 inv 映射到命名空間名稱 urn:xmlns:25hoursaday-com:inventory-tracking 的命名空間聲明。

<bk:bookstore xmlns:bk="urn:xmlns:25hoursaday-com:bookstore">
<bk:book>
<bk:title>Lord of the Rings</bk:title>
<bk:author>J.R.R. Tolkien</bk:author>
<inv:inventory status="in-stock" isbn="0345340426"
xmlns:inv="urn:xmlns:25hoursaday-com:inventory-tracking" />
</bk:book>
</bk:bookstore>

在上例中,urn:xmlns:25hoursaday-com:bookstore 命名空間名稱的命名空間聲明作用域是整個 bk:bookstore 元素,而 urn:xmlns:25hoursaday-com:inventory-tracking 的命名空間聲明作用域是 inv:inventory 元素。能夠識別命名空間的處理器可以獨立處理來自這兩個命名空間的項目,這會使其能夠對 XML 文檔執行多層處理。例如,RDDL 文檔是有效的 XHTML 文檔,這些文檔不僅可以由 Web 瀏覽器呈現,而且還包含使用 http://www.rddl.org 命名空間中元素的信息,該命名空間可用于查找有關 XML 命名空間成員的機讀資源。

應當注意的是,按照定義,前綴 xml 綁定到 XML 命名空間名稱,而且這個特殊的命名空間自動在每個格式規范的 XML 文檔中對文檔作用域預先進行聲明。

默認命名空間

有關命名空間聲明的上一節不是完整的,因為它未考慮默認命名空間。默認命名空間聲明是一個屬性聲明,該屬性聲明的名稱是 xmlns,其值是作為命名空間名稱的命名空間 URI。

默認命名空間聲明指定其作用域中所有不帶前綴的元素名稱都來自聲明的命名空間。下面的書店示例使用默認命名空間,而不使用前綴-命名空間映射。

<bookstore xmlns="urn:xmlns:25hoursaday-com:bookstore">
<book>
<title>Lord of the Rings</title>
<author>J.R.R. Tolkien</author>
<inv:inventory status="in-stock" isbn="0345340426"
xmlns:inv="urn:xmlns:25hoursaday-com:inventory-tracking" />
</book>
</bookstore>

在上例中,除 inv:inventory 元素以外的所有元素都屬于 urn:xmlns:25hoursaday-com:bookstore 命名空間。默認命名空間的主要目的是縮短使用命名空間的 XML 文檔。但是,如果對于元素名稱使用默認命名空間,而不使用顯式映射的前綴,可能會導致混淆,因為文檔中的元素不是明顯地屬于命名空間的作用域。

此外,與常規的命名空間聲明不同的是,默認命名空間聲明可以通過將 xmlns 屬性的值設置為空字符串來取消聲明。應當避免取消對默認命名空間聲明的聲明,因為這一做法可能導致在文檔的一部分中,具有屬于某個命名空間且不帶前綴的名稱,但是在另一部分中卻沒有。例如,在下面的文檔中,只有 bookstore 元素來自 urn:xmlns:25hoursaday-com:bookstore,而其他不帶前綴的元素沒有命名空間名稱。

<bookstore xmlns="urn:xmlns:25hoursaday-com:bookstore">
<book xmlns="">
<title>Lord of the Rings</title>
<author>J.R.R. Tolkien</author>
<inv:inventory status="in-stock" isbn="0345340426"
xmlns:inv="urn:xmlns:25hoursaday-com:inventory-tracking" />
</book>
</bookstore>

應當避免這一做法,因為它對于 XML 文檔的讀者會產生非常容易混淆的情況。有關對命名空間聲明取消聲明的詳細信息,請參閱“命名空間的未來”一節。

限定名稱和擴展名稱

限定名稱又稱為 QName,是一個名為本地名稱的 XML 名稱,它的前面可以有另一個名為前綴的 XML 名稱和一個冒號 (':')字符。用作前綴的 XML 名稱和本地名稱必須與產生的 NCName 相匹配,這意味著它們不得包含冒號字符。限定名稱的前綴必須已經通過作用域內的命名空間聲明(將前綴映射到命名空間 URI)映射到命名空間 URI。限定名稱可以用作屬性名稱,也可以用作元素名稱。

盡管 QName 是重要的助記指導,可以幫助確定文檔中的元素和屬性是從哪個命名空間派生的,但是它們對于能夠識別 XML 的處理器無關緊要。例如,下面的三個 XML 文檔將被一系列 XML 技術(當然包括 XML 架構驗證程序)以同樣的方式處理。

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:complexType id="123" name="fooType"/>
</xs:schema>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:complexType id="123" name="fooType"/>
</xsd:schema>
<schema xmlns="http://www.w3.org/2001/XMLSchema">
<complexType id="123" name="fooType"/>
</schema>

W3C XML 路徑語言建議將擴展名稱描述為命名空間名稱和本地名稱對。通用名稱是由 James Clark 創造的一個替換術語,可用來描述同一個概念。通用名稱由命名空間名稱(用大括號括起來)和本地名稱組成。從通用名稱的角度看,命名空間對于人們的意義更大。下面是上面示例中的三個 XML 文檔,但是 QName 被替換為通用名稱。請注意,下面的語法不是有效的 XML 語法。

<{http://www.w3.org/2001/XMLSchema}schema>
<{http://www.w3.org/2001/XMLSchema}complexType id="123" name="fooType"/>
</{http://www.w3.org/2001/XMLSchema}schema>
<{http://www.w3.org/2001/XMLSchema}schema>
<{http://www.w3.org/2001/XMLSchema}complexType id="123" name="fooType"/>
</{http://www.w3.org/2001/XMLSchema}schema>
<{http://www.w3.org/2001/XMLSchema}schema>
<{http://www.w3.org/2001/XMLSchema}complexType id="123" name="fooType"/>
</{http://www.w3.org/2001/XMLSchema}schema>

對許多 XML 應用程序來說,XML 文檔中元素和屬性的通用名稱非常重要,而用在特定 QName 中的前綴的值并不重要。XML 中的命名空間建議之所以沒有使用擴展名稱方法來指定命名空間,主要是因為它很冗長。相反,之所以提供前綴映射和默認命名空間,是為了避免我們因不斷鍵入命名空間 URI 而產生腕管綜合癥。

命名空間和屬性

除非屬性的名稱有前綴,否則命名空間聲明不應用于屬性。在下面顯示的 XML 文檔中,title 屬性屬于 bk:book 元素且沒有命名空間,而 bk:title 屬性將 urn:xmlns:25hoursaday-com:bookstore 作為其命名空間名稱。請注意,即使這兩個屬性具有相同的本地名稱,該文檔的結構也是完整的。

<bk:bookstore xmlns:bk="urn:xmlns:25hoursaday-com:bookstore">
<bk:book title="Lord of the Rings, Book 3" bk:title="Return of the King"/>
</bk:bookstore>

在下例中,即使指定了一個默認命名空間,title 屬性仍然沒有命名空間,且屬于 book 元素。換句話說,屬性不能繼承默認命名空間。

<bookstore xmlns="urn:xmlns:25hoursaday-com:bookstore">
<book title="Lord of the Rings, Book 3" />
</bookstore>

命名空間 URI

按照 RFC 2396 中的規定,命名空間名稱是統一資源標識符 (URI)。URI 是統一資源定位器 (URL) 或統一資源名稱 (URN)。URL 用于指定資源在 Internet 上的位置,而 URN 應該是信息資源持久的、獨立于位置的標識符。對于不同的命名空間名稱來說,只有當它們的每個字符(區分大小寫)都相同時,才被視為相同。之所以將 URI 用作命名空間名稱,主要是因為它們已經提供了一種用來指定全局唯一標識符的機制。

XML 命名空間建議聲明,命名空間名稱只是充當唯一標識符,而不必實際標識可從網絡檢索的資源。這就在 XML 文檔的作者和用戶之間產生了很大的混淆,特別是由于人們已經普遍將基于 HTTP 的 URL 用作命名空間名稱。因為許多應用程序都將這樣的 URI 轉換為超級鏈接,但是當這些“鏈接”無法跳轉到網頁或其他可從網絡檢索的資源時,會令許多用戶感到惱火。我記得有一個用戶將這比作在社交場合中得到了一個假電話號碼。

為了避免使用戶感到混淆,一個解決方案就是使用不暗示資源具有網絡可檢索性的命名空間-命名架構。在編寫供個人使用的 XML 文檔時,我使用 urn:xmlns: 方案來實現此目的,并創建了一個類似于 urn:xmlns:25hoursaday-com 的命名空間名稱。自建命名空間 URI 有一個問題,那就是它們可能會由于全局不唯一而與 XML 中的名稱建議相抵觸。我通過將我的個人域名 http://www.25hoursaday.com 用作命名空間 URI 的一部分來滿足這個全局唯一要求。

另一個解決方案是將可從網絡檢索的資源保留在作為命名空間名稱的 URI(如用 XSLT 和 RDDL 命名空間實現的 URI)處。通常,這樣的 URI 實際上是 HTTP URL。通過使用 W3C 所建議的格式,可以很好地對這樣的 URL 進行命名,如下所示:

      http://my.domain.example.org/product/[year/month][/area]

有關將結構類似的命名空間名稱用作版本控制機制的詳細信息,請參閱“命名空間和版本控制”一節。

有關命名空間的 DOM、XPath 和 XML 信息集

W3C 已經定義了許多可以為 XML 文檔提供數據模型的技術。這些數據模型通常是一致的,但是由于歷史原因,它們在處理各種邊緣案例的方式上有時會有所不同。對 XML 命名空間和命名空間聲明的處理就是邊緣案例的一個示例,在 W3C 建議中的三個主要數據模型中,該案例會以不同的方式進行處理。這三個數據模型是 XPath 數據模型、文檔對象模型 (DOM) 和 XML 信息集。

XML 信息集 (XML infoset) 是對 XML 文檔中數據的抽象說明,它可視為 XML 文檔的主要數據模型。XPath 數據模型是類似于 XML 信息集的基于樹的模型,在查詢 XML 文檔時會遍歷該模型。DOM 優先于 XPath 和 XML 信息集這兩種數據模型,但是它在許多方面也與這兩個數據模型相似。DOM 和 XPath 數據模型可視為對 XML信息集的解釋。

文檔對象模型 (DOM) 中的命名空間

DOM Level 3 規范的 XML 命名空間部分將命名空間聲明視為以 http://www.w3.org/2000/xmlns/ 作為其命名空間名稱的常規屬性節點,并將 xmlns 視為它們的前綴或限定名稱。

DOM 中的元素和屬性有一個無法在創建之后進行修改的命名空間名稱,不管它們在文檔中的位置是否發生改變。

XPath 數據模型中的命名空間

W3C XPath 建議不將命名空間聲明視為屬性節點,而且不提供以該資格訪問它們的權限。相反,在 XPath 中,XML 文檔中的每個元素都有許多可使用 XPath 命名空間導航軸檢索的命名空間節點。

在文檔中每個元素的作用域內,該元素對于每個命名空間聲明都有一組唯一的命名空間節點。在該命名空間中,命名空間節點對于每個元素都是唯一的。因此,代表同一個命名空間聲明的兩個不同元素的命名空間節點是不同的。

XML 信息集中的命名空間

XML 信息集建議將命名空間聲明視為屬性信息項。

另外,與 XPath 數據模型相似的是,XML 文檔信息集內的每個元素信息項,對于該元素作用域內每個命名空間都有一個命名空間信息項目。

返回頁首返回頁首

XPath、XSLT 和命名空間

W3C XML 路徑語言(也稱為 XPath)用于對 XML 文檔的某些部分進行尋址,它可用在許多 W3C XML 技術(包括 XSLT、XPointer、XML 架構和 DOM Level 3)中。XPath 使用類似于文件系統和 URL 中使用的分層尋址機制來檢索 XML 文檔的某些部分。XPath 支持對字符串、數字和布爾值進行基本操作。

XPath 和命名空間

XPath 數據模型將 XML 文檔視為節點(如元素、屬性和文本節點)樹。在節點樹中,每個節點的名稱都由其本地名稱和命名空間名稱(即,它的通用名稱或擴展名稱)組合而成。

對于沒有命名空間的元素和屬性節點,執行 XPath 查詢是相當簡單的。下面的程序可用于從命令行查詢 XML 文檔,并將用來闡釋命名空間對 XPath 查詢的影響。

using System.Xml.XPath;
using System.Xml;
using System;
using System.IO;
class XPathQuery{
public static string PrintError(Exception e, string errStr){
if(e == null)
return errStr;
else
return PrintError(e.InnerException, errStr + e.Message );
}
public static void Main(string[] args){
if((args.Length == 0) || (args.Length % 2)!= 0){
Console.WriteLine("Usage: xpathquery source query <zero or more
prefix and namespace pairs>");
return;
}
try{
//Load the file.
XmlDocument doc = new XmlDocument();
doc.Load(args[0]);
//create prefix<->namespace mappings (if any)
XmlNamespaceManager  nsMgr = new XmlNamespaceManager(doc.NameTable);
for(int i=2; i < args.Length; i+= 2)
nsMgr.AddNamespace(args[i], args[i + 1]);
//Query the document
XmlNodeList nodes = doc.SelectNodes(args[1], nsMgr);
//print output
foreach(XmlNode node in nodes)
Console.WriteLine(node.OuterXml + "\n\n");
}catch(XmlException xmle){
Console.WriteLine("ERROR: XML Parse error occured because " +
PrintError(xmle, null));
}catch(FileNotFoundException fnfe){
Console.WriteLine("ERROR: " + PrintError(fnfe, null));
}catch(XPathException xpath){
Console.WriteLine("ERROR: The following error occured while querying
the document: "
+ PrintError(xpath, null));
}catch(Exception e){
Console.WriteLine("UNEXPECTED ERROR" + PrintError(e, null));
}
}
}

假設下面的 XML 文檔不聲明任何命名空間,則查詢相當簡單,如以下代碼后面的示例所示。

<?xml version="1.0" encoding="utf-8" ?>
<bookstore>
<book genre="autobiography">
<title>The Autobiography of Benjamin Franklin</title>
<author>
<first-name>Benjamin</first-name>
<last-name>Franklin</last-name>
</author>
<price>8.99</price>
</book>
<book genre="novel">
<title>The Confidence Man</title>
<author>
<first-name>Herman</first-name>
<last-name>Melville</last-name>
</author>
<price>11.99</price>
</book>
</bookstore>

示例 1

?
xpathquery.exe bookstore.xml /bookstore/book/title

選擇所有作為 book 元素(其父級為 bookstore 元素)子級的標題元素,并返回如下結果:

   <title>The Autobiography of Benjamin Franklin</title><title>The Confidence Man</title>
?
xpathquery.exe bookstore.xml //@genre

選擇文檔中的所有 genre 屬性并返回如下結果:

   genre="autobiography"genre="novel"
?
xpathquery.exe bookstore.xml //title[(../author/first-name = 'Herman')]

選擇作者名為 "Herman" 的所有標題并返回如下結果:

   <title>The Confidence Man</title>

但是,在將命名空間添加到混合名稱中之后,事情不再那么簡單。除了向某個 book 元素中添加了命名空間和一個屬性以外,下面的文件與原始文件相同。

<bookstore xmlns="urn:xmlns:25hoursaday-com:bookstore"><book genre="autobiography"><title>The Autobiography of Benjamin Franklin</title><author><first-name>Benjamin</first-name><last-name>Franklin</last-name></author><price>8.99</price></book><bk:book genre="novel" bk:genre="fiction"xmlns:bk="urn:xmlns:25hoursaday-com:bookstore"><bk:title>The Confidence Man</bk:title><bk:author><bk:first-name>Herman</bk:first-name><bk:last-name>Melville</bk:last-name></bk:author><bk:price>11.99</bk:price></bk:book></bookstore>

請注意,默認命名空間位于整個 XML 文檔的作用域內,而將前綴 bk 映射到命名空間名稱 urn:xmlns:25hoursaday-com:bookstore 的命名空間聲明只位于第二個 book 元素的作用域內。

示例 2

?
xpathquery.exe bookstore.xml /bookstore/book/title

選擇所有作為 book 元素(其父級為 bookstore 元素)子級的標題元素,這不返回任何結果。

?
xpathquery.exe bookstore.xml //@genre

選擇文檔中的所有 genre 屬性并返回如下結果:

   genre="autobiography"genre="novel"
?
xpathquery.exe bookstore.xml //title[(../author/first-name = 'Herman')]

選擇作者名字為 "Herman" 的所有標題,這不返回任何結果。

第一個查詢之所以不返回任何結果,是因為 XPath 查詢中不帶前綴的名稱應用于沒有命名空間的元素或屬性。在沒有命名空間的目標文檔中沒有 bookstorebooktitle 元素。第二個查詢返回沒有命名空間的所有屬性節點。盡管命名空間聲明位于由該查詢返回的這兩個屬性節點的作用域內,但是由于命名空間聲明不應用于沒有前綴名稱的屬性,所以它們沒有命名空間。出于與第一個查詢同樣的原因,第三個查詢不返回任何結果。

可通過以下方法來執行能夠識別命名空間的 XPath 查詢:提供一個到 XPath 引擎的前綴-命名空間映射,然后在該查詢中使用這些前綴。所提供的前綴不必與目標文檔中的命名空間-前綴映射相同,而且它們必須是非空前綴。

示例 3

?
xpathquery.exe bookstore.xml /b:bookstore/b:book/b:title b urn:xmlns:25hoursaday-com:bookstore

選擇所有作為 book 元素(其父級為 bookstore 元素)子級的標題元素,并返回如下結果:

    <title xmlns="urn:xmlns:25hoursaday-com:bookstore">The Autobiography of Benjamin Franklin</title><bk:title xmlns:bk="urn:xmlns:25hoursaday-com:bookstore">The Confidence Man</bk:title>
?
xpathquery.exe bookstore.xml //@b:genre b urn:xmlns:25hoursaday-com:bookstore

選擇文檔中來自 "urn:xmlns:25hoursaday-com:bookstore" 命名空間的所有 genre 屬性并返回如下結果:

   bk:genre="fiction"
?
xpathquery.exe bookstore.xml //bk:title[(../bk:author/bk:first-name = 'Herman')] bk urn:xmlns:25hoursaday-com:bookstore

選擇作者名為 "Herman" 的所有標題并返回如下結果:

   <bk:title xmlns:bk="urn:xmlns:25hoursaday-com:bookstore">The Confidence Man</bk:title>

注意 示例 3 與示例 1 和 2 相同,但是它被重寫為能夠識別命名空間。

有關使用 XPath 的詳細信息,請閱讀 Aaron Skonnard 的文章 Addressing Infosets with XPath 并查看 ZVON.org XPath tutorial 上的示例。

XSLT 和命名空間

W3C XSL 轉換 (XSLT) 建議描述一種基于 XML 的語言,用于將 XML 文檔轉換為其他 XML 文檔。XSLT 轉換又稱為 XML 樣式表,它使用模式 (XPath) 來與目標文檔的各個方面進行匹配。在與目標文檔中的節點進行匹配時,可以對那些指定成功匹配輸出結果的模板進行實例化,并使用這些模板來轉換文檔。

對命名空間的支持已緊密集成到 XSLT 中,特別是由于 XPath 用于與源文檔中的節點進行匹配。在 XSLT 內部的 XPath 表達式中使用命名空間比使用 DOM 方便得多。

隨后的示例包含:

?

一個用于從命令行執行轉換的程序。

?

一個 XSLT 樣式表,當它在來自 urn:xmlns:25hoursaday-com:bookstore 命名空間的 bookstore 文檔中運行時,打印源 XML 文檔中來自 urn:xmlns:25hoursaday-com:bookstore 的所有 title 元素。

?

得到的輸出結果。

程序

Imports System.Xml.Xsl
Imports System.Xml
Imports System
Imports System.IO
Class Transformer
Public Shared Function PrintError(e As Exception, errStr As String) As String
If e Is Nothing Then
Return errStr
Else
Return PrintError(e.InnerException, errStr + e.Message)
End If
End Function 'PrintError
'Entry point which delegates to C-style main Private Function
Public Overloads Shared Sub Main()
Run(System.Environment.GetCommandLineArgs())
End Sub 'Main
Overloads Public Shared Sub Run(args() As String)
If args.Length <> 2 Then
Console.WriteLine("Usage: xslt source stylesheet")
Return
End If
Try
'Create the XslTransform object.
Dim xslt As New XslTransform()
'Load the stylesheet.
xslt.Load(args(1))
'Transform the file.
Dim doc As New XmlDocument()
doc.Load(args(0))
xslt.Transform(doc, Nothing, Console.Out)
Catch xmle As XmlException
Console.WriteLine(("ERROR: XML Parse error occured because " +
PrintError(xmle, Nothing)))
Catch fnfe As FileNotFoundException
Console.WriteLine(("ERROR: " + PrintError(fnfe, Nothing)))
Catch xslte As XsltException
Console.WriteLine(("ERROR: The following error occured while
transforming the document: " + PrintError(xslte, Nothing)))
Catch e As Exception
Console.WriteLine(("UNEXPECTED ERROR" + PrintError(e, Nothing)))
End Try
End Sub
End Class 'Transformer

XSLT 樣式表

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:b="urn:xmlns:25hoursaday-com:bookstore">
<xsl:template match="b:bookstore">
<book-titles>
<xsl:apply-templates select="b:book/b:title"/>
</book-titles>
</xsl:template>
<xsl:template match="b:title">
<xsl:copy-of select="." />
</xsl:template>
</xsl:stylesheet>

輸出

<?xml version="1.0" ?>
<book-titles xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:ext="urn:my_extensions" xmlns:b="urn:xmlns:25hoursaday-com:bookstore">
<title xmlns="urn:xmlns:25hoursaday-com:bookstore">The Autobiography of
Benjamin Franklin</title>
<bk:title xmlns="urn:xmlns:25hoursaday-com:bookstore"
xmlns:bk="urn:xmlns:25hoursaday-com:bookstore">The Confidence
Man</bk:title>
</book-titles>

請注意,該樣式表中的命名空間聲明結束于輸出 XML 文檔的根節點上。另請注意,XSLT 命名空間未包括在輸出 XML 文檔中。

從 XSLT 轉換的輸出結果生成 XSLT 樣式表有些麻煩,這是由于處理器必須能夠從實際的樣式表指令確定輸出元素。我發現可以通過兩種方法來解決此問題,我將通過顯示一些樣式表來闡釋這兩種方法,這些樣式表生成下面的 XMLT 樣式表作為輸出結果。

<xslt:stylesheet version="1.0"
xmlns:xslt="http://www.w3.org/1999/XSL/Transform">
<xslt:output method="text"/>
<xslt:template match="/"><xslt:text>HELLO WORLD</xslt:text></xslt:template>
</xslt:stylesheet>

第一種方法涉及到創建一個包含要創建的樣式表的變量,然后結合使用 value-ofdisable-output-escaping 屬性來創建該樣式表。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml"  encoding="utf-8"/>
<xsl:variable name="stylesheet">
&lt;xslt:stylesheet version="1.0"
xmlns:xslt="http://www.w3.org/1999/XSL/Transform"&gt;
&lt;xslt:output method="text"/&gt;
&lt;xslt:template match="/"&gt;&lt;xslt:text&gt;HELLO
WORLD&lt;/xslt:text&gt;&lt;/xslt:template&gt;
&lt;/xslt:stylesheet&gt;
</xsl:variable>
<xsl:template match="/">
<xsl:value-of select="$stylesheet" disable-output-escaping="yes" />
</xsl:template>
</xsl:stylesheet>

如果所創建的樣式表可以方便地進行分區,以便放在變量中,則第一種方法非常有效。盡管此方法快速方便,但是它還會歸入雜項 類別,這在面臨需要靈活性的任何情況時往往會變得難以處理。例如,如果在創建新樣式表時涉及到創建許多動態文本并且與樣式表指令交叉在一起,則相對于上面提到的雜項,以下方法會更適合。

<xslt:stylesheet version="1.0" xmlns:xslt="http://www.w3.org/1999/XSL/Transform"
xmlns:alias="http://www.w3.org/1999/XSL/Transform-alias">
<xslt:output method="xml"  encoding="utf-8"/>
<xslt:namespace-alias stylesheet-prefix="alias" result-prefix="xslt"/>
<xslt:template match="/">
<alias:stylesheet version="1.0">
<alias:output method="text"/>
<alias:template match="/"><alias:text>HELLO
WORLD</alias:text></alias:template>
</alias:stylesheet>
</xslt:template>
</xslt:stylesheet>

上面的文檔使用 namespace-alias 指令,將 alias 前綴及其所綁定到的命名空間名稱替換為 xslt 前綴及其所綁定到的命名空間名稱。

命名空間還用于指定擴展 XSLT 的機制。可以創建執行方式與 XSLT 函數相同的、帶有命名空間前綴的函數。同樣,某些命名空間中的元素可被視為對 XSLT 的擴展,并且可以像執行轉換指令(如 templatecopyvalue-of 等)那樣執行。下面是 Hello World 程序的示例,該程序使用基于命名空間的擴展函數來打印簽名問候語。

<stylesheet version="1.0"
xmlns="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:newfunc="urn:my-newfunc">
<output method="text"/>
<template match="/">
<value-of select="newfunc:SayHello()" />
</template>
<msxsl:script language="JavaScript" implements-prefix="newfunc">
function SayHello() {
return "Hello World";
}
</msxsl:script>
</stylesheet>
返回頁首返回頁首

XML 命名空間警告

與任何有用的工具一樣,XML 中的命名空間可能會被錯誤地使用,而且它還具有許多微妙之處,可能會產生問題(如果用戶沒有意識到這些微妙處)。本節重點介紹 XML 命名空間的用戶通常會在哪些方面遇到問題或面臨誤解。

版本控制和命名空間

在實際中,主要有兩種機制來創建不同版本的 XML 實例文檔。一種方法是像在 XSLT 中那樣使用根元素的 version 屬性,另一種方法是將元素的命名空間名稱用作版本控制機制。目前,基于命名空間的版本控制非常普遍,對于 W3C 尤其如此。W3C 已經將該機制用于各種 XML 技術,包括 SOAP、XHTML、XML 架構和 RDF。對于那些使用命名空間控制版本的文檔,其命名空間 URI 通常采用如下格式:

http://my.domain.example.org/product/[year/month][/area]

通過修改后續版本中的命名空間名稱來控制 XML 文檔的版本有一個主要問題,那就是這意味著處理這些文檔的、能夠識別 XML 命名空間的應用程序將不再處理這些文檔,并且將必須進行升級。這主要有益于版本不經常更改的文檔格式,但是如果在更改版本時會修改元素和屬性的語義,則會要求所有的處理器不再處理新版本,以防對它們產生錯誤理解。

另一方面,在許多情況下,讓 XML 文檔的版本控制機制基于根元素的 version 屬性就足夠了。version 屬性主要有益于文檔結構的更改可以向后兼容的情況。在以下情況下,使用 version 屬性都是非常明智的選擇:

?

元素和屬性的語義將不會被修改。

?

對文檔進行更改時涉及到添加元素和屬性,但是很少涉及到刪除它們。

?

應用程序與各種版本的處理軟件之間的互操作性是必需的。

這兩種版本控制方法不是互斥的,它們可同時使用。例如,XSLT 既使用根元素的 version 屬性,又使用版本控制的命名空間 URI。version 屬性用于對 XML 文檔格式進行遞增式向后兼容的更改,而修改命名空間名稱是為了對文檔的語義進行重大的更改。

文檔類型

正如在幾個有關各種 XML 相關郵件列表的哲學爭論中討論的那樣,術語文檔類型 容易引起誤解。在許多情況下,根元素的命名空間名稱可用于確定如何處理文檔,然而,這很難成為一個一般性規則,并且如此聲明會違反 XML 命名空間的精神,因為它們在設計上完全是為了讓開發人員能夠混合和匹配 XML 詞匯表。

Rick Jelliffe 有關 XML-DEV 的帖子簡明扼要,它抓住了為什么認為根命名空間的 URI 等同于文檔類型概念這一問題的本質。這個帖子的本質是,一個 XML 文檔可以有許多不同的類型,包括它的文檔類型(由它的文檔類型定義 (DTD) 指定)、它的 MIME 媒體類型、它的架構定義(由 xsi:schemaLocation 屬性指定)、它的文件擴展名以及它的根元素的命名空間名稱。因此,在許多情況下,根據用戶從哪個角度來檢查文檔,一個文檔將很有可能有許多不同的類型。

RDDL 文檔(示例,請注意,它的根元素來自 XHTML 命名空間)和批注的映射架構(它們的根元素來自 W3C XML 架構命名空間)是 XML 文檔的兩個示例,在這些示例中,如果只是查看根元素的命名空間 URI,就會曲解實際文檔類型。

一言以蔽之,不能通過查看文檔根元素的命名空間 URI 來最終確定文檔的類型。一定要進行思考,否則是非常愚蠢的。

返回頁首返回頁首

命名空間的未來

在 XML 領域中,有許多開發都側重于處理圍繞 XML 命名空間開發而產生的一些問題。首先,當前的 W3C XML 命名空間建議的草案沒有為取消對已映射到前綴的命名空間的聲明提供機制。W3C XML 命名空間 v1.1 工作草案將提供一種機制來取消對實例文檔中前綴-命名空間映射的聲明,以糾正這種疏忽。

對于在試圖取消引用命名空間 URI 的內容時應當返回什么內容存在著爭論,這導致在 XML 領域中引起富有爭議的辯論,并且還成為 W3C 的 Technical Architecture Group 目前爭論的焦點。當前版本的 XML 命名空間建議不要求命名空間 URI 實際上是可解析的,因為命名空間 URI 應當只是一個用作唯一標識符的命名空間名稱,而不是資源在 Internet 上的位置。

Tim Bray(XML 語言和 XML 命名空間建議最初的編輯之一)已經撰寫了一篇詳盡的論文,論述有關命名空間 URI 和命名空間文檔的問題,可以(或者也許不可以)從 URI 中檢索到這些文檔。此文包含在創建資源目錄描述語言 (RDDL) 時涉及到的許多推理。RDDL 設計用于創建命名空間文檔。

Dare Obasanjo 是 Microsoft 的 WebData 組的成員,該小組在 .NET 框架的 System.Xml 和 System.Data 命名空間、Microsoft XML 核心服務 (MSXML) 和 Microsoft 數據訪問組件 (MDAC) 中開發組件。

有關本文的任何問題或評論,歡迎張貼到 GotDotNet 上的 Extreme XML 留言板。

轉到原英文頁面

轉載于:https://www.cnblogs.com/genson/archive/2007/03/16/677575.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/277083.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/277083.shtml
英文地址,請注明出處:http://en.pswp.cn/news/277083.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

帆軟報表(finereport)點擊事件對話框打開

點擊事件對話框打開iframe var iframe $("<iframe id001 name001 width100% height100% scrollingyes frameborder0>") // iframe參數的命名及寬高等iframe.attr("src", "http://192.168.100.17:8075/WebReport/ReportServer?reportlet1.cpt&…

部署虛擬環境

創建虛擬環境 導入Virtualenv虛擬環境模塊 pip install virtualenv python -m pip install virtualenv 創建虛擬環境 cd 項目文件夾 virtualenv 虛擬環境名 激活虛擬環境 cd 虛擬環境文件夾 運行 Scripts 目錄下的 activate 腳本 Scripts\activate 退出當前虛擬環境 Scripts\d…

走馬觀花:Visual Studio Code Name Orcas Mar07CTP /體驗DLINQ

不知道什么叫“Orcas”&#xff1f;簡單說應該就是下一版本的Visual Studio 吧。現在atlas&#xff0c;LINQ&#xff0c;WF之類東西&#xff0c;對于VS2005是單獨安裝的&#xff0c;Orcas應該是全內置吧。還有很多功能的增強&#xff0c;可以參考英文說明。閑話不說&#xff0c…

各種學習資源

C&#xff1a;http://huangdingjun.blog.163.com/ 網易博客 有好多關于C的博文 http://hi.baidu.com/dudiaodaoke/home獨釣刀客 vim&#xff1a;http://easwy.com/blog/ vim linux 牛人 http://www.swaroopch.com/notes/Vim_zh-cn:%E7%A8%8B%E5%BA%8F%E5%91%98%E7%9A%84%E7%BC…

智課雅思詞匯---二十六、形容詞后綴-ble

智課雅思詞匯---二十六、形容詞后綴-ble 一、總結 一句話總結&#xff1a; assemble 英 [?semb(?)l] 美 [?s?mbl] vt. 集合&#xff0c;聚集&#xff1b;裝配&#xff1b;收集vi. 集合&#xff0c;聚集[ 過去式 assembled 過去分詞 assembled 現在分詞 assembling ] 詞根詞…

[導入]C#實現Des加密和解密

文章來源:http://blog.csdn.net/21aspnet/archive/2007/03/24/1540018.aspx 轉載于:https://www.cnblogs.com/zhaoxiaoyang2/archive/2007/03/25/816385.html

帆軟報表(finereport)圖表鉆取詳細類別 當前頁對話框展示

添加參數欄&#xff0c;季度下拉框的控件命名為 jd 這里添加雷達圖做案例 編輯→特效→ 添加JavaScript 參數&#xff1a;wd 值&#xff1a;分類名 #取雷達圖所點擊的點 參數&#xff1a;jd 值&#xff1a;公式$jd #取參數下拉所選參數 JavaScript詳細: var if…

聊聊storm的PartialKeyGrouping

序 本文主要研究一下storm的PartialKeyGrouping 實例 Testpublic void testPartialKeyGrouping() throws InvalidTopologyException, AuthorizationException, AlreadyAliveException {String spoutId "wordGenerator";String counterId "counter";Strin…

ArcGIS Server安裝的幾個問題

今天安裝 了ArcGIS Server &#xff0c;本來一直不愿意裝這么“重”的東西&#xff0c;不過新事物還是要看看。安裝沒有出很大的問題&#xff0c;基本上一次成功&#xff0c;比很久前&#xff08;大概要到03年了吧&#xff09;第一次裝ArcIMS要好多了&#xff0c;那次可是重裝…

大數據之MySql筆記-0916

2019獨角獸企業重金招聘Python工程師標準>>> 復習: 1.MySQL部署 拓展題: rm -rf $MYSQL_HOME/arch/* binlog日志 恢復 主從同步 rm -rf $MYSQL_HOME/data/* 數據 $MYSQL_HOME/scripts/mysql_install_db \ --usermysqladmin \ --basedir/usr/local/mysql \ --dat…

delphi調用c#寫的webservice中文出現亂碼的問題

解決方法&#xff1a;HTTPRIO1的屬性---HttpWebNode--UseUtf8InHeader設置為true 代碼片斷&#xff1a; function TLoginManager.Get_LoginManagerSoap: ILoginManagerSoap; const defSvcLoginManager; defPrtLoginManagerSoap; var RIO: THTTPRIO; begin Result: nil…

浮浮沉沉的上海

來到上海已經快有一年&#xff0c;抱著學習的心態來的&#xff0c;卻發現忘掉了更多&#xff0c;最近一直在回顧&#xff0c;總想把冷卻的技能重新拾回來&#xff0c;卻也發現不簡單。剛剛從餐北斗辭職&#xff0c;也正如朋友所說&#xff0c;趁早走&#xff0c;再遲一點&#…

GridView的操作大全

一、GridView和DataGrid的異同 GridView 是 DataGrid的后繼控件&#xff0c;在.net framework 2 中&#xff0c;雖然還存在DataGrid&#xff0c;但是GridView已經走上了歷史的前臺&#xff0c;取代DataGrid的趨勢已是勢不可擋。GridView和DataGrid功能相似&#xff0c;都是在we…

Sql Server設置用戶只能查看并訪問特定數據庫

1.新建登錄用戶 以管理員身份登陸數據庫&#xff08;權限最高的身份如sa&#xff09;&#xff0c;點擊安全性->登錄名&#xff0c;右鍵新建登錄名&#xff0c;輸入登錄名和密碼&#xff0c;取消強制實施密碼策略。 2.將服務器角色設置為public 注意&#xff1a;很重要的一…

arcgis jsapi接口入門系列(6):樣式

2019獨角獸企業重金招聘Python工程師標準>>> symbol: function () {//線樣式//樣式詳情請看官方文檔let style {//線顏色&#xff0c;支持多種格式&#xff1a;//CSS color string&#xff1a;例如"dodgerblue";//HEX&#xff1a;例如"#33cc33"…

ORM(四)應用.腳本管理工具

ORM(四)應用.腳本管理工具數據腳本的維護,不知道各位有什么好的工具推薦沒有,由于以前一直是用手工來進行腳本的維護操作,很麻煩,而且容易出錯.大多數時候,都在原來的基礎上進行直接修改.今天有點時間就完成了一個簡陋的工具,也是對ORM組件的應用.下面是程序的運行界面http://f…

OpenCV2:應用篇 三維重建

一.簡介 VTK(Visualization Toolkit):開源三維圖形庫 ITK(Insight Segmentation and Registration Toolkit):開源醫學圖像處理庫,包含醫學算法和支持醫學圖片格式DICOM QT:用戶圖形界面 轉載于:https://www.cnblogs.com/k5bg/p/11232131.html

手把手教你搭建Mac環境微信小程序的本地測試服務器

問題的提出 Mac環境方便快捷地搭建小程序的測試服務器 小程序對于網絡請求的URL的特殊要求 不能出現端口號不能用localhost必須用https主要步驟 用json-server搭建簡單的服務器&#xff0c;搭建出來的服務器地址為localhonst:3000安裝nginx進行反向代理&#xff0c;以便隱藏端口…

自定義vue-cli生成項目模板配置(1)

最近在讀《變量》&#xff0c;目前得到的認知之一&#xff1a;慢變量才是決定事物長期發展的因素。 打算自定義vue-cli的腳手架或者根據自己的需要設置項目模板的相關參數&#xff0c;很大程度與慢變量這個概念相關。 當然&#xff0c;我還有一個想法或者認知&#xff1a;我的技…

spring cloud 微服務調用--ribbon和feign調用

這里介紹ribbon和feign調用兩種通信服務調用方式&#xff0c;同時介紹如何引入第三方服務調用。案例包括了ribbon負載均衡和hystrix熔斷--服務降級的處理&#xff0c;以及feign聲明式服務調用。例子包括spring boot項目&#xff0c;用來作為第三方服務供ribbon消費和feign消費客…