1.Schema概要
XML是可扩展标记语言,也就是说其中的节点标记设置由用户定义生成。如果没有有效的办法来校验XML的合法性,往往会导致很多问题。因此xml通过校验达到合法性规范性,同时也可以对xml节点中的数据校验。
这次学习中,运用的XML校验是通过XML Schema(XSD)。其本身是一个XML文档,所以必须满足XML文档结构。在每个Schema文档中必须包含一个根元素。
2.Schema文档结构
#xml
<?xml version="1.0" encoding="GBK"?>
<note xmlns="">
<to>George</to>
<from>John</from>
<heading>Reminder</heading>
<body>Don't forget the meeting!</body>
</note>
#schema
<?xml version="1.0" encoding="GBK"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="" xmlns="" elementFormDefault="qualified">
<xs:element name="note">
<xs:complexType>
<xs:sequence>
<xs:element name="to" type="xs:string"/>
<xs:element name="from" type="xs:string"/>
<xs:element name="heading" type="xs:string"/>
<xs:element name="body" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
说明:
xmlns:xs=”http://www.w3.org/2001/XMLSchema”:显示 schema 中用到的元素和数据类型来自命名空间 “http://www.w3.org/2001/XMLSchema“。同时它还规定了来自命名空间 “http://www.w3.org/2001/XMLSchema” 的元素和数据类型应该使用前缀 xs:
targetNamespace=”” :显示被此 schema 定义的元素验证的XML来自的命名空间。
xmlns=”” :作用是赋予命名空间一个唯一的名称。
elementFormDefault=”qualified” :指目标XML是否遵循本Schema,qualified表示遵循,unqualified表示不遵循。
3.java代码实现
java中 javax.xml有自带可以生成schema的校验器,方法的理解调用基本上通过API学习。
SchemaFactory.API
http://www.cjsdn.net/Doc/JDK50/javax/xml/validation/SchemaFactory.html
#具体的实现块
private static String byXsd(String xmlString,String xsdString) throws SAXException, IOException {
//从xml转换为字节流构造 StreamSource
Source xmlSource = new StreamSource(new ByteArrayInputStream(xmlString.getBytes()));
Source xsdSource = new StreamSource(new ByteArrayInputStream(xsdString.getBytes()));
StringWriter stringWriter = new StringWriter();
PrintWriter printWriter = new PrintWriter(stringWriter);
Result destResult = new StreamResult(printWriter);
//查找支持指定模式语言的 SchemaFactory 的实现并返回它
SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
//以相对应的xsd生成schema,解析作为模式的指定源并以模式形式返回它。
Schema schema = factory.newSchema(xsdSource);
//进行校验
Validator validator = schema.newValidator();
validator.validate(xmlSource, destResult);
String desc = stringWriter.toString();
printWriter.close();
return desc;
}
#这里得到的结果为打印成功,返回成功的xml字符串格式
<?xml version="1.0" encoding="UTF-8"?><note><to>George</to><from>John</from><heading>Reminder</heading><body>Don't forget the meeting!</body></note>
#另一种不需要返回xml的方式,可以这样实现
try {
schema = factory.newSchema(xsdSource);
Validator validator = schema.newValidator();
validator.validate(xmlSource);
} catch (SAXException | IOException e) {
// TODO Auto-generated catch block
// e.printStackTrace();
System.out.println("Exception: " + e.getMessage());
return false;
}
return true;
#所得结果可以是:validation result:true
#注意:validator.validate()这个方法返回类型为void,只进行校验,需要的返回信息都是代码中额外再实现的。
4.遇到的主要问题
Exception in thread “main” org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 28; cvc-elt.1: 找不到元素 ‘note’ 的声明。
at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:203)
…
这里最后的解决办法是,保持targetNamespace和xmlns所指向的唯一命名空间一致,且xml中的也需要一致,这里最终我是设为空,则xml中的note处可不填,xsd中的命名空间都指向空。
注:初次实践时,遇到这个问题以为是xsd模板生成成功,而validator.validate(xmlSource)读取xml文档时无法读取到note节点。经过测试,发现猜测错误,问题出现的原因是方法读取xml的note节点而xsd模板没有生效成功。