我也不多说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目录下:
metadataCheck.controllers
我们先看下后来这个配置的作用,就是将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文件结构,方便大家理解
中文名称:Metadata_角色信息_内容信息
定义:提供要素类目信息
中文名称:数据表主键
定义:数据表主键
中文名称:所属数据源
定义:所属数据源
中文名称:数据表名称
定义:数据表名称
中文名称:数据表中文名
定义:数据表中文名
中文名称:关键字
定义:数据表搜索关键字
中文名称:注释
定义:注释
中文名称:记录数
定义:数据表包含记录数
中文名称:表大小
定义:数据表表大小
中文名称:最后更新时间
定义:时间戳
中文名称:表空间
定义:数据源使用的表空间
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 errorList = new ArrayList();
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;
}
}