java通過schema校驗xml
之前在做專案時時常需要通過一些“小xml”傳輸或儲存一些資訊,然後就在讀取的時候需要先判斷xml資料是否符合要求,包括這次也是這樣,不同的是 這次我設計了一個比較複雜的xml,結果讀取xml資料 裡穿插著各種判斷,洋洋灑灑寫了一大坨程式碼。然後我就想不是有schema這種xml描述語言嗎,那應該也可以在程式碼裡用它進行校驗xml…
在實現使用schema校驗xml這個目標前,你首先得自己會根據自己的xml要求格式寫出對應的schema,我認為寫schema佔實現校驗目標的七成,剩下的三成才是使用程式碼去校驗。因為一旦有schema,通過框架去校驗就是一段很固定的寫法了,這也就是為什麼要提議使用schema,可以大大減少不必要的重複程式碼工作,而可以專心於讀取資料處,處理關鍵邏輯。
一、幾個重要的標頭
xmlns:xs="http://www.w3.org/2001/XMLSchema"
顯示 schema 中用到的元素和資料型別來自名稱空間 “http://www.w3.org/2001/XMLSchema“。同時它還規定了來自名稱空間 “http://www.w3.org/2001/XMLSchema” 的元素和資料型別應該使用字首xs:
xmlns="http://www.runoob.com"
指出該檔案的預設名稱空間,在文件中所有的名字前面如果沒有字首的,就是由預設名稱空間進行定義和解析的。使用預設名稱空間,可以不加空間字首。
targetNamespace="http://www.runoob.com"
標明節點下面所定義的型別都屬於這個名稱空間。使用targetNamespace名稱空間下的元素必須要加字首。
elementFormDefault="qualified"
表示任何xml中使用本xsd中宣告的元素必須使用名稱空間
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
這句話引用的這個名稱空間是幹什麼呢(它和xmlns:xs
一樣都是一個正常的引用語句,xs
,xi
都是一個別名),他和下面這句話有關:因為下面這句話需要指出你應用的名稱空間的實際的文件在放在哪。這個屬性就是schemaLocation,而這個屬性被定義在http://www.w3.org/2001/XMLSchema-instance
中
xsi:schemaLocation="http://www.runoob.com note.xsd"
關於xmlns
和targetNamespace
的意義區分
可重用元素的使用與名稱空間
xmlns與targetNamespace
關於XML Schema名稱空間中已經有xmlns卻還要targetnamespace的理解
我的理解:
一個元素節點新增了targetNamespace,那麼這個節點以及節點之下就是用來定義這個節點。如果要用這個節點 下的元素,那麼就得加上這個節點的targetNamespace,而且還必須j加上xmlns:xxx=ttt(這裡的ttt代表targetNamespace,xxx代表targetNamespace的別名,然後在呼叫的地方使用xxx:nnn),哪怕是在這個節點之中“呼叫”。所以,如果你寫的這個xsd並不打算讓別人呼叫,那麼就別寫什麼targetNamespace,這隻會給你增加麻煩:自己定義的型別,同一個檔案內呼叫還得加上名稱空間,多麻煩
二、一些常用的知識
簡易型別:
- xs:string
- xs:decimal【十進位制數】
- xs:integer【也有int型別】
- xs:boolean
- xs:date
- xs:time
字串型別是我們在xml裡最常用的型別,但有時候 我只希望使用者填寫固定的某幾個字串,實現“列舉型別”,那麼可以這麼寫
<xs:simpleType name="carType">
<xs:restriction base="xs:string">
<xs:enumeration value="Audi"/>
<xs:enumeration value="Golf"/>
<xs:enumeration value="BMW"/>
</xs:restriction>
</xs:simpleType>
這就實現了個簡單的列舉型別,首先是string型別的,然後限定在“Audi”,“Golf”,“BMW”裡面的其中一個。
下面是常用的幾種對字串限定的方式
- enumeration (布林資料型別無法使用此約束*)
- length (布林資料型別無法使用此約束)
- maxLength (布林資料型別無法使用此約束)
- minLength (布林資料型別無法使用此約束)
三、注意幾個問題
- 如果你想 定義一個
型別
,然後在其他地方重複引用,不要定義成元素
了
正確:
<xs:element name="product" type="prodtype"/>
<xs:complexType name="prodtype">
<xs:attribute name="prodid" type="xs:positiveInteger"/>
</xs:complexType>
錯誤:
<xs:element name="product" type="prodtype"/>
<xs:element name="product" type="prodtype"/>
<xs:complexType>
<xs:attribute name="prodid" type="xs:positiveInteger"/>
</xs:complexType>
</xs:element>
- 當使用all指示器的時候,minOccurs可以選0或1,maxOccurs只能選1。即任意排序裡的“子元素組”只能有1組。否則會報錯的!
- Order指示器和Group指示器的預設子元素個數都是1,你如果想允許xml裡可以寫多個元素,只能自己修改minOccurs、maxOccurs
- 為了避免使用者在填寫xml的內容是出現不必要的空格,我建議string型別改為token型別,它可以去掉前後空格及tab(很多網上的解釋感覺很有歧義:也不知道這個型別的意思是可以去掉空格,還是不能包含空格 否則報錯;試驗一下就知道了,在填寫xml的string型別時加上空格tab並不報錯,所以它的意思是幫你在讀取的時候過濾掉空格)
四、使用程式碼校驗xml
設計好xml,寫好schema後就可以寫程式進行校驗了
有個問題:xml可以用schema來校驗,那schema自己的對錯怎麼檢驗呢
其實很簡單,把schema粘到eclipse裡就行了,對於語法上的錯誤,比如一開始說的那個,使用了targetNamespace,結果在下面引用了 這個schema裡定義的型別,還沒有加 名稱空間。寫到eclipse裡就會報錯了。當然,eclipse也只能檢驗語法錯誤,“邏輯”錯誤誰也沒轍。
- 如果想寫完schema就看看效果, 就把xml和他對應的sxd檔案都放在eclipse的同一個工程的同一個目錄下,然後在xml的標頭裡加上
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="ddddd.xsd"
還記得一開始說的XMLSchema-instance裡的schemaLocation
屬性嗎,它需要寫成這樣
xsi:schemaLocation="http://www.runoob.com note.xsd"
前一個值是名稱空間名稱,後一個才是schema所處的真正位置。而它的同胞noNamespaceSchemaLocation
從名字上就可以看出,這個不需要名稱空間名稱,而只需要真實地址就行了,所以我直接寫上schema的位置,在eclipse裡就可以“實時”看看效果了,xml格式不符合xsd要求的時候,xml就會報錯。可以通過這種簡單的方式對xml和schema檔案進行相互檢驗
- 最終還是要落實到程式碼上
因為程式碼很固定,即使使用的框架不同,但最終都是一段差不多固定的程式碼,就不再重複,給兩個還不錯的連結:
Java通過XML Schema校驗XML
Schema和XMLErrorHandler問題
就說一點,和第二個連結有關:我們是否需要把xml校驗的錯誤結果給出很“人性化,通俗”的錯誤反饋?
我的個人想法:既然我們用了xml來傳輸資料,那麼對方一般就不是什麼都不懂的“外行人”。對於“程式對程式”的傳輸,傳輸方就根本不應該出現 xml格式錯誤的問題:我們既然寫了schema,就是對外公開的,你在傳送之前就得保證自己是按照schema的格式要求寫的。 對於“人對程式”,把這樣的錯誤資訊:
<errors>
<error column="35" line="17" systemID="file:///E:/workspace-jzgk/loginUtil/web-enter.xml">cvc-enumeration-valid: Value 'ID1' is not facet-valid with respect to enumeration '[ID, NAME, CLASS, LINK_TEXT, PARTIAL_LINK_TEXT, XPATH, CSS_SELECTOR]'. It must be a value from the enumeration.</error>
<error column="35" line="17" systemID="file:///E:/workspace-jzgk/loginUtil/web-enter.xml">cvc-type.3.1.3: The value 'ID1' of element 'fix-type' is not valid.</error>
</errors>
反饋給使用者,基本已經夠 一個會配置xml的人理解是什麼錯誤了,再解釋 也無非把那幾個英文單詞翻譯一下
相關文章
- 格式校驗利器:JSON Schema 簡介JSON
- XML Schema定義XML
- Spring boot 與 json_schema ,請求和響應 校驗Spring BootJSON
- Spring Boot 中使用 JSON Schema 來校驗複雜JSON資料Spring BootJSON
- 通過Go來分析和建立XMLGoXML
- 如何給XML Schema增加Annotations標記BHXML
- Spring系列-XML schema擴充套件機制SpringXML套件
- PostgreSQL_通過schema控制使用者許可權SQL
- java校驗是否是日期字串Java字串
- Spring 中的 XML schema 擴充套件機制SpringXML套件
- [資料校驗/資料質量] 資料校驗框架(Java):hibernate-validation框架Java
- XML Schema(XSD)詳解:定義 XML 文件結構合法性的完整指南XML
- springMVC:校驗框架:多規則校驗,巢狀校驗,分組校驗;ssm整合技術SpringMVC框架巢狀SSM
- XML Schema 字串資料型別及約束詳解XML字串資料型別
- XML 驗證概述XML
- Java-Bean Validation後端校驗總結JavaBean後端
- java安全編碼指南之:輸入校驗Java
- 緣起 Dubbo ,講講 Spring XML Schema 擴充套件機制SpringXML套件
- 聊聊 Spring 的 XML Schema 擴充套件機制的使用方式SpringXML套件
- SpringBoot通過yml和xml檔案配置日誌輸出Spring BootXML
- 使用RFC跳過許可權校驗的方法
- Spring Cloud Gateway自定義Token校驗過濾器SpringCloudGateway過濾器
- Java解析XMLJavaXML
- ECC校驗
- 通過DNSLOG回顯驗證漏洞DNS
- ElasticSearch 通過nginx做HTTP驗證ElasticsearchNginxHTTP
- 深入Spring官網系列(十七):Java資料校驗SpringJava
- Java SpringBoot上的引數校驗JSR 303 ValidationJavaSpring BootJS
- XML Schema 複雜元素型別詳解:定義及示例解析XML型別
- 把list集合的內容寫入到Xml中,通過XmlDocument方式寫入Xml檔案中XML
- PHP透過pem檔案校驗簽名異常PHP
- 通過selenium突破極驗驗證實現登入
- vxe-table 校驗,根據行屬性校驗
- SpringBoot分組校驗及自定義校驗註解Spring Boot
- 時間序列的ADF校驗(單位根校驗)
- 行式填報 資料校驗 --- 小計校驗
- spring中bean.xml的http://www.springframework.org/schema/bean報錯SpringBeanXMLHTTPFramework
- No grammar constraints (DTD or XML Schema) referenced in the document.的兩種解決辦法AIXML
- 資料校驗