分享一个 org.w3c.dom XML 封装

之前解析 XML 大多在网页中完成。如果切换到 Java 中可能是 Dom4j 或者其他。不过对于一些小 Case,JDK 自带的 Dom 就可以了,而且可以省掉第三方 JAR,何乐不为呢?于是我参照了一位大侠写的,稍微重构一下,分享给大家。

测试用例:http://git.oschina.net/sp42/ajaxjs/blob/master/java/src/test/com/ajaxjs/test/util/TestXML.java

import static org.junit.Assert.*;

import java.util.List;

import org.junit.Before;
import org.junit.Test;

import com.ajaxjs.util.XML_Wrapper;

public class TestXML {
	XML_Wrapper root;
	String saveTo;
	
	@Before
	public void setUp() {
		root = XML_Wrapper.getRoot("d:/temp/test.xml");
		saveTo = "d:/temp/test2.xml";
	}

	@Test
	public void 解析xml() {
		List<XML_Wrapper> pList = root.getChildrenElement("property");

		for (XML_Wrapper d : pList) {
			System.out.println(
					d.child("name").text() + ", " + d.child("value").text() + ", " + d.child("description").text());
			assertNotNull(d);
		}
	}

	@Test
	public void 修改xml() {
		List<XML_Wrapper> pList = root.getChildrenElement("property");

		XML_Wrapper d = pList.get(0);
		XML_Wrapper nameDom = d.child("name");
		nameDom.setAttribute("a", "2");
		nameDom.setAttribute("b", "3");
		nameDom.text("测试呵呵");

		assertNotNull(nameDom);
		d.child("description").text("添加描述……");

		root.write(saveTo);
	}

	@Test
	public void 新建xml() {
		XML_Wrapper root = XML_Wrapper.newDom("configuration");

		XML_Wrapper propertyDom = root.addElement("property");
		propertyDom.addElement("name", "名称");
		propertyDom.addElement("value", "值");
		XML_Wrapper dDom = propertyDom.addElement("description", "描述");
		dDom.setAttribute("a", "2");

		root.write(saveTo);
	}
}

测试 XML

<?xml version="1.0"?>
<configuration>
	<property>
	  <name a="1">host</name>
	  <value>http://192.168.3.249</value>
	  <description>系统主机地址</description>
	</property>

	<property>
	  <name>login</name>
	  <value>/page/Default.jsp</value>
	  <description>登陆页面</description>
	</property>
</configuration>

完整源码 http://git.oschina.net/sp42/ajaxjs/blob/master/java/src/main/com/ajaxjs/util/XML_Wrapper.java:

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.xml.XMLConstants;
import javax.xml.namespace.NamespaceContext;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import com.ajaxjs.Constant;

/**
 * DOM 操控 XML
 */
public class XML_Wrapper {
	private Element element;

	/**
	 * 传入一个元素
	 * 
	 * @param element
	 *            元素
	 */
	private XML_Wrapper(Element element) {
		this.element = element;
	}

	/**
	 * 返回元素
	 * 
	 * @return 元素
	 */ 
	public Element getDomElement() {
		return element;
	}

	/**
	 * 设置属性
	 * 
	 * @param name
	 * @param value
	 */
	public void setAttribute(String name, String value) {
		element.setAttribute(name, value);
	}

	/**
	 * 设置节点文本值
	 * 
	 * @param value
	 *            节点文本值
	 */
	public void text(String value) {
		Node textNode = element.getFirstChild();
		textNode.setNodeValue(value);
	}

	/**
	 * 获取节点文本值
	 * 
	 * @return 节点文本值
	 */
	public String text() {
		Node textNode = element.getFirstChild();
		return textNode.getNodeValue();
	}

	/**
	 * 添加子节点
	 * 
	 * @param name
	 *            子节点 tag
	 * @return 子节点 XML_Wrapper
	 */
	public XML_Wrapper addElement(String name) {
		Element element = this.element.getOwnerDocument().createElement(name.trim());
		this.element.appendChild(element);

		return new XML_Wrapper(element);
	}

	/**
	 * 添加子节点,并设置文本
	 * 
	 * @param name
	 *            子节点 tag
	 * @param value
	 *            文本
	 * @return 子节点 XML_Wrapper
	 */
	public XML_Wrapper addElement(String name, String value) {
		XML_Wrapper child = addElement(name);
		child.getDomElement().appendChild(element.getOwnerDocument().createTextNode(value));

		return child;
	}

	/**
	 * 返回子节点列表
	 * 
	 * @param name
	 *            子节点 tag
	 * @return
	 */
	public NodeList getChildren(String name) {
		NodeList nodeList = element.getElementsByTagName(name);
		if ((nodeList == null) || (nodeList.getLength() < 1)) {
			return null;
		}
		return nodeList;
	}

	/**
	 * 是否某个子节点
	 * 
	 * @param name
	 *            子节点 tag
	 * @return
	 */
	public boolean hasChild(String name) {
		return getChildren(name) != null;
	}

	/**
	 * 返回第一个子节点
	 * 
	 * @param name
	 *            子节点 tag
	 * @return
	 */
	public XML_Wrapper child(String name) {
		return getFirstChild(name);
	}

	/**
	 * 返回第一个子节点
	 * 
	 * @param name
	 *            子节点 tag
	 * @return
	 */
	public XML_Wrapper getFirstChild(String name) {
		if (hasChild(name)) {
			Node node = getChildren(name).item(0);
			return new XML_Wrapper((Element) node);
		}
		return null;
	}

	/**
	 * 获取子节点,忽略文本节点
	 * 
	 * @param name
	 *            子节点 tag
	 * @return
	 */
	public List<XML_Wrapper> getChildrenElement(String name) {
		NodeList nodeList = getChildren(name);
		if (nodeList == null)
			return null;

		List<XML_Wrapper> list = new ArrayList<>();

		for (int i = 0; i < nodeList.getLength(); i++) {
			Node node = nodeList.item(i);
			if (node.getNodeType() == Node.ELEMENT_NODE) {
				Element e = (Element) node;
				list.add(new XML_Wrapper(e));
			}
		}

		return list;
	}

	/**
	 * 打印子节点
	 */
	public void printChild() {
		NodeList nodeList = element.getChildNodes();
		for (int i = 0; i < nodeList.getLength(); i++) {
			Node node = nodeList.item(i);
			System.out.println(
					"节点名: " + node.getNodeName() + ", 节点值: " + node.getNodeValue() + ", 节点类型: " + node.getNodeType());
		}
	}

	/**
	 * 移除子节点
	 * 
	 * @param name
	 *            子节点 tag
	 */
	public void removeChild(String name) {
		NodeList nodeList = getChildren(name);
		if (nodeList == null) {
			return;
		}
		for (int i = 0; i < nodeList.getLength(); i++) {
			element.removeChild(nodeList.item(i));
		}
	}

	public void write(OutputStream os) {
		write(os, Constant.encoding_UTF8);
	}

	/**
	 * 
	 * @param os
	 * @param encoding
	 */
	public void write(OutputStream os, String encoding) {
		TransformerFactory tFactory = TransformerFactory.newInstance();
		tFactory.setAttribute("indent-number", 2);

		try {
			Transformer transformer = tFactory.newTransformer();
			transformer.setOutputProperty(OutputKeys.ENCODING, encoding);
			transformer.setOutputProperty(OutputKeys.INDENT, "yes");
			transformer.setOutputProperty(OutputKeys.STANDALONE, "yes");
			transformer.transform(new DOMSource(element.getOwnerDocument()), new StreamResult(new OutputStreamWriter(os)));
		} catch (TransformerFactoryConfigurationError | TransformerException e) {
			e.printStackTrace();
		}
	}

	public void write(String xmlFile) {
		write(xmlFile, Constant.encoding_UTF8);
	}

	public void write(String xmlFile, String encoding) {
		try (OutputStream os = new FileOutputStream(xmlFile);) {
			write(os, encoding);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 创建一份新的 XML,包含一个新的节点(根节点)
	 * 
	 * @param rootName
	 *            根节点名称
	 * @return
	 */
	public static XML_Wrapper newDom(String rootName) {
		Document doc = getDocBuilder().newDocument();
		doc.setXmlStandalone(true);

		// getDocBuilder();
		Element root = doc.createElement(rootName);
		doc.appendChild(root);

		return new XML_Wrapper(root);
	}

	private static DocumentBuilder getDocBuilder() {
		try {
			return DocumentBuilderFactory.newInstance().newDocumentBuilder();
		} catch (ParserConfigurationException e) {
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * 送入流创建 XML 文档
	 * 
	 * @param is
	 *            流,并不会自动关闭的
	 * @return
	 */
	public static Element getRoot(InputStream is) {
		Document doc = null;

		try {
			doc = getDocBuilder().parse(is);
			return doc.getDocumentElement();
		} catch (SAXException | IOException e) {
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * 
	 * @param xmlFile
	 * @return
	 */
	public static XML_Wrapper getRoot(String xmlFile) {
		try (InputStream is = new FileInputStream(xmlFile);) {
			return new XML_Wrapper(getRoot(is));
		} catch (IOException e) {
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * XPath
	 * 
	 * @param xmlFile
	 *            XML 文件路径
	 * @param encoding
	 *            XML 文件编码
	 * @param expression
	 *            XPath 表达式
	 * @param namespaceMap
	 *            命名空间
	 * @return
	 */
	public static String xpath(String xmlFile, String encoding, String expression, final Map<String, String> namespaceMap) {
		XPath xpath = XPathFactory.newInstance().newXPath();
		
		if (namespaceMap != null) {
			xpath.setNamespaceContext(new NamespaceContext() {
				@Override
				public String getNamespaceURI(String prefix) {
					if (prefix == null)
						throw new NullPointerException("Null prefix");
					else if ("xml".equals(prefix))
						return XMLConstants.XML_NS_URI;
					else if (namespaceMap.containsKey(prefix))
						return namespaceMap.get(prefix);
					
					return XMLConstants.NULL_NS_URI;
				}
				
				@Override
				public String getPrefix(String namespaceURI) {
					throw new UnsupportedOperationException();
				}
				
				@Override
				public Iterator<?> getPrefixes(String namespaceURI) {
					throw new UnsupportedOperationException();
				}
			});
		}
		
		String value = null;
		
		try (
			FileInputStream is = new FileInputStream(xmlFile);
			InputStreamReader isr = new InputStreamReader(is, encoding);
		) {
			InputSource source = new InputSource(isr);
			
			try {
				value = xpath.evaluate(expression, source);
			} catch (XPathExpressionException e) {
				e.printStackTrace();
			}
		} catch (IOException e) {
			e.printStackTrace();
		}

		return value;
	}
}

你可能感兴趣的:(分享一个 org.w3c.dom XML 封装)