關於Java中XML Namespace 命名空間問題

根據Namespaces in XML W3C 推薦標準的定義,XML命名空間是由國際化資源標識符 (IRI) 標識的 XML 元素和屬性集合;該集合通常稱作 XML“詞匯”。

定義 XML 命名空間的主要動機之一是在使用和重用多個詞匯時避免名稱沖突。XML 模式用於為 XML 實例創建一個詞匯並頻繁使用命名空間。因此,正確理解命名空間概念對於從總體上理解 XML 模式和實例驗證至關重要。

命名空間在多個方面類似於 Java 中的程序包:

  • Java 中的程序包可以包含許多可重用的類和接口。同樣,XML 中的命名空間可以有許多可重用的元素和屬性。
  • 要使用程序包中的類或接口,必須使用程序包名稱完全限定該類或接口。同樣,要使用命名空間中的元素或屬性,必須使用命名空間完全限定該元素或屬性。
  • Java 程序包可能有一個內部類,該類並不直接位於程序包內部,而是借助它的外圍類“屬於”該程序包。命名空間也是如此:某些元素或屬性可能並不直接在命名空間中,而是借助它的父元素或外圍元素而屬於命名空間。這是一個傳遞關系。如果桌子上有一本書,而桌子在地面上,則根據傳遞關系,這本書位於地面上;盡管這本書並非 直接位於地面上。

因此,可以看出 XML 概念中的命名空間與 Java 中的程序包並無多大區別。這種對比旨在簡化對 XML 中命名空間的瞭解,並幫助您直觀認識命名空間的概念。

在本文中,您將瞭解:

  • 命名空間在 XML 中的作用
  • 如何聲明和使用命名空間
  • 默認命名空間與無命名空間之間的區別
  • 如何使用 XML 模式創建命名空間,以及
  • 命名空間中的限定和非限定元素/屬性之間的區別。

聲明和應用命名空間

命名空間被聲明為元素的屬性。並不一定隻在根元素聲明命名空間;而是可以在 XML 文檔中的任何元素中進行聲明。聲明的命名空間的范圍起始於聲明該命名空間的元素,並應用於該元素的所有內容,直到被具有相同前綴名稱的其他命名空間聲明覆蓋—其中,元素內容是指該元素的 <opening-tag> 和 </closing-tag> 之間的內容。命名空間聲明如下:

<someElement xmlns:pfx="http://www.foo.com" />

在屬性xmlns:pfx 中,xmlns類似於一個保留字,它隻用於聲明命名空間。換言之,xmlns用於綁定命名空間,但其本身並不綁定到任何命名空間。因此,以上示例實際上是將前綴“pfx”與命名空間“http://www.foo.com”綁定在一起。

通常將 XSD 或 XS 用作 XML 模式命名空間的前綴,但具體使用什麼前綴完全取決於個人。您可以選擇將前綴 ABC 用於 XML 模式命名空間,這是合法的,但沒有什麼意義。使用有意義的命名空間前綴增強瞭 XML 文檔的清晰性。請註意,前綴隻用作占位符,並且必須通過可以識別命名空間的 XML 分析器進行解釋才能使用綁定到該前綴的實際命名空間。在 Java 類比中,命名空間綁定可以比作聲明一個變量,並且每當引用該變量時,它將被所賦與的值替換。

在上一個命名空間聲明示例中,每當在命名空間范圍中引用前綴“pfx”時,它將被解釋為綁定到實際的命名空間 (http://www.foo.com):

在 Java 中:Stringpfx = "http://www.library.com"

在 XML 中:<someElementxmlns:pfx="http://www.foo.com"/>

盡管命名空間通常看上去像 URL,但這並不意味著實際聲明和使用命名空間時一定要連接到互聯網上。實際上,通常將命名空間用作可以在互連網空間中共享詞匯和不顯示內容的虛擬“容器”。在互連網空間中,URL 是唯一的—因此,您通常選擇使用 URL 來唯一標識命名空間。在瀏覽器中鍵入命名空間 URL 並不意味著它將顯示該命名空間中的所有元素和屬性;它隻是一個概念。

但這裡存在一種誤解:盡管 Namespaces in XML W3C 推薦標準聲明該命名空間名稱應為 IRI,但它對此並無強制規定。因此,我還可以使用以下代碼:

<someElement xmlns:pfx=" foo" />

該代碼完全合法。

至此應明瞭,要使用命名空間,首先應使用前綴綁定將其綁定,然後在需要時使用該前綴。但為什麼不能從一開始便使用命名空間限定元素或屬性呢?首先,由於命名空間(作為 IRI)非常長,因此毫無疑問會使 XML 文檔雜亂不堪。第二,也是最重要的,它可能對語法造成嚴重影響,或者具體一點說,可能對 XML 的生產規則造成嚴重影響—原因是 IRI 可能包含XML 1.0 W3C 推薦標準不允許在 XML 標記中使用的字符。

無效) <http://www.library.com:Book />
有效) <lib:Book xmlns:lib=”http://www.library.com” />

下面的元素 Title 和 Author 與命名空間http://www.library.com關聯:

<?xml version="1.0"?>
<Book xmlns:lib="http://www.library.com">
    <lib:Title>Sherlock Holmes</lib:Title>
    <lib:Author>Arthur Conan Doyle</lib:Author>
</Book>

在下面的示例中,Sherlock Holmes - IIISherlock Holmes - I的元素TitleAuthor與命名空間http://www.library.com關聯,Sherlock Holmes - II的元素TitleAuthor與命名空間http://www.otherlibrary.com關聯。

<?xml version="1.0"?>
<Book xmlns:lib="http://www.library.com">
    <lib:Title>Sherlock Holmes - I</lib:Title>
    <lib:Author>Arthur Conan Doyle</lib:Author>
    <purchase xmlns:lib="http://www.otherlibrary.com">
        <lib:Title>Sherlock Holmes - II</lib:Title>
        <lib:Author>Arthur Conan Doyle</lib:Author>
    </purchase>
    <lib:Title>Sherlock Holmes - III</lib:Title>
    <lib:Author>Arthur Conan Doyle</lib:Author>
</Book>

Namespaces in XML W3C 推薦標準規定瞭某些命名空間約束:

以三字母序列x、ml(采用任何大小寫組合)開頭的前綴被保留,供 XML 和 XML 相關的規范使用。盡管這不是一個嚴重錯誤,但綁定此類前綴並不可取。前綴xml根據定義綁定到命名空間名稱http://www.w3.org/XML/1998/namespace。隻有已聲明並綁定到命名空間的前綴才能使用。(是否曾經試過在 Java 中使用沒有聲明的變量?)

以下代碼違反瞭這些約束:

<?xml version="1.0"?>
<Book xmlns:XmlLibrary="http://www.library.com">
    <lib:Title>Sherlock Holmes - I</lib:Title>
    <lib:Author>Arthur Conan Doyle</lib:Author>
</Book>

[錯誤]:前綴 lib 未綁定到命名空間。
[不可取]:前綴 XmlLibrary 以“Xml”開頭。

單個默認命名空間(而非多個默認命名空間)

重復限定一個要在命名空間中使用的元素或屬性可能會非常麻煩。這種情況下,可以聲明一個 {默認命名空間}。記住,無論在任何時候都隻能存在一個 {默認命名空間}。因此,術語“多個默認命名空間”在實際上是不正確的。

聲明一個 {默認命名空間} 意味著,如果 {默認命名空間} 聲明范圍內的任何元素未使用前綴顯式限定,則該元素將被隱式限定。與帶前綴的命名空間一樣,{默認命名空間} 也可以被覆蓋。{默認命名空間} 聲明如下:

<someElement xmlns="http://www.foo.com"/>
<?xml version="1.0"?>
<Book xmlns="http://www.library.com">
    <Title>Sherlock Holmes</Title>
    <Author>Arthur Conan Doyle</Author>
</Book>

這種情況下,元素Book、TitleAuthor與命名空間http://www.library.com關聯。

記住,命名空間的范圍起始於聲明該命名空間的元素。因此,元素 Book 還與 {默認命名空間}關聯,這是因為它沒有前綴。

<?xml version="1.0"?>
<Book xmlns="http://www.library.com">
    <Title>Sherlock Holmes - I</Title>
    <Author>Arthur Conan Doyle</Author>
    <purchase xmlns="http://www.otherlibrary.com">
        <Title>Sherlock Holmes - II</Title>
        <Author>Arthur Conan Doyle</Author>
    </purchase>
    <Title>Sherlock Holmes - III</Title>
    <Author>Arthur Conan Doyle</Author>
</Book>

在以上的示例中,Sherlock Holmes - IIISherlock Holmes - I的元素BookTitleAuthor與命名空間http://www.library.com關聯,Sherlock Holmes - II的元素 purchase、TitleAuthor與命名空間http://www.otherlibrary.com關聯。

默認命名空間和屬性

默認命名空間不應用於屬性;因此,要將命名空間應用於屬性,必須顯式限定該屬性。此處的屬性isbn{沒有命名空間},而屬性cover與命名空間http://www.library.com關聯。

<?xml version="1.0"?>
<Book isbn="1234"
      pfx:cover="hard"
      xmlns="http://www.library.com"
      xmlns:pfx="http://www.library.com">
    <Title>Sherlock Holmes</Title>
    <Author>Arthur Conan Doyle</Author>
</Book>

取消聲明命名空間

Namespaces in XML 1.0 W3C 推薦標準不允許取消綁定已經綁定的前綴,而 Namespaces in XML 1.1 W3C 推薦標準則允許這樣做。1.0 沒有理由不允許取消綁定,不過該錯誤已經在 1.1 中得到修正。不必知道此差別,這是因為支持 Namespaces in XML 1.1 的 XML 分析器並不多。

盡管取消綁定帶前綴的命名空間有一些差別,但這兩個版本均允許您取消綁定或刪除已聲明的 {默認命名空間}:用其他 {默認命名空間} 聲明(覆蓋聲明中的命名空間為空)覆蓋已聲明的 {默認命名空間}。取消綁定命名空間與未聲明命名空間具有同樣的效果。此處的Sherlock Holmes - IIISherlock Holmes - I的元素Book、TitleAuthor與命名空間http://www.library.com關聯,而Sherlock Holmes - II的元素 purchase、TitleAuthor{沒有命名空間}:

<someElement xmlns="" />
<?xml version="1.0"?>
<Book xmlns="http://www.library.com">
    <Title>Sherlock Holmes - I</Title>
    <Author>Arthur Conan Doyle</Author>
    <purchase xmlns="">
        <Title>Sherlock Holmes - II</Title>
        <Author>Arthur Conan Doyle</Author>
    </purchase>
    <Title>Sherlock Holmes - III</Title>
    <Author>Arthur Conan Doyle</Author>
</Book>

此處是根據 XML 1.0 規范中的命名空間取消綁定前綴的無效示例,而根據 XML 1.1 中的命名空間取消綁定前綴則是有效的:

<purchase xmlns:lib="">

從此處開始,前綴lib不能在 XML 文檔中使用,因為隻要您在元素purchase的范圍內,它就保持未聲名狀態。當然,您完全可以再次定義它。

無名稱空間

如果范圍中沒有默認命名空間,便不存在命名空間。{默認命名空間} 是使用xmlns顯式聲明的命名空間。如果未使用xmlns聲明 {默認命名空間},則不能說元素位於 {默認命名空間} 中。這種情況下,我們可以說元素位於 {無命名空間} 中。當已聲明的 {默認命名空間} 被取消聲明時,也將應用 {無命名空間}。

摘要:

  • 聲明的命名空間的范圍起始於聲明該命名空間的元素,並應用於該元素的所有內容,直到被具有相同前綴名稱的其他命名空間聲明覆蓋
  • 帶前綴的命名空間和 {默認命名空間} 都可以被覆蓋。
  • 帶前綴的命名空間和 {默認命名空間} 都可以被取消聲明。
  • {默認命名空間} 不直接應用於屬性。
  • 僅當顯式聲明 {默認命名空間} 時,該命名空間才存在。如果未聲明默認命名空間,則不應使用術語 {默認命名空間}。
  • 如果范圍中沒有默認命名空間,便不存在命名空間。

命名空間和 XML 模式

到目前為止,我們已經瞭解瞭如何聲明和使用現有命名空間。現在,讓我們瞭解如何創建一個新命名空間,並使用 XML 模式將元素和屬性添加到其中。

XML 模式首先是一個 XML。換言之,同任何其他 XML 文檔一樣,XML 模式使用元素和屬性構建。此“構建材料”必須出自命名空間http://www.w3.org/2001/XMLSchema,它是已聲明和保留的命名空間,其中包含W3C XML 模式結構規范和W3C XML 模式數據類型規范中定義的元素和屬性。不應將元素或屬性添加到該命名空間。

使用這些構建塊,可以根據需要創建新元素和屬性,並對這些元素和屬性附加所需的約束,並將其保留在某個命名空間中。(請參見圖 1。)XML 模式將此特殊命名空間稱作 {目標命名空間},即新建的元素和屬性將駐留到的命名空間。

圖 1:XML 模式命名空間中的元素和屬性用於編寫 XML 模式文檔,

該文檔生成由用戶定義的元素和屬性並將其置於 {目標命名空間} 中。

此 {目標命名空間} 隨後用於驗證 XML 實例。

此 {目標命名空間} 從 XML 實例中引用,以確保實例文檔的有效性。(請參見圖 2。)在驗證過程中,驗證器驗證實例中所用的元素/屬性是否存在於已聲明的命名空間中,並檢查是否對其結構和數據類型存在其他約束。

圖 2:從 XML 模式到 XML 模式實例

限定或未限定

在 XML 模式中,我們可以選擇指定實例文檔是必須限定所有元素和屬性,還是隻限定全局聲明的元素和屬性。無論做出什麼樣的選擇,都將驗證整個實例。那麼,我們為什麼有兩個選擇呢?

答案是“可管理性”。當我們選擇限定時,我們指定實例中的所有元素和屬性都必須有一個命名空間,這將增強實例的命名空間復雜性。比如,當因將某些局部聲明變為全局聲明和/將某些全局聲明變為局部聲明而修改瞭模式時,根本不會影響實例文檔。相反,如果選擇非限定,則指定隻有實例中全局聲明的元素和屬性才必須具有命名空間,從而隱藏實例的命名空間復雜性。但在此情形下,比如,當因將某些局部聲明變為全局聲明和/將某些全局聲明變為局部聲明而修改瞭模式時,將影響所有實例文檔 — 且實例不再有效。如果試圖根據已修改的 XML 模式驗證該實例,則 XML 模式驗證器將報告驗證錯誤。因此,必須根據 XML 模式中所作的修改修正命名空間,才能重新使該實例有效。

<?xml version="1.0" encoding="US-ASCII"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema"
        xmlns:tns="http://www.library.com"
        targetNamespace="http://www.library.com"
        elementFormDefault="qualified">
    attributeFormDefault="unqualified">
    <element name="Book" type="tns:BookType" />
    <complexType name="BookType">
        <sequence>
            <element name="Title" type="string" />
            <element name="Author" type="string" />
        </sequence>
    </complexType>
</schema>

元素<schema>的最近子元素為全局聲明,而其他元素則為局部聲明。在以上示例中,BookBookType被全局聲明,而TitleAuthor則被局部聲明。

可以通過將模式元素屬性elementFormDefaultattributeFormDefault設置為qualified或unqualified 表示在限定和非限定之間的選擇。

elementFormDefault   = (qualified | unqualified) :unqualified
attributeFormDefault = (qualified | unqualified) :unqualified

當將elementFormDefault設置為qualified時,它表示在該語法的實例中,必須使用前綴或通過設置 {默認命名空間} 來顯式限定所有元素。unqualified設置意味著隻有全局聲明的元素才必須被顯式限定,而局部聲明的元素不得被限定。在此情形下,限定一個局部聲明是錯誤的。同樣,將attributeFormDefault設置為qualified時,必須使用前綴顯式限定實例文檔中的所有屬性。

註意,{默認命名空間} 不應用於屬性;因此,不能使用 {默認命名空間} 聲明限定屬性。Unqualified好像暗示通過包含的元素位於命名空間中。這很有趣,對吧?

在下圖中,概念符號空間類似於命名空間分區的非規范性概念。例如,如果將命名空間比作電冰箱,那麼符號空間就是冰箱中的架子。就像架子對電冰箱中的整個空間進行分區一樣,符號空間對命名空間進行分區。

命名空間中有三個主要分區:一個用於全局元素聲明,一個用於全局屬性聲明,一個用於全局類型聲明 (complexType/simpleType)。這種安排表示,全局元素、全局屬性和全局類型可以具有相同的名稱,並可以在{目標命名空間}中共存而不發生任何名稱沖突。此外,每個全局元素和全局 complexType 擁有其自己的符號空間來包含局部聲明。

讓我們來看看屬性對elementFormDefaultattributeFormDefault的四種可能的值組合。

情形 1:elementFormDefault=qualified, attributeFormDefault=qualified

此處,{目標命名空間} 直接包含所有元素和屬性;因此在該情形中,必須限定所有元素和屬性。

情形 2:elementFormDefault=qualified, attributeFormDefault=unqualified

此處,{目標命名空間} 直接包含所有元素,且這些元素的相應屬性包含在相應元素的符號空間中。因此,在該情形中,隻須限定元素,而不得限定屬性,除非屬性是全局聲明的。

情形 3:elementFormDefault=unqualified, attributeFormDefault=qualified

此處,{目標命名空間} 直接包含所有屬性和僅全局聲明的元素,同時這些元素在其符號空間中包含其子元素。因此,在該情形中,隻虛限定全局聲明的元素和所有屬性。

情形 4:elementFormDefault=unqualified, attributeFormDefault=unqualified

此處,{目標命名空間} 直接包含僅在全局聲明的元素,同時這些元素在其符號空間中包含其子元素。每個元素在其符號空間中包含相應的屬性;因此,在該情形中,隻需限定僅在全局聲明的元素和屬性。

以上各圖用於直觀說明命名空間內直接包含的內容或傳遞式包含的內容(取決於elementFormDefault/attributeFormDefault的值)。該設置表示直接位於{目標命名空間}中的元素/屬性必須在相應的 XML 實例中擁有一個與其關聯的命名空間,而未直接(傳遞式)位於{目標命名空間}中的元素/屬性不得在相應的 XML 實例中擁有一個與其關聯的命名空間。

目標命名空間和無目標命名空間

現在,我們知道 XML 模式創建新元素和屬性並將其置於稱作 {目標命名空間} 的命名空間中。但如果在該模式中未指定 {目標命名空間} 又會怎麼樣?如果未指定屬性targetNamespace,則將不存在 {目標命名空間} — 這是合法的 —但在targetNamespace屬性中指定一個空 URI 則是“非法”的。

例如,以下代碼無效。不能為 {目標命名空間} 指定一個空 URI:

<schematargetNamespace="". . .>

在此情形中,如果不存在 {目標命名空間},則如前所述,則將新建的元素和屬性保存在 {無命名空間} 中。(使用術語 {默認命名空間} 是錯誤的。)要驗證相應的 XML 實例,相應的 XML 實例必須使用http://www.w3.org/2001/XMLSchema-instance命名空間中的noNamespaceSchemaLocation屬性來引用沒有目標命名空間的 XML 模式。

結論

衷心希望此命名空間概述能夠幫助您更輕松地遷移到 XML 模式。Oracle XML 開發人員工具包 (XDK) Namespaces in the XML 1.0 W3C 推薦標準中的 W3C 命名空間;您可以通過使用SAXParserFactoryDocumentBuilderFactory類中的setNamespaceAware(boolean)方法打開/關閉命名空間檢查(使用 Oracle XDK 中的 JAXP API)。

參考:XML 模式:瞭解命名空間 http://www.oracle.com/technetwork/cn/articles/srivastava-namespaces-098626-zhs.html

到此這篇關於Java中XML Namespace 命名空間的文章就介紹到這瞭,更多相關XML Namespace 命名空間內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

到此這篇關於Java中XML Namespace 命名空間的文章就介紹到這瞭,更多相關XML Namespace 命名空間內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: