XML解析的两种方式:DOM方式和SAX方式

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u012526194/article/details/48751359

DOM:Document ObjectModel,文档对象模型。这种方式是W3C推荐的处理XML的一种方式。
SAX:Simple API for XML。这种方式不是官方标准,属于开源社区XML-DEV,几乎所有的XML解析器都支持它。

一、DOM解析:

         一次性把xml文档加载成Document树,通过Document对象得到节点对象,通过节点对象访问xml文档内容(标签,属性,文本,注释)。

a)JAXP解析:是SUN公司推出的解析标准实现。

                      以book.xml为例讲解。

<书架>
     <书>
          <书名>计算机网络</书名>
          <作者>张三</作者>
          <售价>100</售价>
     </书>
     <书>
          <书名>数据结构</书名>
          <作者>李四</作者>
          <售价>80</售价>
     </书>
</书架>
获得JAXP中的DOM解析器
l、调用DocumentBuilderFactory.newInstance() 方法得到创建DOM 解析器的工厂。
2、调用工厂对象的newDocumentBuilder方法得到DOM 解析器对象。
3、调用DOM 解析器对象的parse() 方法解析XML 文档,得到代表整个文档的Document 对象,进行可以利用DOM特性对整个XML文档进行操作了。
// 创建解析器对象
DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
// 加载XML文档
Document document = db.parse("src/book.xml");

1、得到某个具体的节点内容 : eg: 拿到计算机网络的售价

public static void test1(Document document) {
		// 拿到所有售价节点
		NodeList nl = document.getElementsByTagName("售价");
		// 获得计算机网络的售价节点
		Node n = nl.item(1);

		// 获取售价文本
		System.out.println(n.getTextContent());
	}
2、遍历所有元素节点
public static void test2(Node node) {
		// 对node节点进行循环
		NodeList nl = node.getChildNodes();
		// 循环判断
		for (int i = 0; i < nl.getLength(); i++) {
			Node n = nl.item(i);
			if (n.getNodeType() == Node.ELEMENT_NODE) {
				// 说明此节点就是标签节点
				System.out.println(n.getNodeName());
				test2(n);
			}
		}
	}
3、修改某个元素节点的主体内容 eg: 修改计算机网络的售价为80
public static void test3(Document document) throws Exception {
		// 拿到所有售价节点
		NodeList nl = document.getElementsByTagName("售价");
		// 获得计算机网络的售价节点
		Node n = nl.item(1);
		// 修改主体内容
		n.setTextContent("80");

		// 将修改的结果保存到硬盘上
		Transformer tf = TransformerFactory.newInstance().newTransformer();
		tf.transform(new DOMSource(document), new StreamResult("src/book.xml"));

	}
4、向指定元素节点中增加子元素节点:eg:给数据结构的售价增加一个内部价节点 :50
public static void test4(Document document) throws Exception {
		// 拿到所有售价节点
		NodeList nl = document.getElementsByTagName("售价");
		// 获得数据结构的售价节点
		Node n = nl.item(0);


		// 创建新的节点
		Element el = document.createElement("内部价");
		// 设置节点的主体内容
		el.setTextContent("50");


		// 将内部价节点挂接到售价几点上
		n.appendChild(el);


		// 将修改的结果保存到硬盘上
		Transformer tf = TransformerFactory.newInstance().newTransformer();
		tf.transform(new DOMSource(document), new StreamResult("src/book.xml"));
	}
5、向指定元素节点上增加同级元素节点 : eg:给数据结构的售价增加一个批发价节点 :60
public static void test5(Document document) throws Exception {
		// 拿到所有书节点
		NodeList nl = document.getElementsByTagName("书");
		// 获得数据结构的书节点
		Node n = nl.item(0);

		// 创建批发价节点
		Element el = document.createElement("批发价");
		// 设置节点的主体内容
		el.setTextContent("60");

		// 将内部价节点挂接到书点上
		n.appendChild(el);

		// 将修改的结果保存到硬盘上
		Transformer tf = TransformerFactory.newInstance().newTransformer();
		tf.transform(new DOMSource(document), new StreamResult("src/book.xml"));
	}
6、删除指定元素节点 eg: 删除内部价节点
public static void test6(Document document) throws Exception {
		// 拿到所有内部价节点
		NodeList nl = document.getElementsByTagName("内部价");
		// 拿到数据结构的内部价节点
		Node node = nl.item(0);

		// 父亲干掉儿子
		node.getParentNode().removeChild(node);

		// 将修改的结果保存到硬盘上
		Transformer tf = TransformerFactory.newInstance().newTransformer();
		tf.transform(new DOMSource(document), new StreamResult("src/book.xml"));
	}
7、操作XML文件属性: eg: 给数据结构的书几点增加一个属性: ISBN : "小小程序员"
public static void test7(Document document) throws Exception {
		// 拿到所有书节点
		NodeList nl = document.getElementsByTagName("书");
		// 获得数据结构的书节点
		Node n = nl.item(0);

		// 增加一个属性
		((Element) n).setAttribute("ISBN", "小小程序员");

		// 将修改的结果保存到硬盘上
		Transformer tf = TransformerFactory.newInstance().newTransformer();
		tf.transform(new DOMSource(document), new StreamResult("src/book.xml"));
	}

b)Dom4J解析:

          i.第一步:读取XML文档信息,生成document对象

1.读取XML文件,获得document对象

<p></p><p>SAXReader reader = new SAXReader();
Document  document = reader.read(new File("input.xml"));</p>

2.解析XML形式的文本,得到document对象.

<p>String text = "<members></members>";
Documentdocument = DocumentHelper.parseText(text);</p>

3.主动创建document对象.

<p>Document document = DocumentHelper.createDocument();
//创建根节点</p><p>Element root = document.addElement("members");</p>

           ii.  第二步:修改XML文档的信息

1. 增:文档、标签、属性

//1.创建文档
Document doc = DocumentHelper.createDocument();
//2.增加标签
Element rootElem = doc.addElement("contactList");
//doc.addElement("contactList");
Element contactElem = rootElem.addElement("contact");
contactElem.addElement("name");
//3.增加属性
contactElem.addAttribute("id", "001");
contactElem.addAttribute("name", "eric");

2.删:标签、属性

 1.删除标签     1.1得到标签对象  1.2删除标签对象

Element ageElem = doc.getRootElement().element("contact").element("age");
//1.2 删除标签对象<span style="white-space:pre">		</span>
ageElem.detach();
//先取得父标签,然后通过父标签移出自己
//ageElem.getParent().remove(ageElem);

2.删除属性   2.1得到属性对象  2.2删除属性

//2.1得到属性对象
//得到第二个contact标签
Element contactElem = (Element)doc.getRootElement().elements().get(1);
//2.2 得到属性对象
Attribute idAttr = contactElem.attribute("id");
//2.3 删除属性
idAttr.detach();
//idAttr.getParent().remove(idAttr);

3. 改:属性值、文本

方案一:修改属性值   1.得到标签对象 2.得到属性对象 3.修改属性值

//1.1  得到标签对象
Element contactElem = doc.getRootElement().element("contact");
//1.2 得到属性对象
Attribute idAttr = contactElem.attribute("id");
//1.3 修改属性值
idAttr.setValue("003");

方案二:修改属性值1.1 得到标签对象1.2 通过增加同名属性的方法,修改属性值

//1.1  得到标签对象
Element contactElem = doc.getRootElement().element("contact");
//1.2 通过增加同名属性的方法,修改属性值
contactElem.addAttribute("id", "004");

修改文本 1.得到标签对象 2.修改文本

Element nameElem = doc.getRootElement().element("contact").element("name");
nameElem.setText("李四");

                      ii.第三步:将修改后的XML文档写入到文件

FileOutputStream out = new FileOutputStream("e:/contact.xml");
//1.指定写出的格式
//紧凑的格式.去除空格换行.项目上线的时候
OutputFormat format = OutputFormat.createCompactFormat();
//漂亮的格式.有空格和换行.开发调试的时候
//OutputFormat format = OutputFormat.createPrettyPrint();
<pre name="code" class="java">/**
* 2.指定生成的xml文档的编码
*   同时影响了xml文档保存时的编码  和  xml文档声明的encoding的编码(xml解析时的编码)
*   结论: 使用该方法生成的xml文档避免中文乱码问题。
*/
format.setEncoding("utf-8");
//1.创建写出对象
XMLWriter writer = new XMLWriter(out,format);
//2.写出对象
writer.write(doc);
//3.关闭流
writer.close();

c)XPath技术:主要是用于快速获取所需的节点对象

1)导入xPath支持jar包。  jaxen-1.1-beta-6.jar

2)使用xpath方法

         List<Node>  selectNodes("xpath表达式");      查询多个节点对象

          Node       selectSingleNode("xpath表达式");  查询一个节点对象

                   3)xPath语法:

                           /       绝对路径      表示从xml的根位置开始或子元素(一个层次结构)

                            //      相对路径      表示不分任何层次结构的选择元素。

                            *       通配符        表示匹配所有元素

                            []      条件          表示选择什么条件下的元素

                            @      属性         表示选择属性节点

                            and     关系         表示条件的与关系(等价于&&)

                            text()    文本         表示选择文本内容

二、SAX解析:加载一点,读取一点,处理一点。对内存要求比较低。

<span style="white-space:pre">		</span>   //创建sax解析器
                   SAXParser sax =SAXParserFactory.newInstance().newSAXParser() ;
                   //获取内容读取器
                   XMLReader xml =  sax.getXMLReader() ;
                   //注册一个内容处理器
                   xml.setContentHandler(newDefaultHandler(){
                            String curName ="" ;  //记录当前是那个标签
                            int index = 0 ;  //记录读取到了那个作者
 
                            public voidstartElement(String uri, String localName,
                                               StringqName, Attributes attributes) throws SAXException {
                                      if(qName.equals("作者")){
                                               curName= "作者" ;
                                               index++ ;
                                     }
                            }
 
                            public voidendElement(String uri, String localName, String qName)
                                               throwsSAXException {
                                     curName ="" ;
                            }
 
                            public voidcharacters(char[] ch, int start, int length)
                                               throwsSAXException {
                                    
                                     if("作者".equals(curName)&& index == 2){
                                               //说明读取到了第二本书的作者
                                               System.out.println(newString(ch,start,length));
                                     }
                            }
                   }) ;
                   //加载xml文档
                   xml.parse("src/book.xml");

============DOM解析    vs  SAX解析              ========

DOM解析

SAX解析

原理: 一次性加载xml文档,不适合大容量的文件读取

原理: 加载一点,读取一点,处理一点。适合大容量文件的读取

DOM解析可以任意进行增删改成

SAX解析只能读取

DOM解析任意读取任何位置的数据,甚至往回读

SAX解析只能从上往下,按顺序读取,不能往回读

DOM解析面向对象的编程方法(Node,Element,Attribute),Java开发者编码比较简单。

SAX解析基于事件的编程方法。java开发编码相对复杂。






展开阅读全文

没有更多推荐了,返回首页