【其他】XML及Schema

XML

一、XML

XML document 描述了 structure and data.

  • has internal representation of a tree: DOM tree or infoset
  • is divided into smaller pieces called elements

1. 基本原則

XML 有着嚴格的錯誤處理(XML has draconian error handling )

  • 接受時嚴格
  • 發送時嚴格

Postel’s Law: 發送時要保守;接收時要開放. 即: XML 僅滿足Postel’s Law第一條

2. 基本語法

基本結構

第一行是XML聲明,定義XML的版本和使用的編碼

  <?xml version="1.0" encoding="ISO-8859-1"?>
  <root>
  ...
  </root>

a. 規則

  • 所有元素都須擁有關閉標籤: <p>This is a paragraph</p>

  • XML標籤對大小寫敏感: <message> 這是正確的 </message>

  • XML必須正確的嵌套:<b><i> Hello </i><b>

  • XML文檔必須擁有一個根元素(有且僅有一個): <root> </root>

  • XML的屬性值需加引號: <node date="08/08/2020"> </node>

  • XML可以使用空元素: <myname/>

b. 元素 和 屬性

  <node date="08/08/2019">	  <!-- 屬性 -->
      <day>08</day>			  <!-- 元素 -->
  	  <month>08</month>
  	  <year>2019</year>
  </node>

因爲屬性引起的一些問題:

  • 屬性無法包含多重的值
  <!-- 錯誤,不可重複key-->
  <a type="red" type="red"></a>
  • 屬性無法描述樹結構
  • 屬性不易擴展
  • 屬性難以閱讀和維護

使用元素來描述數據,屬性提供與數據無關的信息

c. namespace

XML 命名空間提供避免元素命名衝突的方法: <h:table> </h:table>

# 我們可以在一個文檔中定義多個命名空間
<b:book xmlns:b="http://www.atguigu.com/xml/b" xmlns:a="http://www.atguigu.com/xml/a">
# 可以聲明一個默認的命名空間, 但是要注意的是一個文檔中只能有一個默認的命名空間
<book xmlns="http://www.atguigu.com/xml/b" xmlns:a="http://www.atguigu.com/xml/a">
# 屬性定義的命名空間優先級高於標籤, 即table的命名空間爲foo2
<root xmlns:b="bar" xmlns:f="foo" xmlns="bar">
    <f:table xmlns:f="foo2">
        <b:tr>
            <td>Apples</td>
            <td>Bananas</td>
        </b:tr>
    </f:table>
</root>

3. DOM

XML DOM是用於獲取、更改、添加和刪除XML元素的標準。

a. XML DOM 節點樹

DOM 將 XML 文檔作爲一個樹形結構,而樹葉被定義爲節點。節點樹中的節點彼此之間都有等級關係

    <?xml version="1.0" encoding="UTF-8"?>
    <mytext content="medium">
    	<title>Hallo!</title>
    	<content>Bye!</content>
    </mytext>

b. Python 操作DOM實例

參考文檔: XML DOM 獲取節點值

加載並解析XML文件

  import xml.dom.minidom
  import sys
  filename_xml = sys.argv[1]
  # dom: 由解析器創建的 XML 文檔
  dom = xml.dom.minidom.parse(filename_xml)

獲取元素值

  # getElementsByTagName()方法返回包含擁有指定標籤名的所有元素的節點列表,
  # 其中的元素的順序是它們在源文檔中出現的順序。
  mytextNodes = dom.getElementsByTagName("mytext")
  
  for textNode in mytextNodes:
  	titleNode = textNode.childNodes[1]
  	# childNodes[0]: 元素的第一個子元素, 文本節點
  	titleNodeText = titleNode.childNodes[0]
  	# nodeValue: 文本節點的值
  	print(titleNodeText.nodeValue)    # Hallo!

獲取屬性值

  mytextNodes[0].getAttribute("content");

二、XML Schema

1. RelaxNG

  <?xml version="1.0" encoding="UTF-8"?> 
  <people>
  	<person age="41">
  		<name>
  			<first>Harry</first>
  			<last>Potter</last>
  		</name>
  		<address>4 Main Road </address>
  		<project type="epsrc" id="1">DeCompO </project>
  		<project type="eu" id="3"> TONES </project>
  	</person> 
  	<person> 
  		.... 
  </people>

a. 緊湊語法(compact syntax)

參考文檔:RELAX NG Compact Syntax Tutorial

  grammar { 
  	start = people-element
  
  	people-element = element people  { 
  		person-element+ 
  	}
  	person-element = element person {
  		attribute age { text },
  		// 無符號: require
  		name-element,
  		// +: 出現1次或1次以上
  		address-element+,
  		// *: 出現0次或0次以上
  		project-element*
  	}
  	...
  }

數據類型:

text
xsd:integer
xsd:date

b. XML語法(XML syntax)

參考文檔: 官方文檔

  <?xml version="1.0" encoding="UTF-8"?>
  <grammar xmlns="http://relaxng.org/ns/ structure/1.0">
  	<start>
  		<ref name="name-element"> </ref>
  	</start>
  	
  	<define name="people-element">
  		<element name="people">
  			<oneOrMore>
  				<ref name="person-element"/>
  			</oneOrMore>
  		</element>
  	</define>
    
    <define name="person-element">
        
    </define>
  	...
  </grammar>

其他語法:

<element name="addressBook">
    <zeroOrMore>
        <element name="card">
            <choice>
                <element name="name">
                    <text/>
                </element>
                <group>
                    <element name="givenName">
                        <text/>
                    </element>
                    <element name="familyName">
                        <text/>
                    </element>
                </group>
            </choice>
            <optional>
                <element name="note">
                    <text/>
                </element>
            </optional>
        </element>
    </zeroOrMore>
</element>

2. XSD

參考文檔: XSD 教程

a. 元素

**簡易元素(simpleContent)😗*只包含文本的元素,它不會包含任何其他的元素或屬性

# 定義
<xs:element name="xxx" type="yyy"/>							# 元素
<xs:attribute name="xxx" type="yyy"/>						# 屬性
# 默認值和固定值
<xs:element name="color" type="xs:string" default="red"/>	# 默認值
<xs:element name="color" type="xs:string" fixed="red"/>		# 固定值

複合元素: 包含了其他的元素及/或屬性

<xs:element name="age" type="AgeType"/>
...
<xs:complexType name="AgeType">
    # sequence 定義的元素必須以此順序出現
    <xs:sequence>
        <xs:element name='Name' type="xs:string">
        <xs:element name='DoB' type="xs:date">
    </xs:sequence>
    <xs:attribute name="friend" type="xs:boolean" default="true" />
    <xs:attribute name="phone" type="xs:string" /> 
</xs:complexType>

帶有混合內容的複合類型

<letter>
    Dear Mr.
    <name>John Smith</name>.
    Your order 
    <orderid>1032</orderid>
</letter>

爲了讓字符數據可以出現在 “letter” 的子元素之間,mixed 屬性必須被設置爲 “true”

<xs:element name="letter">
  <xs:complexType mixed="true">
    ...
  </xs:complexType>
</xs:element>

b. 限定(restriction)

限定(restriction)用於爲 XML 元素或者屬性定義可接受的值。對 XML 元素的限定被稱爲 facet

限定 描述
enumeration 定義可接受值的一個列表
pattern 定義可接受的字符的精確序列
length 定義所允許的字符或者列表項目的精確數目
maxInclusive 定義數值的上限。所允許的值必須小於或等於此值
maxLength 定義所允許的字符或者列表項目的最大數目
minInclusive 定義數值的下限。所允許的值必需大於或等於此值
minLength 定義所允許的字符或者列表項目的最小數目

範圍約束: 限定值的範圍爲minInclusive - maxInclusive

<!-- <age>4</age> -->

<xs:element name="age">
    <xs:simpleType>
      <xs:restriction base="xs:integer">
        <xs:minInclusive value="3"/>
        <xs:maxInclusive value="7"/>
      </xs:restriction>
    </xs:simpleType>
</xs:element> 

枚舉約束: 把 XML 元素的內容限制爲一組可接受的值

<xs:element name="car">
    <xs:simpleType>
      <xs:restriction base="xs:string">
        <xs:enumeration value="Audi"/>
        <xs:enumeration value="Golf"/>
        <xs:enumeration value="BMW"/>
      </xs:restriction>
    </xs:simpleType>
</xs:element> 

模式約束: 使用正則表達式,把 XML 元素的內容限制定義爲一系列可使用的數字或字母

<xs:element name="letter">
    <xs:simpleType>
      <xs:restriction base="xs:string">
        <xs:pattern value="[a-z]"/>
      </xs:restriction>
    </xs:simpleType>
</xs:element> 

c. 擴展(extension)

舉例說明: 通過添加三個元素,對一個已有的 complexType 元素進行擴展

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

<xs:element name="employee" type="fullpersoninfo"/>

<xs:complexType name="personinfo">
  <xs:sequence>
    <xs:element name="firstname" type="xs:string"/>
    <xs:element name="lastname" type="xs:string"/>
  </xs:sequence>
</xs:complexType>

<xs:complexType name="fullpersoninfo">
  <xs:complexContent>
    <xs:extension base="personinfo">
      <xs:sequence>
        <xs:element name="address" type="xs:string"/>
        <xs:element name="city" type="xs:string"/>
        <xs:element name="country" type="xs:string"/>
      </xs:sequence>
    </xs:extension>
  </xs:complexContent>
</xs:complexType>

</xs:schema>)

4. 對比

RelaxNG: grammar-based

  • simple/flexible: easy to use
  • no mechanism for manipulating datatypes, lists, unions,… [however, can borrow this from XSD]
  • no restrictions & extension, no (non-atomic) types
    • in a document, an element of a type derived by restriction from Y can be used in place of an element of type Y

    • this can make writing complex schemas easier & leaves information in IR!

    • but this means that a validating XML parser has to manage a schema’s type hierarchy

DTDs and XML Schema (XSD): rule-based

  • XML Schema has restrictions on expressing constraints on content models
    • e.g., XML Element Declarations Consistent constraint
    • applications can do error-checking in a format independent way

三、Schematron

一、基本概念

Schematron 文檔基本上是一組應用於 XML 數據的約束

斷言 (asserts)

對應用於實例文檔的特定條件進行測試,實例文檔要想有效,所有斷言的計算結果都必須是 true

<assert test = "count(//b/(*|text())) = 0">
    Error: b elements must be empty
</assert>

報告 (reports)

在這種情況下也對應用的條件進行測試。但是,測試的意義與斷言的意義正好相反。如果測試結果是 true,那麼文檔將處於無效狀態

<report test = "count(//b/(*|text()))!= 0">
    Error: b elements must be empty
</report>

example: “At least 1 person for each family”

<pattern>
    <rule context="person">
        <let name="L" value="@LastName"/>
        <report test="count(//family[@name = $L]) = 0"> 
            There has to be a family for each person mentioned, 
            but <value-of select="$L"/> has none! 
        </report>
    </rule>
</pattern>
<PList>
    <person FirstName="Bob" LastName="Builder"/>
    <person FirstName="Bill" LastName="Bolder"/>
    <person FirstName="Bob" LastName="Milder"/>
    <family name="Builder" town="Manchester"/>
    <family name="Bolder" town="Bolton"/>
</PList>

# output 
Severity: error
Description: There has to be a family for each person mentioned, but Milder has none!

四、PSVI

參考文檔: Post-Schema-Validation Infoset

架構驗證後信息集(Post-Schema-Validation Infoset)

基於 Schema 的驗證完成後,可以按照 Schema 所隱含的數據模型來表達文檔的結構與內容。XML Schema 數據模型包括:

  • 樹形結構及數據內容
  • 標籤(類型註釋)
  • 添加了默認值(元素和屬性)
  • 有效性或無效性結果

這些信息的集合即爲 Schema 既驗信息集 (Post-Schema-Validation Infoset (PSVI)). 對於有效的 XML,PSVI 給它賦以特定的“類型”,從而便於以對象方式來處理整個文檔,並應用面向對象程序設計(OOP)範式。

1. 特點說明

假設P1和P2相同:

  • D1和D2可以不相同, 存在結構相同但某些元素上的屬性不同

  • S1與S2可以不相同, S1和S2指定不同的默認值。 那麼它們都不是相似/相同/等價的

2. 舉例說明:

<p:pipeline xmlns:p="http://www.w3.org/ns/xproc" name="main" version="1.0">
    <p:validate-with-xml-schema>
        <p:input port="schema">
            <p:document href="../docs/document.xsd"/>
        </p:input>
    </p:validate-with-xml-schema>
</p:pipeline>

處理: XML Schema輸出是PSVI,其中可能包含默認屬性和類型信息。 在這裏,我們看到一個默認屬性添加到div元素。

<doc>
    <title>Title</title>
    <div>
        <p>Some paragraph.</p>
    </div>
</doc>
<!-- 輸出: 添加了默認值 -->
<doc>
    <title>Title</title>
    <div class="normal">
        <p>Some paragraph.</p>
    </div>
</doc>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章