验证XML文档是否符合议定的XML结构有两种方法,分别是DTD模式与XML Schema。本文主要介绍XML Schema。
一、XML Schema的优点
- XML Schema基于XML,没有专门的语法。
- XML Schema可以像其他XML文件一样解析和处理。
- XML Schema支持一系列的数据类型(int、float、Boolean、date等)。
- XML Schema提供可扩充的数据模型。
- XML Schema支持综合命名空间。
- XML Schema支持属性组。
二、XSD
XSD文档至少要包含:schema根元素和XML模式命名空间的定义、元素定义。需要注意的是XSD中必须定义一个且只能定义一个schema根元素,根元素中包括模式的约束,XML模式命名空间的定义,其他命名空间的定义、版本信息、语言信息和其他一些信息。
1、schema根元素
语法如下:
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
...
</xsd:schema>
2、元素
语法如下:
<xsd:element name="user" type="xsd:string" />
XSD中元素是利用element标识符来声明,在上面的示例中name属性是元素的名字,type属性是元素值的类型,可以使XML Schema中内置的数据类型或其他类型。
全部元素如下:
元素 | 说明 |
name | 元素的名称 |
type | 元素值的类型 |
minOccurs | 该元素在父元素中最少出现的次数(默认为1,必须大于等于0) |
maxOccurs | 该元素在父元素中最多出现的次数(默认为1,必须大于等于0),当设置为unbounded表示不限制。 |
3、引用元素
引用元素是利用element标记符的ref属性实现的。主要适用于避免在文档中多次定义同一个元素。表示当前元素与被引用的元素相同。
语法如下:
<xsd:element name="user" type="xsd:string" />
<xsd:sequence>
<xsd:element ref="user" /> <!--当前元素就是user元素-->
</xsd:sequence>
4、别名
别名主要利用element标识符中的属性substitutionGroup实现的。
语法:
<xsd:element name="user" type="xsd:string" substitutionGroup="yonghu" />
该语句表示该行的元素名可以是user或用户,如:
<yonghu>admin</yonghu>
<user>admin</user>
这两行xml都是符合条件的。
5、设置默认值与固定值
语法如下:
<xsd:element name="city" type="xsd:string" default="xian" />
<xsd:element name="country" type="xsd:string" fixed="china" />
通过default属性的设置,可以在XML文档中没有对city定义时赋予默认值,而是用fixed属性,可以给元素country设定一个固定的值china,并且不允许改变。
6、利用组合器控制结构
1、sequence组合器,定义了一列元素必须按照模式中指定的顺序显示(如果是可选的,也可以不显示)。
<xsd:sequence>
<xsd:element name="first" type="xsd:string" />
<xsd:element name="middle" type="xsd:string" />
<xsd:element name="last" type="xsd:string" />
</xsd:sequence>
2、all组合器,允许所定义的元素可以按照任意顺序显示,all元素的子元素在默认情况下士必须的,而且每次最多显示一次。
<xsd:all minOccurs="0">
<xsd:element name="first" type="xsd:string" />
<xsd:element name="middle" type="xsd:string" />
<xsd:element name="last" type="xsd:string" />
</xsd:all>
(3)choice组合器,允许指定多组声明中的一个,用于互斥情况。
<xsd:choice>
<xsd:element name="first" type="xsd:string" />
<xsd:element name="middle" type="xsd:string" />
<xsd:element name="last" type="xsd:string" />
</xsd:choice>
7、定义属性
在XML Schema文档中可以按照定义元素的方法定义属性,但受限制程度较高。可以应用在attribute元素定义中的属性如下表所示。
属性 | 含义 |
defalt | 初始默认值 |
fixed | 不能修改和覆盖的固定属性值 |
name | 属性的名称 |
ref | 对前一个属性定义的引用 |
type | 该属性的XSD类型或者简单类型 |
use | 如何使用属性 optional(可选属性,即属性不是必须的,默认是这个)、prohibited(禁止使用)或者required(强制必须)。 |
form | 确定attributeFormDefault的本地址 |
id | 模式文档中属性唯一的ID |
8、创建属性
语法如下:
<xsd:attribute name="age" type="xsd:integer" />
该语句定义了一个名为age的属性,它的值必须为整数。把它添加到模式中时,它必须是schema元素,complexType元素或者attributeGroup元素的子元素。
代码示例:
<xsd:element name="name">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="first" type="xsd:string" />
</xsd:sequence>
<xsd:attribute name="age" type="xsd:integer" use="optional" /> <!--将属性添加到元素name属性中-->
</xsd:complexType>
</xsd:element>
以上文档对应有效的XML文档如下:
<?xml version="1.0"?>
<name age="27">
<first>string</first>
</name>
该示例不但说明了如下约束属性,还展示了组合器的用法。
三、XML Schema数据对象和类型
1、Schema对象
一、属性
CompilationSettings 获取或设置 XmlSchemaSet 的 XmlSchemaCompilationSettings。
Count 获取 XmlSchemaSet 中逻辑 XML 架构定义语言 (XSD) 架构的数量。
GlobalAttributes 获取 XmlSchemaSet 中所有 XML 架构定义语言 (XSD) 架构的所有全局属性。
GlobalElements 获取 XmlSchemaSet 中所有 XML 架构定义语言 (XSD) 架构的所有全局元素。
GlobalTypes 获取 XmlSchemaSet 中所有 XML 架构定义语言 (XSD) 架构的所有全局简单和复杂类型。
IsCompiled 指示 XmlSchemaSet 中的 XML 架构定义语言 (XSD) 架构是否已编译。
NameTable 获取加载新的 XML 架构定义语言 (XSD) 架构时 XmlSchemaSet 使用的默认 XmlNameTable。
XmlResolver 设置用于解析在架构的包含和导入元素中引用的命名空间或位置的 XmlResolver。
二、方法
Add 已重载。 将给定的 XML 架构定义语言 (XSD) 架构添加到 XmlSchemaSet。
Compile 将添加到 XmlSchemaSet 的 XML 架构定义语言 (XSD) 架构编译成一个逻辑架构。
Contains 已重载。 指示 XML 架构定义语言 (XSD) 架构是否位于 XmlSchemaSet。
CopyTo 将 XmlSchemaSet 中的所有 XmlSchema 对象复制到起始位置为给定索引的给定数组中。
Remove 从 XmlSchemaSet 移除指定的 XML 架构定义语言 (XSD) 架构。
RemoveRecursive 从 XmlSchemaSet 中移除指定的 XML 架构定义语言 (XSD) 架构和它导入的所有架构。
Reprocess 重新处理已经存在于 XmlSchemaSet 中的 XML 架构定义语言 (XSD) 架构。
Schemas 已重载。 返回 XmlSchemaSet 中 XML 架构定义语言 (XSD) 架构的集合。
三、事件
ValidationEventHandler 设置一个事件处理程序,用于接收有关 XML 架构定义语言 (XSD) 架构验证错误的信息。
2、Schema基本数据类型
Schema的基本数据类型如下:
数据类型 | 说明 |
boolean | true/false |
datetime | 格式:CCYY-MM-DDThh:mm:ss |
decimal | 任意精度的十进制数字 |
string | 字符串数据 |
int | 整型 |
nonNegativeInteger | 大于或等于0的整型 |
nonPositiveInteger | 小于或等于0的整型 |
short | 短整型 -32768到32767 |
3、约束
内置的数据类型功能虽然已经有一定的限制功能,但是还是远远不足够的,更进一步的约束还是来看看约束。
约束 | 说明 |
enumeration | 用空格分开的一组指定的数值,它把数据类型约束为指定的值 |
fractionDigit | 指定小数点后的最大位数 |
length | 长度单位 |
minExclusive | 下限值 |
maxExclusive | 上限值 |
minLength | 最小长度单位 |
maxLength | 最大长度单位 |
minInclusive | 最小值,所有的值都应该大于或等于该值 |
maxInclusive | 最大值,所有的值都应该小于或等于该值 |
pattern | 数据类型的值必须匹配的指定模式,必须是一个正则表达式 |
totalDigits | 指定小数最大位数的值 |
whiteSpace | 其值为preserve(值中的空格不能改变)、replace(所有的制表符、换行符、回车符都用空格代替)、collapse(执行replace,删除相邻的、结尾处和开头处的空格)。 |
要使用上面约束表的约束,就要利用元素restriction。这个元素中有两个属性:ID属性是模式文档中restriction元素的位置标识符;base属性设置为一个内置的XSD数据类型或者现有的简单类型定义,它是一种被限制的类型。
示例:将一个整数的取值范围设置为1~100之间。
<xsd:restriction base="xsd:int">
<xsd:minInclusive value="1" />
<xsd:maxInclusive value="100" />
</xsd:restriction>
4、简单类型
简单类型是对一个节点的可能值进一步限制的自定义数据类型。创建简单类型需要利用simpleType元素,其定义如下:
<simpleType id="ID" name="NCName" final="(#all|((list|union|restriction)))" />
ID属性应唯一地标明文档内的simpleType元素,name不能使用冒号字符。simpleType不能包含元素,也不能有属性,它基本上是一个值,或者是一个值的集合。
例如:
<xsd:simpleType name="USState">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="AK">
<xsd:enumeration value="AL">
<xsd:enumeration value="AR">
</xsd:restriction>
</xsd:simpleType>
<xsd:element name="statement" type="USState" />
以上文档对应有效的xml文档如下:
<statement>AK</statement>
注意取值只能够为AK、AR、AL中的一个。
5、列表类型
list可以用来定义列表类型。
<xsd:simpleType name="listOfIntType">
<xsd:list itemType="Integer"/>
</xsd:simpleType>
<xsd:element name="listOfMyInt" type="listOfType"/>
listIfIntType这个类型被定义为一个Integet的列表,元素listOfMyInt的值可以是几个整数,他们之间用空格分开。
有效的xml文档如下:
<listOfMyInt>1 2 3 123</listOfMyInt>
6、联合类型
union可以用来定义一个联合类型。例如:
<xsd:simpleType name="zipUnion">
<xsd:union memberTypes="USState listOfMyIntType"/>
</xsd:simpleType>
<xsd:element name="zips" type="zipUnion"/>
用union来定义一个联合类型,里面的成员类型保罗USState和listOfMyIntType,应用了联合类型的元素的值可以是这些原子类型或列表类型中的一个类型的示例,但是一个元素实例不能同时包含两个类型。
有效的XML文档如下:
<zips>CA</zips>
<zips>9192 192391 129</zips>
<zips>AK</zips>
无效的XML文档如下:
<zips>AL 2231</zips>
同时包含两个是错误的。
7、匿名类型
前面定义元素类型的时候总是先定义一个数据类型,然后再把元素的type设成新定义的数据类型。如果这个新的数据类型只会用一次,我们就可以直接设置在元素定义里面,而不用另外来设置。
例如:
<xsd:element name="quantity">
<xsd:simpleType>
<xsd:restriction base="xsd:positiveInteger">
<xsd:maxExclusive value="100"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
元素quantity的类型就是一个从1~99的整数。对于这种没有用type引入,直接定义在element元素里面的类型,我们称之为匿名类型。
8、复杂类型
复杂类型的定义必须使用complexType元素,在这里可以包含属性和元素。在复杂类型的使用中,主要是complexType和simpleType配合使用。
9、内容模型
内容模型可以对在XML文档内使用的元素、属性和类型进行限制,确定用户可以再XML实例的那些等级添加自己的元素和属性。
1、any内容模型
在XML中声明元素时,any是默认的内容模型,该模型可以包含文本、元素和空格。
例如:
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="name">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="first" type="xsd:string" />
<xsd:element name="middle" type="OtherNames" />
<xsd:element name="last" type="xsd:string" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:complexType name="OtherNames">
<xsd:sequence>
<xsd:any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded" />
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
例子中xsd:any元素说明该类型允许添加内容。
namespace属性允许的值为:
- ##any:元素可以来自任何命名空间。
- ##other:元素可以来自除了该元素的父元素所在的目标命名空间之外的命名空间。
- ##local:元素不受命名空间限制。
- ##targetNamespace:元素来自父元素的目标命名空间。
processContents属性说明对这里所创建的元素进行验证时所执行的操作。
processContents属性取值有如下三种:
- strict:表明XML处理器必须获得和哪些命名空间相关联的模式,并验证元素和属性。
- lax:与strict类似,只是如果处理器找不到模式文档,也不会出现错误。
- skip:不利用模式文档验证XML文档。
上述模式的一个有效实例:
<?xml version="1.0" encoding="utf-8" ?>
<name>
<first>santld</first>
<middle>
<nameInChina>San</nameInChina>
</middle>
<last>wang</last>
</name>
2、空内容模型(empty)
有时候元素根本没有内容,它的内容模型是空。为了定义内容是空的类型,我们可以通过这样的方式:首先定义一个元素,它只能包含子元素而不能包含元素内容,然后又不定义任何子元素,依靠这样的方式,就能够定义出内容模型为空的元素。
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="internationalPrice">
<xsd:complexType>
<xsd:complexContent>
<xsd:restriction base="xsd:anyType">
<xsd:attribute name="currency" type="xsd:string"/>
<xsd:attribute name="value" type="xsd:decimal"/>
</xsd:restriction>
</xsd:complexContent>
</xsd:complexType>
</xsd:element>
</xsd:schema>
有效的XML文档如下:
<internationalPrice currency="ERU" value="/423.46"/>
无效的文档示例:
<internationalPrice currency="ERU" value="/423.46"/>这是错误的</internationalPrice>
3、混合内容模型(mixed)
它包含文本、内容和属性。在complexType元素上把mixed属性的值设为true,就声明了一个mixed内容模型。例如:
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="contact">
<xsd:complexType mixed="true">
<xsd:sequence>
<xsd:element name="first" type="xsd:string" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
上述模式的一个有效实例如下:
<?xml version="1.0" encoding="utf-8" ?>
<contact>
My first is <first>Santld</first>.
</contact>
四、Visual Studio设计器创建XSD Schema
用Visual Studio创建XSD Schema还是较为容易的。因为IDE提供可视化工具用于构建元素、简单类型和复杂类型等。首先添加一个新的Schema文件。
英文版的名字是XML Schema,中文版是XML 架构。很奇怪,按照书上说的,添加一个XML Schema文件之后,工具箱会有很多工具,但是我的Visual Studio 2010里面并没有添加任何工具。此处留到以后再补充。
五、.Net验证XML文档
为了在XML文档中关联外部的 XSD Schema文件,要对XML文档以及XSD Schema文件作出相应的修改,具体的修改如下示例所示:
XML文件:
<?xml version="1.0" encoding="utf-8" ?>
<person xmlns="http://www.xxx.com/xxx">
<name>张飞1111111</name>
<age>24</age>
</person>
XML Schema文件:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.xxx.com/xxx">
<xs:element name="person">
<xs:complexType>
<xs:sequence>
<xs:element name="name">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:maxLength value="4"/>
<xs:minLength value="2"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="age">
<xs:simpleType>
<xs:restriction base="xs:positiveInteger">
<xs:maxExclusive value="100"/>
<xs:minExclusive value="1"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
1、使用XmlDocument对象验证
代码文件:XmlDocument验证文件
static void Main(string[] args)
{
XmlDocument doc = new XmlDocument(); //创建文档
doc.Schemas.Add(null, @"C:\Users\Administrator\Desktop\ConsoleApplication1\ConsoleApplication1\person.xsd"); //添加验证架构文件,null为使用默认的命名空间
doc.Load(@"C:\Users\Administrator\Desktop\ConsoleApplication1\ConsoleApplication1\person.xml"); //加载xml文件
doc.Validate(SettingsValidationEventHandler); //执行验证操作,错误处理方法为参数SettingsValidationEventHandler
Console.WriteLine("验证通过"); //如果验证通过才会执行到此
Console.ReadKey(); } static void SettingsValidationEventHandler(object sender, ValidationEventArgs e)
{
if (e.Severity == XmlSeverityType.Warning)
{
Console.Write("警告信息: ");
Console.WriteLine(e.Message); }
else if (e.Severity == XmlSeverityType.Error)
{
Console.Write("错误信息: ");
Console.WriteLine(e.Message);
}
else
{ }
Console.ReadKey();
}
2、使用XmlReader对象验证
XmlReaderSettings是在验证XML文档时经常用到的一个类。在XmlReader类中提供了一个验证XML文档的方法,通过调用该类的Create()方法。该方法接受XML文档的URL和XmlReaderSettings类的示例对象作为输入参数。
一、属性
CheckCharacters 获取或设置一个值,该值指示是否进行字符检查。
CloseInput 获取或设置一个值,该值指示当读取器关闭时,是否应关闭基础流或 TextReader。
ConformanceLevel 获取或设置 XmlReader 将遵循的一致性级别。
IgnoreComments 获取或设置一个值,该值指示是否忽略注释。
IgnoreProcessingInstructions 获取或设置一个值,该值指示是否忽略处理指令。
IgnoreWhitespace 获取或设置一个值,该值指示是否忽略无关紧要的空白。
LineNumberOffset 获取或设置 XmlReader 对象的行号偏移量。
LinePositionOffset 获取或设置 XmlReader 对象的行位置偏移量。
MaxCharactersFromEntities 获取或设置一个值,该值指示文档中允许扩展实体产生的最大字符数。
MaxCharactersInDocument 获取或设置一个值,该值指明 XML 文档中所允许的最大字符数。零 (0) 值表示对 XML 文档的大小没有限制。非零值指定最大大小(以字符 数计)。
NameTable 获取或设置用于原子化字符串比较的 XmlNameTable。
ProhibitDtd 获取或设置一个值,该属性指定是否应用DTD来验证XML文档。如果不使用DTD验证,则设为Flase。默认为True。
Schemas 获取或设置在执行架构验证时使用的 XmlSchemaSet。
ValidationFlags 获取或设置一个指示架构验证设置的值。此设置应用于验证架构的 XmlReader 对象(ValidationType 属性设置为 ValidationType.Schema)。
ValidationType 获取或设置一个值,该值指示 XmlReader 在读取时是否执行验证或类型分配。
XmlResolver 设置用来访问外部文档的 XmlResolver。
二、方法
Clone 创建 XmlReaderSettings 实例的副本。
Reset 将设置类的成员重置为各自的默认值。
三、事件
ValidationEventHandler 当读取器遇到验证错误时发生。
ValidationType属性的取值范围来自一个名为ValidationType的枚举类型,该枚举有以下5个取值:
None 不进行验证,默认值。
Auto 通过观察XML文档自动决定利用DTD或Schema进行验证。
DTD 利用DTD验证
Schema 利用XSD Schema验证
XDR 利用XDR Schema验证
代码文件:XmlReader验证:
static void Main(string[] args)
{
XmlReaderSettings Settings = new XmlReaderSettings(); //
Settings.Schemas.Add(null, @"C:\Users\Administrator\Desktop\ConsoleApplication1\ConsoleApplication1\person.xsd");
Settings.ValidationType = ValidationType.Schema;
Settings.ValidationEventHandler += new ValidationEventHandler(SettingsValidationEventHandler);
XmlReader reader = XmlReader.Create(@"C:\Users\Administrator\Desktop\ConsoleApplication1\ConsoleApplication1\person.xml", Settings);
while (reader.Read())
{ }
reader.Close();
Console.WriteLine("验证成功!");
Console.ReadKey();
} static void SettingsValidationEventHandler(object sender, ValidationEventArgs e)
{
if (e.Severity == XmlSeverityType.Warning)
{
Console.Write("警告信息: ");
Console.WriteLine(e.Message); }
else if (e.Severity == XmlSeverityType.Error)
{
Console.Write("错误信息: ");
Console.WriteLine(e.Message);
}
else
{ }
Console.ReadKey();
}
出处:https://www.cnblogs.com/kissdodog/archive/2013/02/25/2931941.html