1、DOM Document Object Model文档对象模型。W3C推荐的解析方式。(一系列的接口和抽象类)
Jaxp解析XML文档(dom解析方法,它是将整个xml文档加载到内存,对于xml文档的curd操作方便)
属于JDK的一部分。由以下包构成
org.w3c.dom:提供DOm方式解析的接口或抽象类
org.xml.sax:提供SAX方式解析的接口或抽象类
javax.xml:提供了解析XML的标准实现
Package com.test.japx
import java.io.File;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
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;
/**
* jaxp解析xml文档
* @author yxx
*
*/
public class DomDemo {
public static void main(String[] args)throws Exception {
getAttr();
}
// 1、得到某个具体的节点内容
public static void getText() throws Exception{
Document document = getDocument();
NodeList list = document.getElementsByTagName("书架");
Node no = list.item(0);
System.out.println(no.getTextContent());
}
// 2、遍历所有元素节点
public static void list(Node node){
if(node.getNodeType()==Node.ELEMENT_NODE){
System.out.println(node.getNodeName());
}
NodeList nl = node.getChildNodes();
for(int i=0;i<nl.getLength();i++){
list(nl.item(i));
}
}
// 4、向指定元素节点中增加子元素节点
public static void setNode() throws Exception{
Document document = getDocument();
Element d = (Element) document.getElementsByTagName("书").item(0);
Element newEl = document.createElement("编号");
newEl.setTextContent("sss");
d.appendChild(newEl);
write(document);
}
// 6、删除指定元素节点
public static void delNode() throws Exception{
Document document = getDocument();
Node node = document.getElementsByTagName("书名").item(0);
//System.out.println(node.getNodeName());
System.out.println(node.getParentNode());
node.getParentNode().removeChild(node);
write(document);
}
// 7、操作XML文件属性
public static void getAttr()throws Exception{
Document document = getDocument();
Node n = document.getElementsByTagName("书名").item(0);
Element e = (Element)n;
System.out.println(e.getAttribute("name"));
}
/**
*
* 返回document对象(公共方法,得到document对象)
* @return
* @throws Exception
*/
public static Document getDocument() throws Exception{
DocumentBuilderFactory factoy = DocumentBuilderFactory.newInstance();
DocumentBuilder bui = factoy.newDocumentBuilder();
Document document = bui.parse("src/book.xml");
return document;
}
/**
* 向xml文件中写入数据(公共方法,将修改的内容写入到xml文件中)
* @param node
* @throws Exception
*/
public static void write(Document node) throws Exception{
TransformerFactory factory = TransformerFactory.newInstance();
Transformer tf = factory.newTransformer();
tf.transform(new DOMSource(node),new StreamResult(new File("src/book.xml")) );
}
}
2、SAX:Simple APIfor XML。开源社区。非官方标准。(此方式不会讲整个xml文档整个加载到内存中,而只是边读取边操作,适合xml的读取,不适合对xml文档操作)
1. Java Sax解析是按照xml文件的顺序一步一步的来解析,在解析xml文件之前,我们要先了解xml文件的节点的种类,一种是ElementNode,一种是TextNode。
<?xml version="1.0" encoding="UTF-8"?>
<books>
<book id="12">
<name>thinking in java</name>
<price>85.5</price>
</book>
<book id="15">
<name>Spring in Action</name>
<price>39.0</price>
</book>
</books>
其中,像<books>、<book>这种节点就属于ElementNode,而thinking in java、85.5这种就属于TextNode。
下面结合一张图来详细讲解Sax解析。
xml文件被Sax解析器载入,由于Sax解析是按照xml文件的顺序来解析,当读入<?xml.....>时,会调用startDocument()方法,当读入<books>的时候,由于它是个ElementNode,所以会调用startElement(String uri, String localName, String qName, Attributes attributes) 方法,其中第二个参数就是节点的名称,注意:由于有些环境不一样,有时候第二个参数有可能为空,所以可以使用第三个参数,因此在解析前,先调用一下看哪个参数能用,第4个参数是这个节点的属性。这里我们不需要这个节点,所以从<book>这个节点开始,也就是图中1的位置,当读入时,调用startElement(....)方法,由于只有一个属性id,可以通过attributes.getValue(0)来得到,然后在图中标明2的地方会调用characters(char[] ch, int start, int length)方法,不要以为那里是空白,Sax解析器可不那么认为,Sax解析器会把它认为是一个TextNode。但是这个空白不是我们想要的数据,我们是想要<name>节点下的文本信息。这就要定义一个记录当上一节点的名称的TAG,在characters(.....)方法中,判断当前节点是不是name,是再取值,才能取到thinking in java。
来看一个具体的实例
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
/**
* 打印第2本书的作者的主体内容
* @author yxx
*
*/
public class SaxDemo2 {
public static void main(String[] args)throws Exception {
SAXParser saxParser = SAXParserFactory.newInstance().newSAXParser();
XMLReader reader = saxParser.getXMLReader();
reader.setContentHandler(new MyHandlers());
reader.parse("src/book.xml");
}
}
class MyHandlers extends DefaultHandler{
//当前元素是否是作者元素 ,默认为false
boolean isAuthor = false;
//当前的元素是否是第二个,默认为第一个
int authorIndex = 0;
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
System.out.println(qName+"-----------------");
if("作者".equals(qName)){
isAuthor = true;
}
}
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
//当当前的元素为“作者”且是第二个的时候就打印里面的内容
if(authorIndex==1&&isAuthor)
System.out.println(new String(ch,start,length));
}
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
//当当前结束的标签为作者,就将元素authorIndex加1
if("作者".equals(qName)){
isAuthor = false;
authorIndex++;
}
}
}
2、Dom4j解析方法,集合了dom和sax两种解析方式的优点,在对xml读取的时候不会将整个xml文档加载到内存。三个xml文档共用
import java.io.FileOutputStream;
import java.util.List;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
import org.junit.Assert;
import org.junit.Test;
/**
* dom4j练习
* 采用junit测试
* 1.junit测试的方法必须为public的,
* 2.junit测试的方法不能有返回值,
* 3.junit测试方法不能有参数
* @author yxx
*
*/
public class Dom4jDemo1 {
// 1、得到某个具体的节点内容:第1本书的作者
@Test
public void test1() throws Exception{
SAXReader reader = new SAXReader();
Document document = reader.read("src/book.xml");
Element el =document.getRootElement();
Element el1 = el.element("书");
Element el2 = el1.element("作者");
String name = el2.getText();
Assert.assertEquals("张三", name);
}
// 2、遍历所有元素节点
@Test()
public void test2() throws Exception{
SAXReader reader = new SAXReader();
Document document = reader.read("src/book.xml");
Element el =document.getRootElement();
treeWalk(el);
}
public void treeWalk(Element root){
//得到根节点的所有孩子个数
int count = root.nodeCount();
//遍历孩子个数
for(int i=0;i<count;i++){
Node node = root.node(i);
//如果node为Element元素,就将其转换为Element然后自调
if(node.getNodeType()==Node.ELEMENT_NODE)
treeWalk((Element)node);
}
}
// 3、修改某个元素节点的主体内容:第2本书售价改为5.1
@Test
public void test3() throws Exception{
SAXReader reader = new SAXReader();
Document document = reader.read("src/book.xml");
Element el =document.getRootElement();
//得到所有孩子节点,但不包括孙子节点
List<Element> l = el.elements();
Element e = l.get(1);
Element e1 = e.element("售价");
e1.setText("5.1");
OutputFormat format = new OutputFormat();
//用字节流 默认为UTF-8
format.setEncoding("UTF-8");
XMLWriter writer = new XMLWriter(new FileOutputStream("src/book.xml"),format.createPrettyPrint());
writer.write(document);
writer.close();
}
// 4、向指定元素节点中增加子元素节点:第1本书增加内部价
@Test
public void test4() throws Exception{
SAXReader reader = new SAXReader();
Document document = reader.read("src/book.xml");
Element el =document.getRootElement();
Element e = el.element("书");
e.addElement("内部价").setText("100.00");
OutputFormat format = new OutputFormat();
//用字节流 默认为UTF-8
XMLWriter wrier = new XMLWriter(new FileOutputStream("src/book.xml"),format.createPrettyPrint());
wrier.write(document);
wrier.close();
}
// 5、向指定元素节点上增加同级元素节点:第1个售价前面加上批发价
@Test
public void test5() throws Exception{
SAXReader reader = new SAXReader();
Document document = reader.read("src/book.xml");
Element el =document.getRootElement();
//通过DocumentHelper来创建一个元素
Element price = DocumentHelper.createElement("批发价");
price.setText("100");
List<Element> e = el.element("书").elements();
e.add(2,price);
OutputFormat format = new OutputFormat();
//用字节流 默认为UTF-8
XMLWriter wrier = new XMLWriter(new FileOutputStream("src/book.xml"),format.createPrettyPrint());
wrier.write(document);
wrier.close();
}
// 6、删除指定元素节点:批发价
@Test
public void test6() throws Exception{
SAXReader reader = new SAXReader();
Document document = reader.read("src/book.xml");
Element el =document.getRootElement();
Element el1 = el.element("书");
Element el2 = el1.element("批发价");
el2.getParent().remove(el2);
OutputFormat format = new OutputFormat();
//用字节流 默认为UTF-8
XMLWriter wrier = new XMLWriter(new FileOutputStream("src/book.xml"),format.createPrettyPrint());
wrier.write(document);
wrier.close();
}
// 7、操作XML文件属性
@Test
public void test7() throws Exception{
SAXReader reader = new SAXReader();
Document document = reader.read("src/book.xml");
Element el =document.getRootElement();
Element el1 = el.element("书");
el1.addAttribute("出版商", "清华出版社");
OutputFormat format = new OutputFormat();
//用字节流 默认为UTF-8
XMLWriter wrier = new XMLWriter(new FileOutputStream("src/book.xml"),format.createPrettyPrint());
wrier.write(document);
wrier.close();
}
//8、利用dom4j创建xml文档
@Test
public void test8()throws Exception{
//DocumentHelper对象用于创建对象
Document document = DocumentHelper.createDocument();
// 向文档中添加元素
Element el = document.addElement("school");
//设置元素属性
el.addAttribute("name", "清华大学");
//添加子元素
el.addElement("students").addAttribute("name", "李四");
OutputFormat format = new OutputFormat();
XMLWriter writer = new XMLWriter(new FileOutputStream("src/school.xml"),format.createPrettyPrint());
writer.write(document);
writer.close();
}
}
共用的xml文档:
<?xml version="1.0" encoding="UTF-8"?> <书架> <书> <书名>JavaOOP</书名> <作者>张三</作者> <售价>5.00</售价> </书> <书> <书名>JavaScript</书名> <作者>李四</作者> <售价>5.1</售价> </书> </书架>