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"

关于xmlnstargetNamespace的意义区分
可重用元素的使用与命名空间
xmlns与targetNamespace
关于XML Schema命名空间中已经有xmlns却还要targetnamespace的理解
我的理解:
一个元素节点添加了targetNamespace,那么这个节点以及节点之下就是用来定义这个节点。如果要用这个节点 下的元素,那么就得加上这个节点的targetNamespace,而且还必须j加上xmlns:xxx=ttt(这里的ttt代表targetNamespace,xxx代表targetNamespace的别名,然后在调用的地方使用xxx:nnn),哪怕是在这个节点之中“调用”。所以,如果你写的这个xsd并不打算让别人调用,那么就别写什么targetNamespace,这只会给你增加麻烦:自己定义的类型,同一个文件内调用还得加上命名空间,多麻烦

二、一些常用的知识

  1. 简易类型:

    • xs:string
    • xs:decimal【十进制数】
    • xs:integer【也有int类型】
    • xs:boolean
    • xs:date
    • xs:time
  2. 字符串类型是我们在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 (布尔数据类型无法使用此约束)

三、注意几个问题

  1. 如果你想 定义一个类型,然后在其他地方重复引用,不要定义成元素
    正确:
<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>
  1. 当使用all指示器的时候,minOccurs可以选0或1,maxOccurs只能选1。即任意排序里的“子元素组”只能有1组。否则会报错的!
  2. Order指示器和Group指示器的默认子元素个数都是1,你如果想允许xml里可以写多个元素,只能自己修改minOccurs、maxOccurs
  3. 为了避免用户在填写xml的内容是出现不必要的空格,我建议string类型改为token类型,它可以去掉前后空格及tab(很多网上的解释感觉很有歧义:也不知道这个类型的意思是可以去掉空格,还是不能包含空格 否则报错;试验一下就知道了,在填写xml的string类型时加上空格tab并不报错,所以它的意思是帮你在读取的时候过滤掉空格)

四、使用代码校验xml

设计好xml,写好schema后就可以写程序进行校验了
有个问题:xml可以用schema来校验,那schema自己的对错怎么检验呢
其实很简单,把schema粘到eclipse里就行了,对于语法上的错误,比如一开始说的那个,使用了targetNamespace,结果在下面引用了 这个schema里定义的类型,还没有加 命名空间。写到eclipse里就会报错了。当然,eclipse也只能检验语法错误,“逻辑”错误谁也没辙。

  1. 如果想写完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文件进行相互检验

  1. 最终还是要落实到代码上
    因为代码很固定,即使使用的框架不同,但最终都是一段差不多固定的代码,就不再重复,给两个还不错的链接:
    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的人理解是什么错误了,再解释 也无非把那几个英文单词翻译一下

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值