XML Schema

  驗證XML文檔是否符合議定的XML結構有兩種方法,分別是DTD模式與XML Schema。本文主要介紹XML Schema。

一、XML Schema的優點

  1. XML Schema基於XML,沒有專門的語法。
  2. XML Schema可以像其他XML文件一樣解析和處理。
  3. XML Schema支持一系列的數據類型(int、float、Boolean、date等)。
  4. XML Schema提供可擴充的數據模型。
  5. XML Schema支持綜合命名空間。
  6. 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基本數據類型

  Schema的基本數據類型如下:

數據類型 說明
boolean true/false
datetime 格式:CCYY-MM-DDThh:mm:ss
decimal 任意精度的十進制數字
string 字符串數據
int 整型
nonNegativeInteger 大於或等於0的整型
nonPositiveInteger 小於或等於0的整型
short 短整型 -32768到32767

  2、約束

  內置的數據類型功能雖然已經有一定的限制功能,但是還是遠遠不足夠的,更進一步的約束還是來看看約束。

約束 說明
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>

  3、簡單類型

  簡單類型是對一個節點的可能值進一步限制的自定義數據類型。創建簡單類型需要利用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中的一個。

  4、列表類型

  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>

  5、聯合類型

  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>

  同時包含兩個是錯誤的。

  6、匿名類型

  前面定義元素類型的時候總是先定義一個數據類型,然後再把元素的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元素裏面的類型,我們稱之爲匿名類型。

  7、複雜類型

  複雜類型的定義必須使用complexType元素,在這裏可以包含屬性和元素。在複雜類型的使用中,主要是complexType和simpleType配合使用。

  8、內容模型

  內容模型可以對在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屬性允許的值爲:

  1. ##any:元素可以來自任何命名空間。
  2. ##other:元素可以來自除了該元素的父元素所在的目標命名空間之外的命名空間。
  3. ##local:元素不受命名空間限制。
  4. ##targetNamespace:元素來自父元素的目標命名空間。

  processContents屬性說明對這裏所創建的元素進行驗證時所執行的操作。

  processContents屬性取值有如下三種:

  1. strict:表明XML處理器必須獲得和哪些命名空間相關聯的模式,並驗證元素和屬性。
  2. lax:與strict類似,只是如果處理器找不到模式文檔,也不會出現錯誤。
  3. 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>
複製代碼

代碼文件: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();
        }
複製代碼

代碼文件: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();
        }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章