使用dom4j解析XSD文件

时间:2021-08-18 06:25:54

 在比较大的项目中,我们有时会用到服务这个概念,一些服务会以xml的形式返回结果,这个时候就要对XML进行解析,但很多时候,我们对服务提供的XML结构不甚了解,就算了解了,如果服务被修改XML结构被改变,这个时候以前写好的解析XML的方法就会出现紊乱,如何解决这个问题呢?其实标准的服务在提供给用户XML的时候会提供给用户对应的XML描述文件,这就是XSD文件,对此文件进行解析后再利用解析后的XSD文件对XML进行解析,这样即使服务节点变了,后台的代码也能正确解析当前服务返回的XML文件。XSD文件的解析方法如下:

静态变量类:

package test;

public class XMLConstants {

// 默认数据节点,设置为空则认为根目录为默认数据节点
public static final String MESSAGE = "Features";

//xml编码
public static final String ENCODING = "UTF-8";

// xsd默认命名空间,设置为空则没有默认命名空间
public static final String XSD_DEFAULT_NAMESPACE = "xs";

// xsd定义的默认数据节点,设置为空则认为根目录为默认数据节点
public static final String XSD_DEFAULT_DATANODE = "Features";

// xsd复合类型节点
public static final String XSD_COMPLEX_TYPE = "complexType";

// xsd序列节点
public static final String XSD_SEQUENCE = "sequence";

// xsd元素节点
public static final String XSD_ELEMENT = "element";

// xsd注解节点
public static final String XSD_ANNOTATION = "annotation";

// xsd注解文档节点
public static final String XSD_DOCUMENTATION = "documentation";

// xsd简单类型节点
public static final String XSD_SIMPLE_TYPE = "simpleType";

// xsd限制节点
public static final String XSD_RESTRICTION = "restriction";

// xsd name属性
public static final String XSD_ATTRIBUTE_NAME = "name";

// xsd type属性
public static final String XSD_ATTRIBUTE_TYPE = "type";

// xsd base属性
public static final String XSD_ATTRIBUTE_base = "base";

// 用来描述xsd中的unbounded节点信息
public static final String XSD_UNBOUNDED = "[unbounded]";

public static final String XSD_UNBOUNDED_REPLATE = "\\[unbounded\\]";

public static final String XSL_ELEMENT_FOREACH = "for-each";

public static final String XSL_ELEMENT_SELECT = "select";

/** ************* 创建xslt基础变量配置 ******************* */

public static final String STYLESHEET = "stylesheet";

public static final String VERSION = "version";

public static final String VERSIONNUM = "1.0";

public static final String NAMESPACE = "xsl";

public static final String NAMESPACEADDRESS = "http://www.w3.org/1999/XSL/Transform";

public static final String TEMPLATE = "template";

public static final String MATCH = "match";

public static final String APPLYTEMPLATES = "apply-templates";

public static final String VALUEOF = "value-of";

public static final String SELECT = "select";

public static final String XMLENCODING = "UTF-8";

public static final String ROOTSPER = "/";

public static final String DOUBELROOTSPER = "//";

public static final String SPER = ":";

}

XSD节点对象类:

package test;public class XSDNode { // 节点名称 private String name; // 节点XPath private String xPath; // 节点描述 private String annotation; // 节点类型 private String type; // 业务用路径,描述路径中的unbound节点 private String unboundedXpath; private String isUnbounded;public String getName() { return name; } public void setName(String name) { this.name = name; } public String getXPath() { return xPath; } public void setXPath(String path) { xPath = path; } public String getAnnotation() { return annotation; } public void setAnnotation(String annotation) { this.annotation = annotation; } public String getType() { return type; } public void setType(String type) { this.type = type; } public String getUnboundedXpath() { return unboundedXpath; } public void setUnboundedXpath(String unboundedXpath) { this.unboundedXpath = unboundedXpath; }public String getIsUnbounded() {return isUnbounded;}public void setIsUnbounded(String isUnbounded) {this.isUnbounded = isUnbounded;} } 

XSD解析方法类:

package test;import java.util.ArrayList;import java.util.Iterator;import java.util.List;import org.dom4j.Attribute;import org.dom4j.Document;import org.dom4j.Element;import org.dom4j.Node;import org.dom4j.io.SAXReader;public class XSDReader { private List<XSDNode> list = new ArrayList<XSDNode>(); /** * 解析XSD,返回数据节点对象列表 * * @param xsd * @return * @throws Exception */ public List<XSDNode> paserXSD(String xsd) throws Exception { SAXReader saxReader = new SAXReader(); // ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(xsd.getBytes(BaseConstants.XM LENCODING)); Document doc = saxReader.read(xsd); Element element = doc.getRootElement(); String basePath = null;Element dataElement = null;if("".equals(XMLConstants.XSD_DEFAULT_NAMESPACE)){if("".equals(XMLConstants.MESSAGE)){dataElement = element;}else{basePath = "//element[@name=\"" + XMLConstants.MESSAGE + "\"]";dataElement = (Element) element.selectSingleNode(basePath); }}else{basePath = "//" + XMLConstants.XSD_DEFAULT_NAMESPACE + ":element[@name=\"" + XMLConstants.MESSAGE + "\"]"; dataElement = (Element) element.selectSingleNode(basePath); }String elementPath = null;if("".equals(XMLConstants.XSD_DEFAULT_NAMESPACE)){elementPath = "//element";}else{elementPath = "//" + XMLConstants.XSD_DEFAULT_NAMESPACE + ":element"; }paseData(dataElement, "//", elementPath, "//"); return list; } /** * 转换XSD的数据节点,生成XSDNode对象 * * @param element * @param xPath * @param xsdPath * @param unboundedXpath */ public void paseData(Element element, String xPath, String xsdPath, String unboundedXpath) { if(element==null) return;// 获取节点name属性 String nodeName = element.attributeValue("name"); // 组装xml文档中节点的XPath xPath += nodeName; unboundedXpath += nodeName; // 并列多节点限制属性 String maxOccurs = element.attributeValue("maxOccurs"); if (maxOccurs != null && !"1".equals(maxOccurs) && !("//" + XMLConstants.MESSAGE + "").equals(xPath)) {// 节点可以有多个 unboundedXpath += XMLConstants.XSD_UNBOUNDED; } // 组装下一个element元素的XPath String currentXsdPath = xsdPath + "[@name=\"" + nodeName + "\"]" + "/" + XMLConstants.XSD_DEFAULT_NAMESPACE + ":complexType/" + XMLConstants.XSD_DEFAULT_NAMESPACE + ":sequence/" + XMLConstants.XSD_DEFAULT_NAMESPACE + ":element"; // 查找该节点下所有的element元素 List<Node> elementNodes = element.selectNodes(currentXsdPath); if (elementNodes != null && elementNodes.size() > 0) {// 如果下面还有element,说明不是叶子Iterator<Node> nodes = elementNodes.iterator(); while (nodes.hasNext()) { if (!xPath.endsWith("/")) { xPath += "/"; unboundedXpath += "/"; } Element ele = (Element) nodes.next(); paseData(ele, xPath, currentXsdPath, unboundedXpath); } } else { // 该element为叶子 XSDNode xsdNode = new XSDNode(); // 获取注释节点 String annotation = ""; Node annotationNode = element .selectSingleNode(xsdPath + "[@name=\"" + nodeName + "\"]/" + XMLConstants.XSD_DEFAULT_NAMESPACE + ":annotation/" + XMLConstants.XSD_DEFAULT_NAMESPACE + ":documentation"); if (annotationNode != null) annotation = annotationNode.getText(); // 获取节点类型属性 String nodeType = ""; Attribute type = element.attribute("type"); if (type != null){ nodeType = type.getText(); }else { String spath = xsdPath + "[@name=\"" + nodeName + "\"]/" + XMLConstants.XSD_DEFAULT_NAMESPACE + ":simpleType/" + XMLConstants.XSD_DEFAULT_NAMESPACE + ":restriction"; Element typeNode = (Element) element.selectSingleNode(spath); if (typeNode != null) { Attribute base = typeNode.attribute("base"); if (base != null) nodeType = base.getText(); } } xsdNode.setName(nodeName); xsdNode.setXPath(xPath); xsdNode.setAnnotation(annotation); xsdNode.setType(nodeType); xsdNode.setUnboundedXpath(unboundedXpath); list.add(xsdNode); } } public static void main(String[] args) { try { String realPath = XSDReader.class.getResource("/").getPath();XSDReader xsdReader = new XSDReader();List<XSDNode> nodes = xsdReader.paserXSD(realPath+"/feature.xsd");for (XSDNode node : nodes) { System.out.println(node.getUnboundedXpath()); } } catch (Exception ex){ ex.printStackTrace(); } } } 

示例的XSD文件:

<?xml version="1.0" encoding="UTF-8"?><xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:gml="http://www.opengis.net/gml" elementFormDefault="qualified" attributeFormDefault="unqualified"><xs:element name="Features"><xs:annotation><xs:documentation>QueryChange</xs:documentation></xs:annotation><xs:complexType><xs:sequence><xs:element name="networkName"/><xs:element name="FeatureCollection" maxOccurs="unbounded"><xs:complexType><xs:sequence><xs:element name="featureMember" maxOccurs="unbounded"><xs:complexType><xs:sequence><xs:element name="Road"><xs:complexType><xs:sequence><xs:element name="lineId"/><xs:element name="lineName"/><xs:element name="passNodeIds"/><xs:element name="passNodeNames"/><xs:element name="passNodeCoordinates"/><xs:element name="geometry"><xs:complexType><xs:sequence><xs:element ref="gml:LineString"/></xs:sequence></xs:complexType></xs:element></xs:sequence></xs:complexType></xs:element></xs:sequence></xs:complexType></xs:element></xs:sequence></xs:complexType></xs:element></xs:sequence></xs:complexType></xs:element></xs:schema>