利用xmlbeans工具对xml格式进行验证(需要xsd文件)

我也不多说xmlbeans的优缺点,看完整个操作过程就知道它的优缺点了。我们有个需求,项目中需要进行对xml文件进行格式验证,并且需要输出错误具体信息,

开始的时候使用sax进行验证,这个例子我也有转载一篇,方便可用,但是就是不能输出xml格式错误具体信息,只能显示是否合法,所以不满足项目需求,

看到xmlbeans工具,发现可行,下面具体介绍操作步骤及xmlbeans实现原理。


首先下载xmlbeans工具,我这里有个2.6.0的版本,挺好用的

链接:

http://download.csdn.net/detail/cronousgt/9787716

实现原理:我简单说一下,xsd(xml schemas definition)文件是对xml文件进行格式化定义的文件,他是xml文件的规范及约束,当然DTD也可以规范xml文件。这里xmlbeans主要使用xsd文件

1.首先我们需要有一份定义你的xml文件结构的xsd文件,这里我有一份叫 tableInfo.xsd 文件,这是一份描述数据库库表信息的文件,文件描述什么的不重要,重要的是他就是你需要操作的xml文件的结构定义xsd文件,我们假设需要我们验证格式的xml文件就是 tableInfo.xml文件

2.第二步我们需要生成以tableInfo.xsd文件为模版的之后可操纵tableInfo.xml文件的jar文件(当然这里不一定只是操作tableInfo.xml文件,只要是符合tableInfo.xsd文件格式的都行,名字叫abc.xml也是可以的)

2.1下载过工具压缩包后,将文件解压,就解压在c盘好了,我这里就是解压在c盘,截图如下:


2.2配个环境变量吧,当然如果你进目录不嫌烦也可以不配,cd到 C:\xmlbeans-2.6.0 目录,这里我们还是配一下,截图



方便你们配置 变量&路径 : XMLBEANS_HOME   C:\xmlbeans-2.6.0      

     Path%XMLBEANS_HOME%\bin;

若果你是win10 Path直接可以编辑,最后的分号可以不加

最后检查一下 命令行输入 scomp命令 看看有没有出现如下图所示


如上图所示即为成功

2.3在c盘下建立一个src文件夹作为输出源,src下面建立一个jar文件夹用来存放生成的jar,建立完成后,这里我们还需要一个xsdconfig文件(自己手动建立),这个文件是配置你要生成的jar包中class类放在什么package里面,这个其实用的时候无所谓,但是需要配置一下,随你喜好,比如说我的这个xsdconfig文件如下,建立好这个文件后我放在了src目录下:

<xb:config xmlns:xb="http://xml.apache.org/xmlbeans/2004/02/xbean/config">
    <xb:namespace>
        <xb:package>metadataCheck.controllers</xb:package>
    </xb:namespace>
</xb:config>
我们先看下后来这个配置的作用,就是将class放在 metadataCheck.controllers 包下,给一个生成好的 jar的图示例,看图就明白了:


2.4准备工作已经做好,现在我们来生成所需的操作xml的jar 在命令行输入如下命令:

scomp -out C:\src\jar\tableInfo-xmlbeans.jar  C:\src\tableInfo.xsd  -compiler C:\JDK\jdk1.7\bin\javac  c:\src\tableInfo.xsdconfig
这里我们我们稍微说一下, -out是 jar文件输出位置, 根据的是src下面我们的tableInfo.xsd文件,

-compiler 后面是你的jdk中javac的路径  最后加上我们class放在什么包下的tableInfo.xsdconfig文件路径。 执行成功如下图所示:


2.5将生成好的tableInfo-xmlbeans.jar拿出来导入我们的项目中,即可使用,这里看一下我的xs文件结构,方便大家理解

<?xml version="1.0" encoding="utf-8"?>
<!--edit by Cronous 2017 1-17-->
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tab="http://www.hhu.edu.cn" elementFormDefault="qualified" attributeFormDefault="unqualified">
	<!-- A.1 MD_Metadata数据表信息DOM_TABLE元数据项定义 -->
	<xs:complexType name="Metadata">
		<xs:sequence>
			<xs:element name="contInfo" type="contInfo" id="Metadata_角色名称_内容信息" minOccurs="1" maxOccurs="unbounded">
				<xs:annotation>
					<xs:documentation>中文名称:Metadata_角色信息_内容信息</xs:documentation>
					<xs:documentation>定义:提供要素类目信息</xs:documentation>
				</xs:annotation>
			</xs:element>
		</xs:sequence>
	</xs:complexType>
	<!--元数据内容信息-->
	<xs:complexType name="contInfo">
		<xs:sequence>
			<xs:element name="tab_id" type="xs:decimal" id="表ID" minOccurs="1">
				<xs:annotation>
					<xs:documentation>中文名称:数据表主键</xs:documentation>
					<xs:documentation>定义:数据表主键</xs:documentation>
				</xs:annotation>
			</xs:element>
			<xs:element name="db_id" type="xs:decimal" id="所属数据源" minOccurs="1">
				<xs:annotation>
					<xs:documentation>中文名称:所属数据源</xs:documentation>
					<xs:documentation>定义:所属数据源</xs:documentation>
				</xs:annotation>
			</xs:element>
			<xs:element name="tab_e_name" type="xs:string" id="表名" minOccurs="0" maxOccurs="1">
				<xs:annotation>
					<xs:documentation>中文名称:数据表名称</xs:documentation>
					<xs:documentation>定义:数据表名称</xs:documentation>
				</xs:annotation>
			</xs:element>
			<xs:element name="tab_c_name" type="xs:string" id="表中文名" minOccurs="0" maxOccurs="1">
				<xs:annotation>
					<xs:documentation>中文名称:数据表中文名</xs:documentation>
					<xs:documentation>定义:数据表中文名</xs:documentation>
				</xs:annotation>
			</xs:element>
			<xs:element name="keyword" type="xs:string" id="关键字" minOccurs="0" maxOccurs="1">
				<xs:annotation>
					<xs:documentation>中文名称:关键字</xs:documentation>
					<xs:documentation>定义:数据表搜索关键字</xs:documentation>
				</xs:annotation>
			</xs:element>
			<xs:element name="note" type="xs:string" id="注释" minOccurs="0" maxOccurs="1">
				<xs:annotation>
					<xs:documentation>中文名称:注释</xs:documentation>
					<xs:documentation>定义:注释</xs:documentation>
				</xs:annotation>
			</xs:element>
			<xs:element name="rec_num" type="xs:decimal" id="记录数" minOccurs="0" maxOccurs="1">
				<xs:annotation>
					<xs:documentation>中文名称:记录数</xs:documentation>
					<xs:documentation>定义:数据表包含记录数</xs:documentation>
				</xs:annotation>
			</xs:element>
			<xs:element name="tab_size" type="xs:decimal" id="表大小" minOccurs="0" maxOccurs="1">
				<xs:annotation>
					<xs:documentation>中文名称:表大小</xs:documentation>
					<xs:documentation>定义:数据表表大小</xs:documentation>
				</xs:annotation>
			</xs:element>
			<xs:element name="updatestamp" type="xs:date" id="最后更新时间" minOccurs="0" maxOccurs="1">
				<xs:annotation>
					<xs:documentation>中文名称:最后更新时间</xs:documentation>
					<xs:documentation>定义:时间戳</xs:documentation>
				</xs:annotation>
			</xs:element>
			<xs:element name="meta_id" type="xs:decimal" id="元数据ID" minOccurs="0" maxOccurs="1">
				<xs:annotation>
					<xs:documentation>中文名称:表空间</xs:documentation>
					<xs:documentation>定义:数据源使用的表空间</xs:documentation>
				</xs:annotation>
			</xs:element>
		</xs:sequence>
	</xs:complexType>
	<!--Root of Document-->
	<xs:element name="Metadata" type="Metadata"/>
</xs:schema>

这时候大家再看生成的jar包中的class文件就能看懂了,这个工具读入xsd的结构,生成可以操作xml文 件对应节点的接口 ContInfo和Metadata,这样我们就可以容易的操作一个一个类型的xml文件,可读可 写,还可以自己生成xml文件,功能比较强大,对于读写操作,请看这篇微博:

http://youlong05.iteye.com/blog/87324

2.6下面我们来看对xml的验证显示具体错误信息部分,首先我的验证方法如下:

package commons;

import org.apache.xmlbeans.*;
import javax.xml.XMLConstants;
import javax.xml.stream.FactoryConfigurationError;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
import org.w3c.dom.*;
/**
 * Created by Cronous on 2017/3/1.
 */

    public static String validateXml(XmlObject xmlObject){
        String msg="";
        List<XmlValidationError> errorList = new ArrayList<XmlValidationError>();
        XmlValidationError xmlFormatError = null;
        XmlOptions xmlOptions = new XmlOptions();
        xmlOptions.setErrorListener(errorList);
        boolean isValid = xmlObject.validate(xmlOptions);
        String path = "";
        if (!isValid){
            XmlError error;
            error = errorList.get(0);
            if (error instanceof XmlValidationError){
                xmlFormatError = (XmlValidationError) error;
            }
            XmlCursor errorLoca=xmlFormatError.getCursorLocation();
            if(errorLoca!=null){
                path=getXpath(errorLoca.getDomNode());
                path=removePairMarkers(path, "[", "]");
            }
            String errorCode=xmlFormatError.getErrorCode();
            //int errorType=xmlFormatError.getErrorType();
            if(errorCode.equals(XmlErrorCodes.DATATYPE_ENUM_VALID))

                msg+=path+":"+"不是合法的枚举值";
            else if(errorCode.equals(XmlErrorCodes.ELEM_COMPLEX_TYPE_LOCALLY_VALID$EXPECTED_DIFFERENT_ELEMENT))
                msg+=path+":"+"此处不应该出现该元素";
            else if(errorCode.equals(XmlErrorCodes.ELEM_COMPLEX_TYPE_LOCALLY_VALID$MISSING_ELEMENT))
                msg+=path+":"+"缺少必填元素";
            else if(errorCode.equals(XmlErrorCodes.FLOAT))
                msg+=path+":"+"不是合法的浮点数";
            else if(errorCode.equals(XmlErrorCodes.DATATYPE_FRACTION_DIGITS_VALID))
                msg+=path+":"+"不是合法的正整数 ";
            else
                msg+=path+":"+"验证错误";
        }else{
            msg="valid";
        }
        return msg;

    }
    public static String getXpath(Node node)
    {
        String path="",parPath="";
        int index=0;
        if(node.getNodeType() == Node.DOCUMENT_NODE){
            return node.getNodeName();
        }else if(node.getParentNode().getNodeType() == Node.DOCUMENT_NODE){
            return "/"+node.getNodeName();
        }
        parPath=getXpath(node.getParentNode());
        Node pre;
        String myName;

        pre=node.getPreviousSibling();
        myName=node.getNodeName();

        while(pre!=null)
        {
            if(pre.getNodeName().equals(myName))
            {
                index++;
                pre=pre.getPreviousSibling();
            }
            else
                pre=pre.getPreviousSibling();
        }
        path=parPath+"/"+myName+"["+index+"]";

        //System.out.println(path);
        return path;
    }
    /**
     *
     * @param in : input string
     * @param left: the left marker
     * @param right: the right marker
     * @return the string that has the marker pairs removed
     *
     * 此函数用于去除输入字符串中,成对出现的标记符.例如:
     */
    public static String removePairMarkers(String in, String left, String right){

        int cCnt = 0;
        boolean leftFound = false;
        String out = "";

        while(cCnt != in.length()){
            if (!leftFound){
                int l = in.indexOf(left, cCnt);
                if (l >=0) {
                    out += in.substring(cCnt, l);
                    cCnt = l;
                    leftFound = true;
                }
                else {
                    break;
                }
            } else {
                int r = in.indexOf(right, cCnt);
                cCnt = r+1;
                leftFound = false;
            }
        }
        return out;
    }


}

调用方法:

package com;
import commons.validateXML;
import metadataCheck.daos.CatalogDao;
import metadataCheck.daos.MetadataDao;
import metadataCheck.models.CatalogModel;
import metadataCheck.models.MetaDataModel;
public class testCheckXML {


	public static void main(String[] args) {
	    //checkXML(file)传进来的的是xml文件对象
	    String xmlValidateFlag = checkXML(file);
	    //输出验证信息
        System.out.println(xmlValidateFlag);
	}
	private static String checkXML(File file) {   //这个方法,主要目的是将xml文件转换成xmlObject,进行验证
	    //这里的MetadataDocument就是jar包中的接口
        MetadataDocument metadataDocument = null;
        try {
        //将xml文件解析成XMLObject对象
            metadataDocument = MetadataDocument.Factory.parse(file);
        } catch (XmlException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        XmlObject xmlObject = metadataDocument;
        String str = validateXML.validateXml(xmlObject);
        //System.out.println(str);
        return str;
    }


}


3.验证过程到此结束。






  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值