使用dom4j解析XSD文件

在比较大的项目中,我们有时会用到服务这个概念,一些服务会以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>
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
使用Javadom4j根据XSD文件,调整错误节点到正确的位置,需要进行以下步骤: 1. 解析XSD文件,获取元素的层级关系。 ```java SAXReader reader = new SAXReader(); Document xsdDoc = reader.read(new File("schema.xsd")); Element root = xsdDoc.getRootElement(); Map<String, Element> elementMap = new HashMap<>(); getElementMap(elementMap, root); ``` 其中,`getElementMap`方法可以递归获取所有的元素节点,并将其存储在一个`Map`中,方便后续操作。 2. 解析XML文件,获取错误节点。 ```java Document xmlDoc = reader.read(new File("data.xml")); Element errorNode = (Element)xmlDoc.selectSingleNode("//error"); ``` 这里假设错误节点为`error`,可以通过XPath表达式获取该节点。 3. 根据错误节点的路径,获取其应该插入的父节点。 ```java String errorPath = errorNode.getUniquePath(); String parentPath = errorPath.substring(0, errorPath.lastIndexOf("/")); Element parentNode = elementMap.get(parentPath); ``` 这里,通过`getUniquePath`方法获取错误节点的路径,然后根据路径获取其应该插入的父节点。 4. 将错误节点从原位置删除,并插入到正确的位置。 ```java Element errorParent = errorNode.getParent(); errorParent.remove(errorNode); parentNode.add(errorNode); ``` 这里,先从原位置删除错误节点,然后将其插入到正确的位置。 完整代码示例: ```java import java.io.File; import java.util.HashMap; import java.util.List; import java.util.Map; import org.dom4j.Document; import org.dom4j.Element; import org.dom4j.io.SAXReader; public class XsdAdjuster { public static void main(String[] args) throws Exception { SAXReader reader = new SAXReader(); Document xsdDoc = reader.read(new File("schema.xsd")); Element root = xsdDoc.getRootElement(); Map<String, Element> elementMap = new HashMap<>(); getElementMap(elementMap, root); Document xmlDoc = reader.read(new File("data.xml")); Element errorNode = (Element)xmlDoc.selectSingleNode("//error"); String errorPath = errorNode.getUniquePath(); String parentPath = errorPath.substring(0, errorPath.lastIndexOf("/")); Element parentNode = elementMap.get(parentPath); Element errorParent = errorNode.getParent(); errorParent.remove(errorNode); parentNode.add(errorNode); System.out.println(xmlDoc.asXML()); } private static void getElementMap(Map<String, Element> elementMap, Element element) { elementMap.put(element.getUniquePath(), element); List<Element> elements = element.elements(); for (Element child : elements) { getElementMap(elementMap, child); } } } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值