XML和Schema中xmlns,targetNamespace和xsi:schemaLocation的關係和作用
XML的名稱空間:
在w3c的官方說法中,名稱空間提供了避免元素命名衝突的作用,即相同的元素名稱表示不同含義的情況。
這裡就不再舉例詳細說明了,在網上很容易找到。如果要避免重名的衝突,那很明顯的,在xml文件中就可以出現多個不同的名稱空間。
名稱空間的語法:
xmlns:namespace-prefix="namespaceURI"
當名稱空間被定義在元素的開始標籤中時,所有帶有相同字首的子元素都會與同一個名稱空間相關聯,字首可以看做是名稱空間的一個別名;
xmlns:是預設名稱空間。如果不加字首(namespace-prefix),即為預設名稱空間,指定使用該名稱空間的元素及子元素只要不加其他字首,就都是預設名稱空間的元素。
XML Schema:
XML Schema是定義 XML文件的合法構建模組,即定義xml文件中可以出現哪些元素、屬性、元素之間的關係、順序、元素的數量、元素或屬性的型別和值的範圍等等,是對xml文件的一種約束方式。
不過xsd(XML Schema Definition,即XML Schema定義)文件本身也是使用XML語言來寫的。所以它也具有xmlns的屬性。
下面給出一個簡單的xsd文件:
book.xsd
<?xml version="1.0" encoding="UTF-8"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.example.org/book" xmlns="http://www.example.org/book" elementFormDefault="qualified"> <xs:element name="books" type="booksType"/> <xs:complexType name="booksType"> <xs:sequence> <xs:element name="book" type="bookType" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:complexType name="bookType"> <xs:sequence> <xs:element name="name" type="xs:string"/> <xs:element name="author" type="xs:string"/> <xs:element name="price" type="priceType"/> </xs:sequence> <xs:attribute name="id" type="xs:string" use="required"/> </xs:complexType> <xs:simpleType name="priceType"> <xs:restriction base="xs:decimal"> <xs:minExclusive value="0"/> <xs:maxInclusive value="500"/> </xs:restriction> </xs:simpleType> </xs:schema>
targetNamespace:
該屬性聲明瞭本XML Schema文件中定義的元素是屬於targetNamespace屬性指定的名稱空間(URI)下的。
有一個現象,在很多xsd文件中會發現,xmlns和targetNamespace指定的名稱空間值(URI)是一樣的,但其實他們之間的關係並不是固定的。為什麼這樣說呢?
因為targetNamespace聲明瞭在該xsd文件下定義的元素屬於該名稱空間,而xmlns的作用僅僅是指定預設名稱空間。但是,如果在eclipse或idea等IDE工具裡,一個xmlns和targetNamespace的URI相同的xsd文件(比如上面給出的book.xsd),將xmlns或targetNamespace修改的不一致,會發現IDE在該xsd文件引用自定義的元素時會報錯,如下圖,是將上面的文件的targetNamespace修改為“http://www.example.org/book_modify”。
這麼一看它們之間看起來好像又有關聯?
其實是因為當預設名稱空間xmlns和targetNamespace指定的名稱空間一致時,在預設名稱空間下使用的元素(如:type="booksType")是屬於targetNamespace名稱空間下的。所以在這種情況下,當只是修改xmlns或者targetNamespace,使兩者不一致時,IDE工具會發現在xmlns引用的名稱空間下找不到該元素的定義的錯誤。
當然,也可以將預設名稱空間xmlns和targetNamespace給定不一樣的值,用另外加了字首的名稱空間引用targetNamespace的名稱空間下的元素,這樣在使用targetNamespace下定義的元素時需要加上該字首。如下:
book_modify.xsd
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns="http://www.example.org/other"
targetNamespace="http://www.example.org/book"
xmlns:bo="http://www.example.org/book"
elementFormDefault="qualified">
<!--
將xmlns定義為其他值。
增加新的名稱空間xmlns:bo="http://www.example.org/book",其值是targetNamespace的URI。
這樣,要是使用在targetNamespace下定義的元素,需要使用字首bo。
-->
<xs:element name="books" type="bo:booksType"/><!-- 使用了bo字首 -->
<xs:complexType name="booksType">
<xs:sequence>
<xs:element name="book" type="bo:bookType" maxOccurs="unbounded"/><!-- 使用了bo字首 -->
</xs:sequence>
</xs:complexType>
<xs:complexType name="bookType">
<xs:sequence>
<xs:element name="name" type="xs:string"/>
<xs:element name="author" type="xs:string"/>
<xs:element name="price" type="bo:priceType"/><!-- 使用了bo字首 -->
</xs:sequence>
<xs:attribute name="id" type="xs:string" use="required"/>
</xs:complexType>
<xs:simpleType name="priceType">
<xs:restriction base="xs:decimal">
<xs:minExclusive value="0"/>
<xs:maxInclusive value="500"/>
</xs:restriction>
</xs:simpleType>
</xs:schema>
XML中使用Schema例項:
這裡先給出一個使用book.xsd來約束的xml檔案
books.xml
<?xml version="1.0" encoding="UTF-8"?>
<books xmlns="http://www.example.org/book"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.example.org/book book.xsd">
<book id="1001">
<name>Thinking in Java</name>
<author>Bruce Eckel</author>
<price>86.4</price>
</book>
<book id="1002">
<name>Head First 設計模式</name>
<author>Freeman</author>
<price>64.2</price>
</book>
<book id="1003">
<name>深入理解Java虛擬機器</name>
<author>周志明 </author>
<price>59.2</price>
</book>
</books>
在xml文件中,經常看到 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"這樣的名稱空間,那它有什麼作用呢?
它的作用是告知xml文件解析器,用某個schema例項來驗證該xml文件。而且該名稱空間的URI
“http://www.w3.org/2001/XMLSchema-instance”是一個固定值,這個URI指向一個xsd文件,該xsd的targetNamespace的值就是這個URI。同時在xsd中定義了四個屬性,其中有一個屬性的名稱為:schemaLocation,這個屬性在xml文件中也經常用到,如上面的例子中
xsi:schemaLocation="http://www.example.org/book book.xsd"
xsi:schemaLocation的作用:
其語法是:schemaLocation=“{namespaceURI} {xsd名稱}”
字首xsi是自定義的,不過現在大家都習慣了這個官方的習慣。
其作用是告知解析器,schemaLocation指定的名稱空間下的元素要用該xsd的schema來約束。就像該屬性的名稱的字面意義,確定schema的定位。
但是,如果要讓該schema起到作用,需要在xml中使xmlns的URI和該xsd文件的targetNamespace的URI相同。且在schemaLocation中,namespaceURI的值一定要和該xmlns相同,也就是和xsd檔案的targetNamespace相同,這樣,解析器才能準確的知道在該xmlns下的元素要遵循哪個schema。當然也可以在xmlns後加名稱空間的字首,在該字首修飾的元素需要遵循該schema的規範。例如:
books_modify.xml
<?xml version="1.0" encoding="UTF-8"?>
<m:books xmlns:m="http://www.example.org/book"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.example.org/book book.xsd">
<m:book id="1001">
<m:name>Thinking in Java</m:name>
<m:author>Bruce Eckel</m:author>
<m:price>86.4</m:price>
</m:book>
<m:book id="1002">
<m:name>Head First 設計模式</m:name>
<m:author>Freeman</m:author>
<m:price>64.2</m:price>
</m:book>
<m:book id="1003">
<m:name>深入理解Java虛擬機器</m:name>
<m:author>周志明 </m:author>
<m:price>59.2</m:price>
</m:book>
</m:books>
參考連結: