XML 简单介绍
在介绍Java中解析 XML 的方法之前前先来介绍下 XML,在我之前学习 HTML 的时候,就听当时的老师介绍过 XML ,它和 HTML 一样是一种标记语言,不同的是它的语法更加灵活,HTML 中的标签是预定义的,而 XML 中的标签则由创建者自己定义,并且每个 XML 标签都是成对出现的 ,通常需要在文件的首行写上 XML 的一个文档头作为开始 其中可以包括版本,编码方式… XML 文档 和HTMl各种节点,节点也可以有属性,但其每一个属性都必须有属性值。
下面是一个 XML 文档内容,并将作为解析XML文档用例。
<!-- XML 中的注释 -->
<!-- 文档头 -->
<?xml version="1.0" encoding="UTF-8"?>
<!-- 根节点 -->
<struts>
<!-- 子节点、文本及属性 -->
<action name="login" class="com.tennyson.xml.LoginAction">
<result name="success">/jsp/homepage.jsp</result>
<result name="fail">/jsp/showLogin.jsp</result>
</action>
<action name="logout" class="com.tennyson.xml.LogoutAction">
<result name = "success">/jsp/welcome.jsp</result>
<result name = "error">/jsp/error.jsp</result>
</action>
</struts>
Java 中解析 XML 的方法
要在 Java 中使用 XML ,首先要解析它,Java 中有四种解析 XML 文档的方法,Java自身提供了两种解析XML 文档的方法:DOM 解析器和 SAX 解析器,也就是说在使用这两种方法时不用再引入jar包二直接使用。另外两种是 JDOM 和 DOM4J, 下面将会分别介绍。
DOM XML
DOM 解析器读入的 XML 文档解析后保留其树形结构,可以获取文档树中的上下文结构、信息,使用也比较简单。
DOM解析器把整个XML文档装载到内存,并解析成一个Document对象。
- 优点:元素与元素之间保留结构关系,故可以进行增删改查操作。
- 缺点:XML文档过大,可能出现内存溢出显现。
要读入一个 XML 文档需要 DocumentBuilder 对象,可以从 DocumentBuilderFactory 中获得该对象,之后即可使用 DocumentBuilder 对象读入文档。
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
// 获取 DocumentBuilder 对象
DocumentBuilder builder = factory.newDocumentBuilder();
// 读入 XML 文件,获得一个 Document 对象
Document document = builder.parse("struts.xml");
Document 对象保留了文档树的结构,之后的操作与解析器无关。
可以通过 getDocumentElement() 获得文档的根节点,之后通过 getChildNodes() 获取根节点下的子节点,该方法将会返回一个 NodeList 集合
...
// 获取文档根节点
Element struts = document.getDocumentElement();
// 枚举所有子节点
NodeList strutsNodeList = struts.getChildNodes();
for (int i = 0; i < strutsNodeList.getLength(); i++) {
Node childNode = strutsNodeList.item(i);
// 只获取子元素,而忽略空白字符
if (childNode instanceof Element) {
Element action = (Element) childNode;
}
}
如果知道了获取的子节点中只有一个文本节点,则可以使用getFirstChild()获取到,并通过getData()获取到节点字符串,对getData()得到的返回值调用trim()方法可以将实际数据前后的空白字符删除掉。
同样可以使用getLastChild()方法得到最后一个子元素,使用getNextSibling()得到下一个兄弟节点
可以调用getAttributes()方法获取节点的所有属性,使用getNodeName()获取属性名getNodeValue()获取属性值,如果知道属性名可以使用getAttribute(“attributeName”)获取该属性值。
...
// 根据属性名获取属性
String attributeValue = action.getAttribute("name");
SAX
尽管使用 DOM 解析XML 文档操作简单,并且易于对 DOM 树增加或删除节点,但使用 DOM 解析器需要处理整个文档,当文档过大,或者你只需要处理文档中某个节点而不关注文档上下文时,使用 DOM 就显得效率低下,且占用内存资源,这是可以使用 SAX 解析器,SAX 解析器解析 XML 文档采用了基于事件的模型,在解析时触发一系列事件。
SAX相较于速度更快,更有效。它逐行扫描文档,一边扫描一边解析。并以事件驱动的方式进行具体解析,每执行一行,都将触发对应的事件。
- 优点:处理速度快,可以处理大文件
- 缺点:只能读,逐行后将释放资源
DOM4J
已解析一下XML文件为例,展示DOM4J的使用
<?xml version = “1.0” encoding=”UTF-8”?>
<products>
<product id = “p001”>
<name>华为X80</name>
<color>白</color>
<price>2800</price>
</product>
<product id = “p002”>
<name>华为X88</name>
<color>黑</color>
<price>2900</price>
</product>
</products>
dom4j解析代码:
public class Test {
public static void main(String[] args) throws Exception {
List<Product> products = anaylysisXML("product.xml");
for (Product product : products) {
System.out.println(product);
}
}
@SuppressWarnings("unchecked")
public static List<Product> anaylysisXML(String fileName) throws Exception {
List<Product> list = new ArrayList<Product>();
// 使用dom4j解析XML文件,首先要获取SAXReader对象
SAXReader reader = new SAXReader();
// 加载XML文件的DOM树
Document doc = reader.read(fileName);
// 获取DOM树的根节点
Element root = doc.getRootElement();
// 获取根节点下的所有子节点
List<Element> elements = root.elements();
// 遍历节点
for (Element element : elements) {
Product product = new Product();
// 根据属性名获取属性值
Attribute id = element.attribute("id");
product.setId(id.getValue());
// 根据子节点名获取当前节点下子节点的文本值
String name = element.elementText("name");
String color = element.elementText("color");
Double price = Double.parseDouble(element.elementText("price"));
product.setName(name);
product.setColor(color);
product.setPrice(price);
/*
* // 获取当前节点下的所有子节点
* List<Element> elemList = element.elements();
*
* // 遍历节点
* for (Element node : elemList) {
*
* // 获取当前节点的节点名
* String nodeName = node.getName();
* // 获取当前节点的文本值(文本节点)
* String value = node.getText();
* if ("name".equals(nodeName)) {
* product.setName(value);
* }
*
* if ("color".equals(nodeName)) {
* product.setColor(value);
* }
*
* if ("price".equals(nodeName)) {
* product.setPrice(Double.parseDouble(value));
* }
*
*
* }
*/
list.add(product);
}
return list;
}
}