欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

(转汇总)xml文件常用的合法验证工作 博客分类: XML相关 XML工作ApacheSOAP数据结构 

程序员文章站 2024-03-18 09:42:16
...
xsd对xml的合法性校验

=======================
part1:配置引入篇

完全遵循xml规范的格式正确的文档并不总能满足需要。许多情况下还需要保证文档的有效性。这时,一种"元数据"文档被创建来定义这个Xml文档中包含什么样的元素、属性和其他项目。有三种这样的"元数据"文档,它们是DTD、XML-DR Schema以及W3C Schema,它们定义了一个Xml文档必须遵循什么样的结构才是有效的。通过定义Xml文档的结构,应用能够在执行任何计算和转换之前对文档进行验证。

  现在很清楚了,你尽可以在xml文档中自定义所需要的标记以描述数据,任何想使用这个文档的人也可以使用它,只要你为他们提供一个文档是如何组织以及使用什么样的标记描述数据的定义即可!由于XSD Schema是万维网联盟W3C的推荐标准,下面的验证均只针对它展开。

如何从Xml文档内部引用Xml Schema验证 ?

  在创建了一个Xml Schema文档之后,就可以用它来验证xml文档的有效性了。做起来很简单,只需要在xml文档根元素内引用该schema文件就可以了。不过,根据xml schema文档是否包含targetNamespace属性,xml文档内的引用有以下两种方式:
  1、使用noNamespceSchemaLocation属性引用schema文件

  当xml schema文档不包括targetNamespace属性时,应当通过xml文档根元素的noNamespaceSchemaLocation属性及W3C的schmea实例命名空间(xmlns:xsi="http://www.w3.org/2001/XMLScheam-instance")来引用名xml schema文件。下面的例子引用不包含"targetNamespace"属性的名为"noTargetNS.xsd"的架构文件:

<?xml version="1.0" encoding="utf-8" ?>
<Employees  Xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance
"xsi:noNamespaceSchemaLocation="noTargetNS.xsd">
<Name>LinY</Name>
<Age>42</Age>
</Employees>


  2、使用schemaLocation属性引用schema文件

  然而,如果xml schmea文件包含了一个targetNamespace 属性,在xml文档中就将通过schemaLocation属性而不是noNamespaceSchemaLocation属性来引用schema文档。而且,这个属性所指定的值必须是完整的。它需要包含以空格分开的两部分,前一部分是Uri,这个Uri与schema文档的targetNamespace属性内部引用的Uri是一致的;后一部分是schema文件完整路径及名称。另外,Xml文档的根元素也必须声明schema实例名字空间(xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"),下面的例子引用包含"targetNamespace"属性的名为yesTargetNS.xsd架构文件:

<?Xml version="1.0" encoding="utf-8" ?>
<Employees Xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.tuha.net  yesTargetNS.xsd"
Xmlns="http://www.tuha.net">
<Name>XiaoM</Name>
<Age>25</Age>
</Employees>
  在xml文档内部正确地引用schema文件之后,在解析xml文档时将执行验证。

-----------------
遗留问题:
1.我写的XML与xsd通这JAVA代码编辑校验是OK的,为何在配置引入时,不能有效的校验呢?


=========================
part2 :代码编程校验篇

使用java代码对xml文件的校验,也可使用dom4j方式、Jdom方式,举例如下:
DOM4J方式源网址:http://lavasoft.blog.51cto.com/62575/97597
Jdom方式源网址: http://blog.xmulib.org/ringtail/2006/11/java_apixml.html


Dom4j方式:

/**
     * 通过XSD(XML Schema)校验XML
     */
    public static void validateXMLByXSD() {
        String xmlFileName = "Q:\\_dev_stu\\xsdtest\\src\\note.xml";
        String xsdFileName = "Q:\\_dev_stu\\xsdtest\\src\\note.xsd";
        try {
            //创建默认的XML错误处理器
            XMLErrorHandler errorHandler = new XMLErrorHandler();
            //获取基于 SAX 的解析器的实例
            SAXParserFactory factory = SAXParserFactory.newInstance();
            //解析器在解析时验证 XML 内容。
            factory.setValidating(true);
            //指定由此代码生成的解析器将提供对 XML 名称空间的支持。
            factory.setNamespaceAware(true);
            //使用当前配置的工厂参数创建 SAXParser 的一个新实例。
            SAXParser parser = factory.newSAXParser();
            //创建一个读取工具
            SAXReader xmlReader = new SAXReader();
            //获取要校验xml文档实例
            Document xmlDocument = (Document) xmlReader.read(new File(xmlFileName));
            //设置 XMLReader 的基础实现中的特定属性。核心功能和属性列表可以在 http://sax.sourceforge.net/?selected=get-set 中找到。
            parser.setProperty(
                    "http://java.sun.com/xml/jaxp/properties/schemaLanguage",
                    "http://www.w3.org/2001/XMLSchema");
            parser.setProperty(
                    "http://java.sun.com/xml/jaxp/properties/schemaSource",
                    "file:" + xsdFileName);
            //创建一个SAXValidator校验工具,并设置校验工具的属性
            SAXValidator validator = new SAXValidator(parser.getXMLReader());
            //设置校验工具的错误处理器,当发生错误时,可以从处理器对象中得到错误信息。
            validator.setErrorHandler(errorHandler);
            //校验
            validator.validate(xmlDocument);

            XMLWriter writer = new XMLWriter(OutputFormat.createPrettyPrint());
            //如果错误信息不为空,说明校验失败,打印错误信息
            if (errorHandler.getErrors().hasContent()) {
                System.out.println("XML文件通过XSD文件校验失败!");
                writer.write(errorHandler.getErrors());
            } else {
                System.out.println("Good! XML文件通过XSD文件校验成功!");
            }
        } catch (Exception ex) {
            System.out.println("XML文件: " + xmlFileName + " 通过XSD文件:" + xsdFileName + "检验失败。\n原因: " + ex.getMessage());
            ex.printStackTrace();
        }
    }


==================
使用JDOM校验:

使用JAXP进行校验

代码如下:
    // 1. Lookup a factory for the W3C XML Schema language
        SchemaFactory factory =
            SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema");
       
        // 2. Compile the schema.
        // Here the schema is loaded from a java.io.File, but you could use
        // a java.net.URL or a javax.xml.transform.Source instead.
        File schemaLocation = new File("/opt/xml/docbook/xsd/docbook.xsd");
        Schema schema = factory.newSchema(schemaLocation);
   
        // 3. Get a validator from the schema.
        Validator validator = schema.newValidator();
       
        // 4. Parse the document you want to check.
         InputStream in = new FileInputStream("/opt/xml/docbook/xsd/docbook.xml");
        Source source = new StreamSource(in);
       
        // 5. Check the document
        try {
            validator.validate(source);
            System.out.println(" valided   OK!");
        }
        catch (SAXException ex) {
            System.out.println(" failed valided ");
            ex.getMessage();
            throw ex ;
        } 

如果要使用xml自身指定的xsd进行校验,则使用下面的方法:
SchemaFactory factory = SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema");
Schema schema = factory.newSchema();
这种方法仅适用于 XSD。

(JDOM中有一段,其它的描述:
但是由于JDOM没有自己的解析器,它使用标准的解析器(如Xerces)来完成这个工作。如果想要进行schema校验必须确保选择了支持这个schema的解析器。
代码如下:
SAXBuilder builder =
  new SAXBuilder("org.apache.xerces.parsers.SAXParser", true);
builder.setFeature(
  "http://apache.org/xml/features/validation/schema", true);
builder.setProperty(
  "http://apache.org/xml/properties/schema/external-schemaLocation",
  "http://www.w3.org/2001/12/soap-envelope soap-envelope.xsd" + " " +
  "http://kevinj.develop.com/weblog/weblog.xsd weblog.xsd");
Document doc = builder.build(xml);

如果你想要使用JAXP来选择解析器,可以跳过指定类到SAXBuilder结构和用"org.apache.xerces.jaxp.SAXParserFactoryImpl"代替" javax.xml.parsers.SAXParserFactory"作为系统属性。这就告诉JAXP使用Xerces的 factory来创建解析器。可以用命令行来指定这个属性:
java -Djavax.xml.parsers.SAXParserFactory=
          org.apache.xerces.jaxp.SAXParserFactoryImpl



转贴一个别人的事例: http://topic.csdn.net/t/20040708/11/3156121.html


==================
遗留问题,以上两种JAVA代码方式,我都试用过了。但还暂不明其中的源由。