XMl Schema校验

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)

这里最后的解决办法是,保持targetNamespacexmlns所指向的唯一命名空间一致,且xml中的也需要一致,这里最终我是设为空,则xml中的note处可不填,xsd中的命名空间都指向空。

注:初次实践时,遇到这个问题以为是xsd模板生成成功,而validator.validate(xmlSource)读取xml文档时无法读取到note节点。经过测试,发现猜测错误,问题出现的原因是方法读取xml的note节点而xsd模板没有生效成功。


版权声明:本文为BERRYL_weibo原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。