Java 如何操纵 XML
XML 简介
XML 是一种可扩展标记语言,最主要的用处就是用来做为程序的配置文件了。当然,它还可以作为数据源来存储数据,作为传输数据的媒体等。它的语法非常严格,一个空格都不能多,不同于 HTML。
XML 的约束模式
一个 XML 文件不仅要在语法上符合标准,还要在内容上是否符合标准才是一个真正有用的 XML 文件。
这些判断工作就是由 XML 解析器来完成的,解析器分为非校验类解析器和校验类解析器。如 IE 就是非校验类解析器,只能够用来检测 XML 文件的格式是否符合标准,而 XML DTD 和 XML schema 就是一种能够检验内容的校验类解析器。(XML schema 是对 XML DTD 的一种改进)
那什么是符合语法标准而内容却不对呢?举个小例子
<?xml version="1.0" encoding="gbk" standalone="no"?>
<?xml-stylesheet type="text/css" href="book.css" ?>
<bookstore>
<book>
<bookname>Java 就业培训教程</bookname>
<author>张孝祥</author>
<price>39元</price>
<price>28元</price>
</book>
</bookstore>
这里书的价格有两个,从格式上来说是对的,但在内容上就不符合规范了,到底是用第一个还是第二个作为书的价格呢?现实中情况更为复杂,所以需要一种能够判断XML 文件是否符合标准的解析器。
上面提到的 XML DTD 和 XML schema 就能够提供这样的功能,它实现定义了规范,所有使用这种规范的 XML 文件就必须遵循它的规则。
<!ELEMENT bookstore(book+)>
<!ELEMENT book(bookname,author,price)>
<!ELEMENT bookname (#PCDATA)>
<!ELEMENT author (#PCDATA)>
<!ELEMENT price (#PCDATA)>
上述就是一个 XML DTD 的规范,这就规定了 book 里面不能再有未定义的标签了。
但是用的更多的还是 XML schema ,它的好处太多了。对于程序员来说最直接的好处就是它采用 XML 的语法,非常容易上手。
Java 中如何操纵 XML 文件呢?
说白了就是如何用 Java 对 XML 文件进行增删改查啦,Java 提供了很多种方式来解析 XML 文件。这里只讲解 DOM 解析,展示下 DOM 的优缺点:
操作上简单,其处理方式是将 XML 整个作为类似树结构的方式读入内存中以便操作及解析,因此支持应用程序对 XML 数据的内容和结构进行修改,但是同时由于其需要在处理开始时将整个 XML 文件读入到内存中去进行分析,因此其在解析大数据量的 XML 文件时会遇到类似于内存泄露以及程序崩溃的风险,请对这点多加注意。
适用于小型 XML 文件解析、需要全解析或者大部分解析 XML、需要修改 XML 树内容以生成自己的对象模型。
先展示下导入的包:
import java.io.IOException;
import java.util.concurrent.SynchronousQueue;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
再展示下 book.xml 文件内容:
<?xml version="1.0" encoding="UTF-8" standalone="no"?><books>
<book id="001">
<title>Harry Potter</title>
<author>J K. Rowling</author>
</book>
<book id="002">
<title>Learning XML</title>
<author>Erik T. Ray</author>
</book>
<book id="004">
<title>Java Sucessfull</title>
<author>keqi</author>
</book>
</books>
- 查询
try {
//第一步:先得到文档建造工厂类
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
//第二步:通过文档建造工厂类得到文档建造实例
DocumentBuilder db = dbFactory.newDocumentBuilder();
//第三步:通过给文档建造实例指定文档来得到文档对象
Document document = db.parse("book.xml");
//第四步:得到名为 book 的结点集合
NodeList nodeList = document.getElementsByTagName("book");
//遍历结点,并把每个节点的相关信息输出
for(int i = 0;i<nodeList.getLength();i++){
Element node = (Element) nodeList.item(i);
System.out.println("title:" + node.getElementsByTagName("title").item(0).getFirstChild().getNodeValue());
System.out.println("author:" + node.getElementsByTagName("author").item(0).getFirstChild().getNodeValue());
}
} catch (ParserConfigurationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SAXException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}*/
- 增加
//第一步:先得到文档建造工厂类
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
//第二步:通过文档建造工厂类得到文档建造实例
DocumentBuilder db = dbFactory.newDocumentBuilder();
//第三步:通过给文档建造实例指定文档来得到文档对象
Document document = db.parse("book.xml");
NodeList nList = document.getElementsByTagName("books");
Element books = (Element) nList.item(0);//得到根节点
Element book = document.createElement("book");//创建 book 节点
book.setAttribute("id", "003");//设置属性
//创建title节点,设置值,并添加到book节点中
Element title = document.createElement("title");
title.appendChild(document.createTextNode("Java Sucessfull"));
book.appendChild(title);
//创建author节点,设置值,并添加到book节点中
Element author = document.createElement("author");
author.appendChild(document.createTextNode("keqi"));
book.appendChild(author);
books.appendChild(book);//将book节点添加到books中
//将 document 对象写回到文件中去
Transformer transformer = TransformerFactory.newInstance().newTransformer();
transformer.transform(new DOMSource(document),new StreamResult("book.xml"));
- 删除
//第一步:先得到文档建造工厂类
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
//第二步:通过文档建造工厂类得到文档建造实例
DocumentBuilder db = dbFactory.newDocumentBuilder();
//第三步:通过给文档建造实例指定文档来得到文档对象
Document document = db.parse("book.xml");
NodeList nodeList = document.getElementsByTagName("book");
for(int i =0;i<nodeList.getLength();i++) {
Element element = (Element) nodeList.item(i);
if(element.getAttribute("id").equals("003")) {
element.getParentNode().removeChild(element);//删除此节点
}
}
- 修改
//第一步:先得到文档建造工厂类
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
//第二步:通过文档建造工厂类得到文档建造实例
DocumentBuilder db = dbFactory.newDocumentBuilder();
//第三步:通过给文档建造实例指定文档来得到文档对象
Document document = db.parse("book.xml");
NodeList nodeList = document.getElementsByTagName("book");
for(int i =0;i<nodeList.getLength();i++) {
Element element = (Element) nodeList.item(i);
if(element.getAttribute("id").equals("003")) {
NodeList list1 = element.getChildNodes();
for(int j=0;j<list1.getLength();j++) {
if(list1.item(j).getNodeName().equals("title")){
list1.item(j).setTextContent("人生");
}
if(list1.item(j).getNodeName().equals("author"){
list1.item(j).setTextContent("路遥");
}
}
}
}
Transformer transformer = TransformerFactory.newInstance().newTransformer();
transformer.transform(new DOMSource(document),new StreamResult("book.xml"));
总结一下,就是首先得到 document 对象,然后通过对它的结点进行一系列操作实现增删改改查的目的,最后再将此 document 对象写回到 XML 文件中去。