您的位置:首页 > 编程语言 > Java开发

java-web 之 第二讲 -- dom4j 解析 XML 文件

2015-05-13 21:40 405 查看

dom4j 之 XML 解析

1:dom4j 简介:

解析XML 文档的开放源代码XML 框架,支持 XML,XPath,XSLT, 出现前景是早期的 dom4j 分离出来后创建的,相对比 dom4j 灵活,也使用SAX 解析器来分析文档。
dom4j API 介绍继承关系图:1:XMl 文档的创建:DocumentHelper-- 静态方法public class Test3 {/***dom4j 创建 XML 文件*/public static void main(String[] args) {// 创建根元素节点 然后创建文档对象Element elRoot = DocumentHelper.createElement("student");Document doc = DocumentHelper.createDocument(elRoot);// 添加属性 先添加根节点的属性elRoot.addAttribute("sn", "1");//添加子元素和元素内容Element elName = elRoot.addElement("name");Element elAge = elRoot.addElement("age");elName.setText("郭新杰");elAge.setText("28");//输出文档 到文件try {OutputFormat format = OutputFormat.createCompactFormat();format.setEncoding("GB2312");format.setIndent(" ");//XMLWriter writer = new XMLWriter(new FileOutputStream("stu.xml"));输出到文件XMLWriter writer = new XMLWriter(format);// 规范化输出writer.write(doc);} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}xml 例子为:<?xml version="1.0" encoding="GB2312"?><?xml-stylesheet type="text/xsl" href="student.xsl"?><students><student sn="1"><name>张三</name><age>12</age></student><student sn="2"><name>李四</name><age>13</age></student><student sn="3"><name>王五</name><age>14</age></student><student sn="4"><name>赵六</name><age>15</age></student></students>

构建 DOM 树 -- xml文件的 dom4j 解析

dom4j 在 包中提供了两个类,DOMReader :从一个现有的 W3C DOM 树构建 dom4j 树
SAXReader : 使用 SAX 解析器,从不同的输入源来构造 dom4j 树
以SAXReader 为例来创建文档对象
SAXReader sax = new SAXReader();
接上面代码为:
SAXReader sax = new SAXReader();
File file = new File("test.xml");
try {
Document d = sax.read(file);
// 访问根元素
Element root = d.getRootElement();
// 得到某个元素的所有子元素
List list = root.elements();

// 利用 XPath 表达式,需要引进 包 jaxen 的支持
list  = root.selectNodes("//name");  //获取 所有 <name> 的元素
list  = root.selectNodes("//student[@sn='1']"); //获取 sn 的值=1的<student> 元素
// XPath 表达式结束 --------------------------------------
System.out.println("\n"+list.size());
for(int m = 0;m<list.size();m++){
Element name =(Element) list.get(m);
System.out.println("这里是 sn 的值 -- "+name.attributeValue("sn"));// 这里是获取元素的指定属性  比如:sn
//System.out.println("00 -- "+name.elementText("name"));// 获取name 的值  这里使用SAXReader 来获取
System.out.println("00 -- "+name.getStringValue());// 获取name 的值 这里使用 XPath 表达式来获取
}
} catch (DocumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

// -------------------------------------------------以 DOMReader 来构造对象
DocumentBuilderFactory df = DocumentBuilderFactory.newInstance();
try {
DocumentBuilder db = df.newDocumentBuilder();
File f = new File("test.xml");
org.w3c.dom.Document doc1 = db.parse(f);

} 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();
}
好了 基础回顾结束,下面开始讲解 dom4j 的访问者模式 和 基于事件的处理

2 : dom4j 访问者模式

实际应用中,我们往往需要遍历整个XML 文档,根据不同类型的节点进行不同的操作,这个时候可以考虑下访问者模式(VIsitor),通常用于处理对象树结构,树中的每个节点对象都可以接受一个访问者对象,
节点对象向访问者对象传递本身。访问者对象反过来调用节点对象的操作。
dom4j 包中 有个 Visitor 接口,针对不同类型节点,定义了多个重载的 visit()  方法  如:访问元素方法为 void visit(Element node)  访问元素属性方法为:  void visit(Attribute node)
我们需要实现 Visitor 接口  然后在 node 中定义了一个 accept(Visitor v)
例子:
public class Dom4jVisitor {/*** dom4j 访问者模式*/public static void main(String[] args) {// TODO Auto-generated method stubSAXReader read = new SAXReader();File f = new File("test.xml");try{Document doc = read.read(f);doc.accept(new MyVisitor());}catch(Exception e){e.printStackTrace();}}} 
package com.tide.servlet;import org.dom4j.Attribute;import org.dom4j.Element;import org.dom4j.ProcessingInstruction;import org.dom4j.VisitorSupport;public class MyVisitor extends VisitorSupport {/*** 对于属性节点,打印出属性的名称和值*/public void visit(Attribute node){System.out.println("attribute: "+node.getName()+" == "+node.getValue());}/*** 对于处理指令节点,打印出处理指令目标和数据*/public void visit(ProcessingInstruction node){System.out.println("处理指令 :"+node.getTarget()+" -- "+node.getText());}/*** 对于元素节点,判断是否只包含文本内容,如果是 打印出元素名称和内容* 如果不是,只打印元素的名称*/public void visit(Element node){if(node.isTextOnly()){System.out.println("element: "+node.getName()+" == "+node.getText());}}}
打印后的内容为:
处理指令 :xml-stylesheet -- type="text/xsl" href="student.xsl"attribute: sn == 1element: name == 张三element: age == 12attribute: sn == 2element: name == 李四element: age == 13attribute: sn == 3element: name == 王五element: age == 14attribute: sn == 4element: name == 赵六element: age == 15

3:dom4j 基于对事件的处理

dom4j 支持对文档的基于事件的处理,尤其是对于较大的文档,可以利用 dom4j 提供的基于事件的处理模型,在解析过程中进行处理,而不必等到整个文档解析完毕。
SAXReader 定义了 addHandler() 方法,用于添加一个 ElementHandler 实例
public void addHandler(String path,ElementHandler handler)    当解析到参数 path 指定的路径时,将调用参数 handler 指定的处理器,针对不同的节点路径,可以添加多个ElementHandler实例。
ElementHandler 接口的方法主要有:
void onStart(ElementPath path) // 解析遇到元素的开始标签时被调用
void onEnd(ElementPath path)   // 解析遇到元素的结束标签时被调用
ElementPath 接口主要方法:
void addHandler(String path,ElementHandler handler)  和 SAXReader 的 addHandler() 方法大致相同
void removeHandler(String path)
String getPath() //获取当前节点路径
Element getCurrent() //获取当前元素
例子:xml 文件还是上面的xml     最大的好处是不必要便利文档所有内容就可以对内容进行处理
public class Test4 {/*** dom4j 基于事件的处理 ElementHandler*/public static void main(String[] args) {SAXReader read  = new SAXReader();File f = new File("test.xml");read.addHandler("/students/student", (ElementHandler) new StudentHandler());try{read.read(f);}catch(Exception e){e.printStackTrace();}}}
package com.tide.servlet;import org.dom4j.Element;import org.dom4j.ElementHandler;import org.dom4j.ElementPath;/*** 定义 StudentHandler 处理器类, 对 <student> 元素进行处理* @author Administrator**/public class StudentHandler implements ElementHandler{@Overridepublic void onStart(ElementPath path) {Element ele =  path.getCurrent();System.out.println("Fount student : "+ele.attributeValue("sn"));//添加对子元素 name 的处理器path.addHandler("name", new Namehandler());System.out.println("添加对子元素 name 的处理器");}@Overridepublic void onEnd(ElementPath path) {// 移除对子元素 name 的处理器path.removeHandler("name");System.out.println("移除对子元素 name 的处理器");}}
package com.tide.servlet;import org.dom4j.Element;import org.dom4j.ElementHandler;import org.dom4j.ElementPath;public class Namehandler implements ElementHandler {@Overridepublic void onEnd(ElementPath path) {Element ele = path.getCurrent();//输出 <name> 元素的名称和文本内容System.out.println("name :"+ele.getName()+" == "+ele.getText());}@Overridepublic void onStart(ElementPath path) {System.out.println("path : "+path.getPath());}}
最后的输出内容为:
Fount student : 1添加对子元素 name 的处理器path : /students/student/namename :name == 张三移除对子元素 name 的处理器Fount student : 2添加对子元素 name 的处理器path : /students/student/namename :name == 李四移除对子元素 name 的处理器Fount student : 3添加对子元素 name 的处理器path : /students/student/namename :name == 王五移除对子元素 name 的处理器Fount student : 4添加对子元素 name 的处理器path : /students/student/namename :name == 赵六移除对子元素 name 的处理器

                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: