由于项目需要对大量的XML文件进行处理,而自己当时的XML知识还仅限在怎么编写XML实 例文档,使用简单的XPath对XML文档进行搜索,而对于XML模式、XLST没有任何概念。一句话就是XML的相关知识还是相当的匮乏,所以下决心开 始学习XML比较深入的知识,而此次的XML学习之旅将从XML模式开始。并将此学习过程中的一些心得总结出来,以供大家分享。文中有不当之处,望前辈指 点一二:)
一、XML中命名空间的作用
之前每当自己编写XML实例文档时总是会被命名空间所困扰,不明白它的意义和作用,但是好像 对自己编写XML实例文档也没有什么影响,所以也没有深入的去理解它。其实XML里的命名空间的作用与其它语言(如C#)中命名空间的作用差不多:为命名 提供一个容器,只要在该容器中没有相同的命名就可以避免命名冲突。在不同的命名空间里的相同的命名会被解析成两个不同的命名。下面的示例中定义了两个 XML模式和一个XML实例文档
n1schema.xsd
<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="n1schema"
targetNamespace="http://tempuri.org/n1schema.xsd"
elementFormDefault="qualified"
xmlns="http://tempuri.org/n1schema.xsd"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
>
<xs:complexType name="Address">
<xs:sequence>
<xs:element name="Country" type="xs:string"></xs:element>
<xs:element name="Province" type="xs:string"></xs:element>
<xs:element name="City" type="xs:string"></xs:element>
</xs:sequence>
</xs:complexType>
</xs:schema>
n2schema.xsd
<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="n2schema"
targetNamespace="http://tempuri.org/n2schema.xsd"
elementFormDefault="qualified"
xmlns="http://tempuri.org/n2schema.xsd"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
>
<xs:complexType name="Address">
<xs:sequence>
<xs:element name="Country" type="xs:string"></xs:element>
<xs:element name="State" type="xs:string"></xs:element>
<xs:element name="City" type="xs:string"></xs:element>
</xs:sequence>
</xs:complexType>
</xs:schema>
multiNamespaceTest.xml
<?xml version="1.0" encoding="utf-8" ?>
<root xmlns:n1="http://tempuri.org/n1schema.xsd"
xmlns:n2="http://tempuri.org/n2schema.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<billTo xsi:type="n1:Address">
<n1:Country>China</n1:Country>
<n1:Province>Jiangsu</n1:Province>
<n1:City>Nanjing</n1:City>
</billTo>
<shipTo xsi:type="n2:Address">
<n2:Country>USA</n2:Country>
<n2:State>IL</n2:State>
<n2:City>Chicago</n2:City>
</shipTo>
</root>
在n1shema.xsd和n2schema.xsd中都定义了一个复杂类型 Address,然后在multiNamespaceTest.xml实例文档中引入前两个XML模式定义的命名空间,我们可以看到billTo元素定义 为n1schema.xsd中定义的Address类型,而shipTo元素定义为n2schema.xsd中定义的Address类型,在 multiNamespaceTest.xml中这两个Address类型并不会相互冲突。
二、XML模式创建的命名空间
从上面的n1schema.xsd和n2schema.xsd中可以看出,它们的schema元素都定义了targetNamespace属性(参考W3C描述),该属性就定义了该XML模式所创建的命名空间,所有在该XML模式中声明的元素和定义的类型、属性都处于该命名空间内,这样在引用该命名空间的XML文档就可以引用那些元素和类型、属性了。
n1shema.xsd和n2schema.xsd的根元素xs:schema还可以定义elementFormDefault和attributeFormDefault属性(参考W3C描述), 它们的值只能是qualified或unqualified,它们的默认值都是unqualified。elementFormDefault属性用于设 定该XML模式创建的命名空间中的局部元素和类型被引用时是否需要指定的前缀;attributeFormDefault属性用于设定该XML模式创建的 命名空间中的属性被引用时是否需要指定的前缀。
qualifiedSchema.xsd——两个属性都设为qualified
<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="qualifiedSchema"
targetNamespace="http://tempuri.org/qualifiedSchema.xsd"
elementFormDefault="qualified" attributeFormDefault="qualified"
xmlns="http://tempuri.org/qualifiedSchema.xsd"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
>
<xs:element name="books" type="BooksType"></xs:element>
<xs:complexType name="BooksType">
<xs:sequence>
<xs:element name="book" type="BookType" minOccurs="1" maxOccurs="unbounded"></xs:element>
</xs:sequence>
</xs:complexType>
<xs:complexType name="BookType">
<xs:sequence>
<xs:element name="ISBN" type="xs:string"></xs:element>
<xs:element name="Name" type="xs:string"></xs:element>
</xs:sequence>
<xs:attribute name="Category" type="xs:string"></xs:attribute>
</xs:complexType>
</xs:schema>
qualifiedTest.xml
<?xml version="1.0" encoding="utf-8" ?>
<q:books xmlns:q="http://tempuri.org/qualifiedSchema.xsd">
<q:book q:Category="Computer">
<q:ISBN>7115134162</q:ISBN>
<q:Name>C++ Primer Plus(第五版)</q:Name>
</q:book>
<q:book q:Category="Computer">
<q:ISBN>7115134162</q:ISBN>
<q:Name>C++ Primer Plus(第五版)</q:Name>
</q:book>
</q:books>
由上可以看到qualifiedTest.xml中引用qualifiedSchema.xsd中定义的属性和元素时都加上了q:前缀。而下面的两段代码显示了elementFormDefault和attributeFormDefault属性设为unqualified的情形
unqualifiedSchema.xsd——两个属性都是用默认值unqualified
<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="unqualifiedSchema"
targetNamespace="http://tempuri.org/unqualifiedSchema.xsd"
xmlns="http://tempuri.org/unqualifiedSchema.xsd"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
>
<xs:element name="books" type="BooksType"></xs:element>
<xs:complexType name="BooksType">
<xs:sequence>
<xs:element name="book" type="BookType" minOccurs="1" maxOccurs="unbounded"></xs:element>
</xs:sequence>
</xs:complexType>
<xs:complexType name="BookType">
<xs:sequence>
<xs:element name="ISBN" type="xs:string"></xs:element>
<xs:element name="Name" type="xs:string"></xs:element>
</xs:sequence>
<xs:attribute name="Category" type="xs:string"></xs:attribute>
</xs:complexType>
</xs:schema>
unqualifiedTest.xml
<?xml version="1.0" encoding="utf-8" ?>
<q:books xmlns:q="http://tempuri.org/unqualifiedSchema.xsd">
<book Category="Computer">
<ISBN>7115134162</ISBN>
<Name>C++ Primer Plus(第五版)</Name>
</book>
<book Category="Computer">
<ISBN>7115134162</ISBN>
<Name>C++ Primer Plus(第五版)</Name>
</book>
</q:books>
但是,无论 elementFormDefault和attributeFormDefault属性设为qualified还是unqualified,引用XML模式中定义的全局元素都必须加上q:前缀(有种情况下,引用XML模式中定义的全局元素不需要加上前缀,该情况会在第三部分进行介绍)。
当然,这里还有一种特殊的情况:XML模式的schema元素没有定义targetNamespace属性,那么该XML模式就不会创建命名空间。
三、XML模式的引用方式
引用具有命名空间的XML模式
我们在编写XML实例文档时,可以引用本地XML模式创建的命名空间,也可以引用网络中可访 问的XML模式定义的命名空间,但是它们的引用方式不一样。前面两部分的xml文件都是引用本地XML模式定义的命名空间。下面介绍一下如何引用网络中可 访问的XML模式创建的命名空间。