之前解析 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 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 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
host
http://192.168.3.249
系统主机地址
login
/page/Default.jsp
登陆页面
完整源码 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 getChildrenElement(String name) {
NodeList nodeList = getChildren(name);
if (nodeList == null)
return null;
List 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 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;
}
}