XML基础知识

当你使用Web Service、SOAP 传递或接受数据进行通讯时,

当你使用Spring、Struts、Maven 等当今流行框架及工具进行搭建配置时,

当你开发中需要解析Html、xls、PDF、Access 等文件时,

你会发现Xml将是这些领域中一项不可或缺的技术。可是你真正的研究过其中的奥秘么?如果一直以来只是一知半解的话,那么接下来就跟我一起扫扫盲吧。

一、XML与XSD(XML Schema Definition)

<?xml version="1.0" encoding="UTF-8"?>
<itnan xmlns="http://www.it-nan.com/schema/libs" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:schemaLocation="http://www.it-nan.com/schema/libs ../xsd/libs.xsd" >
    <info>IT男's blog</info>
    <url>http://www.it-nan.com</url></itnan>

上面这行代码是一个简单的xml格式文档。下面我们来逐一了解其中的含义:

第一行:xml标签,指明这是一个xml文档;version是版本号(指明xml的版本);encoding是编码规则(指明当前文档采用的编码格式 )。

第二行:xmlns是默认命名空间,声明url为“http://www.it-nan.com/schema/libs”的是默认的命名空间(如果后面有:xxx 则表明是定义为xxx的命名空间,如:xmlns:xsi);itnan是默认命名空间中定义的根节点标签(如果前面有类似于xxx: 的前缀,则表明该标签是从xxx命名空间中定义的标签,如:xsi:schemaLocation)。

第三行:这行是声明url为“http://www.w3.org/2001/XMLSchema-instance”的命名空间,由前缀xsi代表。“http://www.w3.org/2001/XMLSchema-instance”这个地址为xml的基础空间,所有的基础属性的定义都来自于这里,如:下面用到的schemaLocation属性,xsi是开发人员约定的一个名字,不是固定的,可以随意定义。

第四行:这行是用于指定命名空间与定义标签结构的XSD(XML Schema Definition)文件的对应关系。schemaLocation属性的值由多个URI引用对组成,两个URI之间以空白符分隔。第奇数个URI是命名空间的名字,第偶数个URI给出模式文档的位置(可以是url地址,也可以是相对路径),编辑器将从这个位置读取XSD文件,并与他的命名空间匹配来限制该空间下的标签结构。

第五、六行:这个是在定义itnan下的标签,而这个标签的结构是根据默认命名空间下的xsd文件定义出来的。下面就让我们看看xsd文件是如何定义的。

<?xml version="1.0" encoding="UTF-8"?><schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.it-nan.com/schema/libs" elementFormDefault="qualified">
	<element name="itnan">
	  <complexType>
	    <sequence>
              <element name="info" type="string"/>
              <element name="url" type="string"/>
	    </sequence>
	  </complexType>
	</element></schema>

上面这行代码是一个简单的xsd文档。下面我们来逐一了解其中的含义:

第一行:由于xsd文档也是符合xml规范的,所以也要在第一行声明这是一个xml文档;version是版本号(指明xml的版本);encoding是编码规则(指明当前文档采用的编码格式 )。

第二行:xmlns也同上面xml文档的一样表示默认的命名空间;而“http://www.w3.org/2001/XMLSchema”这个地址为xsd的基础命名空间,所有的基础属性的定义都来自于这里,如:下面用到的targetNamespace、elementFormDefault、element等。

第三行:由于这个xml文档里的“http://www.w3.org/2001/XMLSchema”为默认命名空间,而targetNamespace就是这个命名空间所定义的属性,所以targetNamespace属性不用加前缀修饰。这个属性是用于定义下面所规定的标签结构服务于哪个命名空间,所以这个值是与引用这个xsd文件的xml文档中声明的schemaLocation属性的命名空间必须要一致。(而这里表示下面的这些定义都是用于“http://www.it-nan.com/schema/libs”命名空间下的标签)

第四行:elementFormDefault有两个值“qualified”和“unqualified”。“qualified”表示:下面定义的所用标签都为targetNamespace设置的命名空间服务,而“unqualified”表示:除了全局元素或者类型将归于目标命名空间外,局部元素将归于无名命空间。(这个属性大部分都设置为“qualified”)

第五行之后:这些就都是xsd用来定义xml文档标签结构的代码,下面统一介绍。

二、常用的Schema文档教程

1. 最简单的Schema文档

如何写一个最简单的XML Schema文档呢?

首先,我们写出一个最简单的XML文档。

hello.xml:

<?xml version="1.0"?><greeting>Hello World!!</greeting><!--一个根元素:greeting;且这个元素不含属性,无子元素,内容是字符串。-->

hello.xsd:

<?xml version="1.0"?> <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"><xsd:element name="greeting" type="xsd:string"/></xsd:schema>

XML Schema文档后缀名是.xsd,完全符合XML语法,根元素是schema,命名空间xmlns:xsd=”http://www.w3.org/2001/XMLSchema,用元素定义实例文档中的元素,如greeting。

2. 含子元素的Schema文档

假设实例文档是如下的:

customer.xml:

<customer>
  <name>teiki</name>
  <address>No.237, Road Waitan, Shanghai</address></customer>

则可以写出以下的XML Schema文档:

customer.xsd:

<?xml version="1.0"?><xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <xsd:element name="customer">
  <xsd:complexType>
  <xsd:sequence>
    <xsd:element name="name" type="xsd:string"/>
    <xsd:element name="address" type="xsd:string" />
  </xsd:sequence>
  </xsd:complexType>
  </xsd:element></xsd:schema>

实例文档customer.xml中,元素含有两个子元素,所以我们在Schema文档中采用ComplexType来定义该元素。sequence表示子元素依次出现的顺序。

3. 含子元素和孙元素的Schema文档

这次我们给出一个更加复杂一些的文档:

customer.xml:

<customer>
  <name>Teiki</name>
  <address>
  <!-- address追加一个地址子元素 -->
    <prefecture>Zhejiang</prefecture>
    <city>Hangzhou</city>
    <street>Xilu Road, No.121, 7F</street>
  </address></customer>

为此,我们需要一个更加复杂一点的Schema文档:

address.xsd:

<?xml version="1.0"?><xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"><xsd:element name="customer">
  <xsd:complexType>
  <xsd:sequence>
    <xsd:element name="name" type="xsd:string"/>
    <!-- 追加子元素address-->
    <xsd:element name="address">
      <xsd:complexType>
      <xsd:sequence>
        <xsd:element name="prefecture" type="xsd:string"/>
        <xsd:element name="city" type="xsd:string" />
        <xsd:element name="street" type="xsd:string" />
      </xsd:sequence>
      </xsd:complexType>
    </xsd:element>
    </xsd:sequence>
    </xsd:complexType>
  </xsd:element></xsd:schema>

不过,我们还可以采用ref元素来重新编写这个Schema文档:

address2.xsd:

<?xml version="1.0"?><xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"><xsd:element name="customer">
  <xsd:complexType>
  <xsd:sequence>
    <xsd:element name="name" type="xsd:string"/>
    <xsd:element ref="address"/>
  </xsd:sequence>
  </xsd:complexType></xsd:element><xsd:element name="address">
  <xsd:complexType>
  <xsd:sequence>
    <xsd:element name="prefecture" type="xsd:string"/>
    <xsd:element name="city" type="xsd:string" />
    <xsd:element name="street" type="xsd:string" />
  </xsd:sequence>
  </xsd:complexType></xsd:element></xsd:schema>

使用ref元素可以直接将其指向另一个模块,使文档更加具有可读性。

4. 定义相同子元素的数量

先看这个简单的订购数据实例文档:

order.xml:

<order><orderItem>Accounting Book</orderItem><orderItem>Taxation Book</orderItem></order>

假设元素,即每次的订购书目不能超过10种,那该怎么写这个Schema文档呢?这里要用到的maxOccurs属性。

order.xsd:

<?xml version="1.0"?><xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"><xsd:element name="order">
  <xsd:complexType>
  <xsd:sequence>
    <xsd:element name="orderItem" type="xsd:string" maxOccurs="10" />
  </xsd:sequence>
  </xsd:complexType></xsd:element></xsd:schema>

第7行中的maxOccurs属性为10,代表orderItem元素可以最大有10个。如果,不设定元素个数,则可以用maxOccurs=”unbounded”来定义。

类似,如果要定义最小值,可以使用minOccurs,比如下面这句:

<xsd:element name="orderItem" type="xsd:string" minOccurs="5" maxOccurs="10"/>

这两个属性缺省值都是1。

5. 定义可选项的子元素

假如上面的订书数据中,可以用书名或者书号任一一种订购,则实例文档可能如下:

order2.xml:

<order>
  <orderItem>
    <!--书名订购-->
    <name>Accounting Book</name>
  </orderItem>
  <orderItem>
    <!--书号订购-->
    <id>7-5058-3496-7</id>
  </orderItem></order>

这时书写Schema文档还需要使用choice元素。

order2.xsd:

<?xml version="1.0"?><xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"><xsd:element name="order">
  <xsd:complexType>
  <xsd:sequence>
    <xsd:element ref="orderItem" maxOccurs="10" />
  </xsd:sequence>
  </xsd:complexType></xsd:element><xsd:element name="orderItem">
  <xsd:complexType>
  <xsd:choice>
    <xsd:element name="name" type="xsd:string"/>
    <xsd:element name="id" type="xsd:string"/>
  </xsd:choice>
  </xsd:complexType></xsd:element></xsd:schema>

稍微更复杂的可选项子元素

再稍微修改一下订书数据的实例文档:

order3.xml:

<order>
  <orderItem>
    <name>Accounting Book</name>
    <quantity>2</quantity>
  </orderItem>
  <orderItem>
    <id>7-5058-3496-7</id>
  </orderItem></order>

这里假定值为1时,缺省。

如何修改Schema文档呢?

order3.xsd:

<?xml version="1.0"?><xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"><xsd:element name="order">
  <xsd:complexType>
  <xsd:sequence>
    <xsd:element ref="orderItem" maxOccurs="10"/>
  </xsd:sequence>
  </xsd:complexType></xsd:element><xsd:element name="orderItem">
  <xsd:complexType>
  <xsd:sequence>
  <xsd:choice>
    <xsd:element name="name" type="xsd:string"/>
    <xsd:element name="id" type="xsd:string"/>
  </xsd:choice>
  <xsd:element name="quantity" type="xsd:string" minOccurs="0"/>
  </xsd:sequence>
  </xsd:complexType></xsd:element></xsd:schema>

文档中的quantity最少出现值为0,也就是可以有,也可以没有。
当然,也可以直接在元素中,包含quantity,然后定义它的minOccurs。

6. 内置简单类型

具有简单类型的元素只能包含字符数据,不能包含子元素,也不能有属性。XML Schema推荐标准内置了44种简单类型,如例中的xs:string、xs:integer等,这些简单类型可以直接引用。XML Schema内置的数据类型的层次结构如下图所示。

XML基础知识_第1张图片

xsd-simpleType

XML Schema支持类型的派生,这和面向对象语言中对象的继承有些类似,但又不完全相同。XML Schema类型的派生分为限制(restriction)和扩展(extension),通过限制派生的新类型的值范围是原类型值范围的子集,通过扩展则可以为现有类型添加新的元素和属性。

对于简单类型,只有限制派生而没有扩展派生,我们只能通过限制一个现有的简单类型(内置的简单类型或派生于内置简单类型的简单类型)来派生一个新的简单类型。那如何对现有的简单类型进行限制呢?XML Schema给我们提供了12个面(facet),用于指定一个值的有效范围、约束值的长度和精度、枚举一系列的有效值,或者指定有效值必须匹配的正则表达式。

面与类型的关系就好像棱镜的面与棱镜的关系,透过不同的面,你看到的景观(内容)是不同的。在XML Schema中,面相当于是对一个现有的简单类型添加某些约束(限制),约束不同,得到的结果就不同。也就是说,你可以把面(facet)看成是对数据类型的约束,目的是为了让它的值限制在一定的范围内。实际上,这些面就是http://www.w3.org/2001/XMLSchema名称空间中的一些元素,只不过这些元素是用来对现有类型的值进行约束的,因而称为面。

要定义新的简单类型,使用xs:simpleType元素,要对现有的基类型进行限制,使用xs:restriction元素,并在该元素的内部使用限制值范围的面(facet)。例如,我们定义一个雇员年龄的类型,雇员年龄要求在18~60岁之间,我们可以从内置的xs:integer类型派生一个新的简单类型ageType,然后使用xs:minInclusive和xs:maxInclusive面来限制年龄值的范围。

例如这个实力文档:

<xs:simpleType name="ageType">
         <xs:restriction base="xs:integer">
               <xs:minInclusive value="18"/>
               <xs:maxInclusive value="60"/>
         </xs:restriction></xs:simpleType>

7. 自定义简单类型

如果内置简单类型的44种还不能满足要求,怎么办呢?下面学习自定义简单类型。(XML的扩展性充分体现在这里)

例如这个实例文档:

order4.xml:

<order>
  <orderItem>
    <id>7-5058-3496-7</id>
    <quantity>5</quantity>
  </orderItem></order>

ID是一个标准的ISBN编码,我们怎么定义这个ISBN编码呢?

<xsd:simpleType name="idType">
  <xsd:restriction base="xsd:string">
    <xsd:pattern value="\d{1}-\d{4}-\d{4}-\d{1}"/>
  </xsd:restriction></xsd:simpleType>

idType是一个自定义的简单类型。

我们对它做了限制:

<xsd:restriction base=”xsd:string”>代表它是基于一个字符串类型。再用pattern元素来描述该字符串的形式。

value=”\d{1}-\d{4}-\d{4}-\d{1}”这是一个正则表达式,关于正则表达式,以后再介绍。嘻嘻!

利用这个自定义的简单类型,我们可以重新写Schema文档:

order4.xsd:

<?xml version="1.0"?><xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"><xsd:element name="order">
  <xsd:complexType>
  <xsd:sequence>
    <xsd:element ref="orderItem" maxOccurs="10"/>
  </xsd:sequence>
  </xsd:complexType></xsd:element><xsd:element name="orderItem">
  <xsd:complexType>
  <xsd:sequence>
    <xsd:element name="id" type="idType"/>
    <xsd:element name="quantity" type="xsd:integer"/>
  </xsd:sequence>
  </xsd:complexType></xsd:element><xsd:simpleType name="idType">
  <xsd:restriction base="xsd:string">
    <xsd:pattern value="\d{1}-\d{4}-\d{4}-\d{1}"/>
  </xsd:restriction></xsd:simpleType></xsd:schema>

假如我们事先确定好ID只有3个,即只有3个ISBN是可选的,那怎么办?我们可以用enumeration元素来进行列举。

<xsd:simpleType name="idType">
  <xsd:restriction base="xsd:string">
    <xsd:enumeration value="7-5058-3496-7"/>
    <xsd:enumeration value="7-5005-6450-3"/>
    <xsd:enumeration value="7-3020-6069-7"/>
  </xsd:restriction></xsd:simpleType>

再来看订购量quantity的值,如果我们设定其值必须在1-10之间,该怎么办呢?可以这些自定义一个简单类型。

<xsd:simpleType name="quantityType">
  <xsd:restriction base="xsd:integer">
    <xsd:minInclusive value="1"/>
    <xsd:maxInclusive value="10"/>
  </xsd:restriction></xsd:simpleType>

其中,minInclusive,maxInclusive分别代表该类型的取值范围。

所以最终修改后的Schema文档如下:

order4-1.xsd:

<?xml version="1.0"?><xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"><xsd:element name="order">
  <xsd:complexType>
  <xsd:sequence>
    <xsd:element ref="orderItem" maxOccurs="10"/>
  </xsd:sequence>
  </xsd:complexType></xsd:element><xsd:element name="orderItem">
  <xsd:complexType>
  <xsd:sequence>
    <xsd:element name="id" type="idType"/>
    <xsd:element name="quantity" type="quantityType"/>
  </xsd:sequence>
  </xsd:complexType></xsd:element><xsd:simpleType name="idType">
  <xsd:restriction base="xsd:string">
    <xsd:enumeration value="7-5058-3496-7"/>
    <xsd:enumeration value="7-5005-6450-3"/>
    <xsd:enumeration value="7-3020-6069-7"/>
  </xsd:restriction></xsd:simpleType><xsd:simpleType name="quantityType">
  <xsd:restriction base="xsd:integer">
    <xsd:minInclusive value="1"/>
    <xsd:maxInclusive value="10"/>
  </xsd:restriction>
  </xsd:simpleType></xsd:schema>

8. 定义属性

最后,我们再来讲讲元素的属性如何在Schema文档中定义。

比如上面的order.xml实例文档中:

<order>
  <orderItem id="7-5058-3496-7" /></order>

对此,我们在Schema文档中采用一个attribute来定义:

order.xsd:

<xsd:element name="orderItem">
  <xsd:complexType>
  <xsd:sequence>  ←空元素  </xsd:sequence>  
    <!--定义该元素属性-->
    <xsd:attribute name="id" type="xsd:string"/>
  </xsd:complexType></xsd:element>

那么,实例文档中该属性值是必须的还是可有可无的呢?我们可以这样限制:

<xsd:attribute name="id" type="idType" use="required"/>

这里我们讲id属性类型作为一种自定义数据类型idType。
而且,用attribute元素的use属性来定义是否是必须的属性。
required是必须值,optional是可选值,prohibited是无属性值。

那么对于属性的缺省值,我们怎么定义呢?
比如:

<order>
  <orderItem id="4-8443-1780-6" quantity="3"/></order>

我们还可以用attribute元素的另一个属性default来定义:

<xsd:attribute name="quantity" type="xsd:integer" default="1"/>

所以,我们可以重新写出一个Schema文档:

order2.xsd:

<xsd:element name="orderItem">
  <xsd:complexType>
  <xsd:sequence></xsd:sequence>
    <xsd:attribute name="id" type="idType" use="required"/>
    <xsd:attribute name="quantity" type="xsd:integer" default="1"/>
  </xsd:complexType></xsd:element>

上面的属性我们定义我们还可以采用属性组的办法来重新改写Schema文档。

order3.xsd:

<xsd:element name="orderItem">
  <xsd:complexType>
  <xsd:sequence></xsd:sequence>
    <xsd:attributeGroup ref="orderItemAttributes"/>
  </xsd:complexType></xsd:element><xsd:attributeGroup name="orderItemAttributes">
  <xsd:attribute name="id" type="idType" use="required"/>
  <xsd:attribute name="quantity" type="xsd:integer" default="1"/></xsd:attributeGroup>

这个属性组就不详细解释了,不过,大家一看就清楚了吧。

9.最后,我们写一个完整的订书order.xml的Schema文档。
<?xml version="1.0"?><xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <xsd:element name="order">
  <xsd:complexType>
  <xsd:sequence>
    <xsd:element ref="orderItem" maxOccurs="10"/>
  </xsd:sequence>
  </xsd:complexType></xsd:element><xsd:element name="orderItem">
  <xsd:complexType>
  <xsd:sequence></xsd:sequence>
    <xsd:attributeGroup ref="orderItemAttributes"/>
  </xsd:complexType></xsd:element><xsd:attributeGroup name="orderItemAttributes">
  <xsd:attribute name="id" type="idType" use="required"/>
  <xsd:attribute name="quantity" type="xsd:integer" default="1"/></xsd:attributeGroup><xsd:simpleType name="idType">
  <xsd:restriction base="xsd:string">
    <xsd:pattern value="\d{1}-\d{4}-\d{4}-\d{1}"/>
  </xsd:restriction></xsd:simpleType></xsd:schema>


你可能感兴趣的:(XML基础知识)