代码改变世界

XSD使用

2009-08-13 09:09  Andy Ge  阅读(1087)  评论(0编辑  收藏  举报

XML Schema 描述 XML 文档的结构。XML Schema 语言也称作 XML Schema 定义(XML Schema DefinitionXSD)。

1.     教程网站

http://www.w3school.com.cn/schema/index.asp

2.     为何使用XSD

Ø 可更容易地描述允许的文档内容

Ø 可更容易地验证数据的正确性

Ø 可更容易地与来自数据库的数据一并工作

Ø 可更容易地定义数据约束(data facets

Ø 可更容易地定义数据模型(或称数据格式)

Ø 可更容易地在不同的数据类型间转换数据

3.     XSD定义

1.1       minOccurs,maxOccurs

通过 schema,我们可使用 maxOccurs minOccurs 属性来定义某个元素可能出现的次数。maxOccurs 定义某元素出现次数的最大值,而 minOccurs 则定义某元素出现次数的最小值。maxOccurs minOccurs 的默认值都是 1

1.2       XML例子

针对下面的XML实例,我们可以通过以下几种方式定义XSD

<?xml version="1.0" encoding="utf-8"?>

<shiporder orderid="889923" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

 <orderperson>George Bush</orderperson>

 <shipto>

    <name>John Adams</name>

    <address>Oxford Street</address>

    <city>London</city>

    <country>UK</country>

 </shipto>

 <item>

    <title>Empire Burlesque</title>

    <note>Special Edition</note>

    <quantity>1</quantity>

    <price>10.90</price>

 </item>

 <item>

    <title>Hide your heart</title>

    <quantity>1</quantity>

    <price>9.90</price>

 </item>

</shiporder>

1.3       基本定义方式

<?xml version="1.0" encoding="utf-8" ?>

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

 <xs:element name="shiporder">

    <xs:complexType>

      <xs:sequence>

        <xs:element name="orderperson" type="xs:string"/>

        <xs:element name="shipto">

          <xs:complexType>

            <xs:sequence>

              <xs:element name="name" type="xs:string"/>

              <xs:element name="address" type="xs:string"/>

              <xs:element name="city" type="xs:string"/>

              <xs:element name="country" type="xs:string"/>

            </xs:sequence>

          </xs:complexType>

        </xs:element>

        <xs:element name="item" maxOccurs="unbounded">

          <xs:complexType>

            <xs:sequence>

              <xs:element name="title" type="xs:string"/>

              <xs:element name="note" type="xs:string" minOccurs="0"/>

              <xs:element name="quantity" type="xs:positiveInteger"/>

              <xs:element name="price" type="xs:decimal"/>

            </xs:sequence>

          </xs:complexType>

        </xs:element>

      </xs:sequence>

      <xs:attribute name="orderid" type="xs:string" use="required"/>

    </xs:complexType>

 </xs:element>

</xs:schema>

1.4       ref

定义元素,能够在其他地方通过ref进行引用。

<?xml version="1.0" encoding="utf-8" ?>

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

 <xs:element name="orderperson" type="xs:string"/>

 <xs:element name="name" type="xs:string"/>

 <xs:element name="address" type="xs:string"/>

 <xs:element name="city" type="xs:string"/>

 <xs:element name="country" type="xs:string"/>

 <xs:element name="title" type="xs:string"/>

 <xs:element name="note" type="xs:string"/>

 <xs:element name="quantity" type="xs:positiveInteger"/>

 <xs:element name="price" type="xs:decimal"/>

   

 <xs:attribute name="orderid" type="xs:string"/>

 

 <xs:element name="shipto">

    <xs:complexType>

      <xs:sequence>

        <xs:element ref="name"/>

        <xs:element ref="address"/>

        <xs:element ref="city"/>

        <xs:element ref="country"/>

      </xs:sequence>

    </xs:complexType>

 </xs:element>

 <xs:element name="item">

    <xs:complexType>

      <xs:sequence>

        <xs:element ref="title"/>

        <xs:element ref="note" minOccurs="0"/>

        <xs:element ref="quantity"/>

        <xs:element ref="price"/>

      </xs:sequence>

    </xs:complexType>

 </xs:element>

 

 <xs:element name="shiporder">

    <xs:complexType>

      <xs:sequence>

        <xs:element ref="orderperson"/>

        <xs:element ref="shipto"/>

        <xs:element ref="item" maxOccurs="unbounded"/>

      </xs:sequence>

      <xs:attribute ref="orderid" use="required"/>

    </xs:complexType>

 </xs:element>

 

</xs:schema>

1.5       named types

通过定义类型,可以指定元素的类型。

<?xml version="1.0" encoding="utf-8" ?>

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

 

 <xs:simpleType name="stringtype">

    <xs:restriction base="xs:string"/>

 </xs:simpleType>

 

 <xs:simpleType name="inttype">

    <xs:restriction base="xs:positiveInteger"/>

 </xs:simpleType>

 

 <xs:simpleType name="dectype">

    <xs:restriction base="xs:decimal"/>

 </xs:simpleType>

 

 <xs:simpleType name="orderidtype">

    <xs:restriction base="xs:string">

      <xs:pattern value="[0-9]{6}"/>

    </xs:restriction>

 </xs:simpleType>

 

 <xs:complexType name="shiptotype">

    <xs:sequence>

      <xs:element name="name" type="stringtype"/>

      <xs:element name="address" type="stringtype"/>

      <xs:element name="city" type="stringtype"/>

      <xs:element name="country" type="stringtype"/>

    </xs:sequence>

 </xs:complexType>

 

 <xs:complexType name="itemtype">

    <xs:sequence>

      <xs:element name="title" type="stringtype"/>

      <xs:element name="note" type="stringtype" minOccurs="0"/>

      <xs:element name="quantity" type="inttype"/>

      <xs:element name="price" type="dectype"/>

    </xs:sequence>

 </xs:complexType>

 

 <xs:complexType name="shipordertype">

    <xs:sequence>

      <xs:element name="orderperson" type="stringtype"/>

      <xs:element name="shipto" type="shiptotype"/>

      <xs:element name="item" maxOccurs="unbounded" type="itemtype"/>

    </xs:sequence>

    <xs:attribute name="orderid" type="orderidtype" use="required"/>

 </xs:complexType>

 

 <xs:element name="shiporder" type="shipordertype"/>

 

</xs:schema>

 

2         .NetXSD

2.1       通过XMLSchema方式

利用这种方式能够检查整个的XML文档中的所有问题,简单的代码如下:

using System;

using System.IO;

using System.Xml;

using System.Xml.Schema;

using System.Text;

 

namespace XSDStudy

{

    public class XMLValidator

    {

        bool valid = false;

        public bool Valid

        {

            get { return valid; }

        }

 

        StringBuilder sb;

        public string Message

        {

            get { return sb.ToString(); }           

        }

 

        bool backOnError = false;

        public bool BackOnError

        {

            get { return backOnError; }

            set { backOnError = valid; }

        }

 

        public XMLValidator()

        {

        }

 

        public XMLValidator(bool backOnError)

        {

            this.backOnError = backOnError;

        }

 

        XmlTextReader xmlReader;

        public void Validate(string xml,string xsd)

        {

            xmlReader = new XmlTextReader(new MemoryStream(Encoding.UTF8.GetBytes(xml)));

            XmlReader xsdReader = XmlReader.Create(new MemoryStream(Encoding.UTF8.GetBytes(xsd)));

            validate(xsdReader);

        }

 

 

        private void validate(XmlReader xsdReader)

        {

            sb = new StringBuilder();

            valid = true;

            try

            {

                XmlSchema schema = XmlSchema.Read(xsdReader, validationEventHandler);

                XmlReaderSettings readerSettings = new XmlReaderSettings();

                readerSettings.ValidationType = ValidationType.Schema;

                readerSettings.ConformanceLevel = ConformanceLevel.Auto;

                readerSettings.Schemas.Add(schema);

 

                readerSettings.ValidationEventHandler += new ValidationEventHandler(validationEventHandler);

 

                XmlReader objXmlReader = XmlReader.Create(xmlReader, readerSettings);

 

                keepExecute = valid || !backOnError;

 

                while (keepExecute && objXmlReader.Read())

                {

                    ////empty loop to check each node, when meet some invalid node will return.

                }

 

            }

            catch (Exception ex)

            {

                sb.AppendLine(ex.Message);

            }

        }

 

        bool keepExecute = true;

        void validationEventHandler(object sender, ValidationEventArgs args)

        {

            valid = false;

            keepExecute = valid || !backOnError;

            sb.AppendLine(string.Format("Line:{0} - Position: {1} - {2}", xmlReader.LineNumber, xmlReader.LinePosition, args.Message));

        }

    }

}

 

2.2       直接利用XMLDocument

利用这种方式,只能检测出第一条错误的信息,然后就返回了,简单的代码如下:

using System;

using System.IO;

using System.Xml;

using System.Xml.Schema;

using System.Text;

using System.Xml.XPath;

 

namespace XSDStudy

{

    public class XmlDocumentValidator

    {

        StringBuilder sb;

        public string Message

        {

            get { return sb.ToString(); }

        }

 

        bool valid = false;

        public bool Valid

        {

            get { return valid; }

        }

 

        public XmlDocumentValidator()

        {

        }

 

 

        public void Validate(string xml, string xsd)

        {

            XmlTextReader xmlReader = new XmlTextReader(new MemoryStream(Encoding.UTF8.GetBytes(xml)));

            XmlReader xsdReader = XmlReader.Create(new MemoryStream(Encoding.UTF8.GetBytes(xsd)));

            validate(xmlReader, xsdReader);

        }

 

 

        private void validate(XmlReader xmlReader, XmlReader xsdReader)

        {

            sb = new StringBuilder();

            valid = true;

            try

            {

                XmlReaderSettings settings = new XmlReaderSettings();

                settings.Schemas.Add(null, xsdReader);

                settings.ValidationType = ValidationType.Schema;

 

                XmlReader reader = XmlReader.Create(xmlReader, settings);

                XmlDocument document = new XmlDocument();

                document.Load(reader);

 

                ValidationEventHandler eventHandler = new ValidationEventHandler(validationEventHandler);

 

                document.Validate(eventHandler);

            }

            catch (Exception ex)

            {

                sb.AppendLine(ex.Message);

            }

        }

 

        void validationEventHandler(object sender, ValidationEventArgs e)

        {

            valid = false;

            switch (e.Severity)

            {

                case XmlSeverityType.Error:

                    sb.AppendLine(string.Format("Error: {0}", e.Message));

                    break;

                case XmlSeverityType.Warning:

                    sb.AppendLine(string.Format("Warning {0}", e.Message));

                    break;

            }

        }

    }

}

 

修改上述方法,使得可以直接针对文件进行验证。