一、DOM4J
1、特点:最优秀的一个,集易用和性能于一身。开放源代码(需要导入外部jar包:dom4j-1.6.1.jar)2、场合:使用DOM4J
Attribute定义了XML的属性
| |
Branch为能够包含子节点的节点如XML元素(Element)和文档(Docuemnts)定义了一个公共的行为,
| |
CDATA 定义了XML CDATA 区域
| |
CharacterData是一个标识借口,标识基于字符的节点。如CDATA,Comment, Text.
| |
Comment 定义了XML注释的行为
| |
定义了XML文档
| |
DocumentType 定义XML DOCTYPE声明
| |
Element定义XML 元素
| |
ElementHandler定义了 Element 对象的处理器
| |
Entity定义 XML entity
| |
Node为所有的dom4j中XML节点定义了多态行为
| |
NodeFilter 定义了在dom4j节点中产生的一个滤镜或谓词的行为(predicate)
| |
ProcessingInstruction 定义 XML 处理指令.
| |
Text 定义XML 文本节点.
| |
Visitor 用于实现Visitor模式.
| |
XPath 在分析一个字符串后会提供一个XPath 表达式
|
- SAXReader reader = new SAXReader(); Document doc = reader.read(File xmlfile);
- List childNodes = doc.selectNodes("//Config/Child/ChildNode" );
- for (Object obj:childNodes) {
- Node childNode = (Node)obj;
- String name = childNode.valueOf("@name" );
- String text = childNode.getText();
- }
- 一.Document对象相关
- 1 .读取XML文件,获得document对象.
- SAXReader reader = new SAXReader();
- Document document = reader.read(new File( "input.xml" ));
- 2 .解析XML形式的文本,得到document对象.
- String text = "<members></members>" ;
- Document document = DocumentHelper.parseText(text);
- 3 .主动创建document对象.
- Document document = DocumentHelper.createDocument();
- Element root = document.addElement("members" ); // 创建根节点
- 二.节点相关
- 1 .获取文档的根节点.
- Element rootElm = document.getRootElement();
- 2 .取得某节点的单个子节点.
- Element memberElm=root.element("member" ); // "member"是节点名
- 3 .取得节点的文字
- String text=memberElm.getText();也可以用:
- String text=root.elementText("name" );这个是取得根节点下的name字节点的文字.
- 4 .取得某节点下名为 "member" 的所有字节点并进行遍历.
- List nodes = rootElm.elements("member" );
- for (Iterator it = nodes.iterator(); it.hasNext();) {
- Element elm = (Element) it.next();
- // do something
- }
- 5 .对某节点下的所有子节点进行遍历.
- for (Iterator it=root.elementIterator();it.hasNext();){
- Element element = (Element) it.next();
- // do something
- }
- 6 .在某节点下添加子节点.
- Element ageElm = newMemberElm.addElement("age" );
- 7 .设置节点文字.
- ageElm.setText("29" );
- 8 .删除某节点.
- parentElm.remove(childElm);// childElm是待删除的节点,parentElm是其父节点
- 9 .添加一个CDATA节点.
- Element contentElm = infoElm.addElement("content" );
- contentElm.addCDATA(diary.getContent());
- 三.属性相关.
- 1 .取得某节点下的某属性
- Element root=document.getRootElement();
- Attribute attribute=root.attribute("size" ); // 属性名name
- 2 .取得属性的文字
- String text=attribute.getText();也可以用:
- String text2=root.element("name" ).attributeValue( "firstname" );这个是取得根节点下name字节点的属性firstname的值.
- 3 .遍历某节点的所有属性
- Element root=document.getRootElement();
- for (Iterator it=root.attributeIterator();it.hasNext();){
- Attribute attribute = (Attribute) it.next();
- String text=attribute.getText();
- System.out.println(text);
- }
- 4 .设置某节点的属性和文字.
- newMemberElm.addAttribute("name" , "sitinspring" );
- 5 .设置属性的文字
- Attribute attribute=root.attribute("name" );
- attribute.setText("sitinspring" );
- 6 .删除某属性
- Attribute attribute=root.attribute("size" ); // 属性名name
- root.remove(attribute);
- 四.将文档写入XML文件.
- 1 .文档中全为英文,不设置编码,直接写入的形式.
- XMLWriter writer = new XMLWriter( new FileWriter( "output.xml" ));
- writer.write(document);
- writer.close();
- 2 .文档中含有中文,设置编码格式写入的形式.(或以美化的格式输出到文件)
- OutputFormat format = OutputFormat.createPrettyPrint();
- format.setEncoding("GBK" ); // 指定XML编码
- XMLWriter writer = new XMLWriter( new FileWriter( "output.xml" ),format);
- writer.write(document);
- writer.close();
- 五.字符串与XML的转换
- 1 .将字符串转化为XML
- String text = "<members> <member>sitinspring</member> </members>" ;
- Document document = DocumentHelper.parseText(text);
- 2 .将文档或节点的XML转化为字符串.
- SAXReader reader = new SAXReader();
- Document document = reader.read(new File( "input.xml" ));
- Element root=document.getRootElement();
- String docXmlText=document.asXML();
- String rootXmlText=root.asXML();
- Element memberElm=root.element("member" );
- String memberXmlText=memberElm.asXML();
- dom4j API 包含一个解析 XML 文档的工具。本文中将使用这个解析器创建一个示例 XML 文档。清单 1 显示了这个示例 XML 文档,catalog.xml。
- 与 W3C DOM API 相比,使用 dom4j 所包含的解析器的好处是 dom4j 拥有本地的 XPath 支持。DOM 解析器不支持使用 XPath 选择节点。
- /*DOM4J提供至少3种遍历节点的方法*/
- //1) 枚举(Iterator)
- // 枚举所有子节点
- for ( Iterator i = root.elementIterator(); i.hasNext(); ) {
- Element element = (Element) i.next();
- // do something
- }
- // 枚举名称为foo的节点
- for ( Iterator i = root.elementIterator(foo); i.hasNext();) {
- Element foo = (Element) i.next();
- // do something
- }
- // 枚举属性
- for ( Iterator i = root.attributeIterator(); i.hasNext(); ) {
- Attribute attribute = (Attribute) i.next();
- // do something
- }
- //2)递归
- //递归也可以采用Iterator作为枚举手段,但文档中提供了另外的做法
- public void treeWalk() {
- treeWalk(getRootElement());
- }
- public void treeWalk(Element element) {
- for (int i = 0, size = element.nodeCount(); i < size; i++) {
- Node node = element.node(i);
- if (node instanceof Element) {
- treeWalk((Element) node);
- } else { // do something....
- }
- }
- }
- //3) Visitor模式
- //主要原理就是两种类互相保有对方的引用,并且一种作为Visitor去访问许多Visitable。只需要自定一个类实现Visitor接口即可。
- public class MyVisitor extends VisitorSupport {
- public void visit(Element element){
- System.out.println(element.getName());
- }
- public void visit(Attribute attr){
- System.out.println(attr.getName());
- }
- }
- //调用: root.accept(new MyVisitor())
- import java.io.File;
- import java.io.FileWriter;
- import java.io.IOException;
- import java.util.Iterator;
- import org.dom4j.Attribute;
- import org.dom4j.Document;
- import org.dom4j.DocumentException;
- import org.dom4j.DocumentHelper;
- import org.dom4j.Element;
- import org.dom4j.io.SAXReader;
- import org.dom4j.io.XMLWriter;
- /**
- * dom4j生成与解析XML文档
- */
- public class Dom4jDemo {
- /**
- * 利用dom4j进行xml文档的写入操作
- */
- public void createXml(File file) {
- // XML 声明 <?xml version="1.0" encoding="UTF-8"?> 自动添加到 XML文档中
- // 使用DocumentHelper类创建文档实例(生成 XML文档节点的 dom4j API工厂类)
- Document document = DocumentHelper.createDocument();
- // 使用addElement()方法创建根元素 employees(用于向 XML 文档中增加元素)
- Element root = document.addElement("employees");
- // 在根元素中使用 addComment()方法添加注释"An XML Note"
- root.addComment("An XML Note");
- // 在根元素中使用 addProcessingInstruction()方法增加一个处理指令
- root.addProcessingInstruction("target", "text");
- // 在根元素中使用 addElement()方法增加employee元素。
- Element empElem = root.addElement("employee");
- // 使用 addAttribute()方法向employee元素添加id和name属性
- empElem.addAttribute("id", "0001");
- empElem.addAttribute("name", "wanglp");
- // 向employee元素中添加sex元素
- Element sexElem = empElem.addElement("sex");
- // 使用setText()方法设置sex元素的文本
- sexElem.setText("m");
- // 在employee元素中增加age元素 并设置该元素的文本。
- Element ageElem = empElem.addElement("age");
- ageElem.setText("25");
- // 在根元素中使用 addElement()方法增加employee元素。
- Element emp2Elem = root.addElement("employee");
- // 使用 addAttribute()方法向employee元素添加id和name属性
- emp2Elem.addAttribute("id", "0002");
- emp2Elem.addAttribute("name", "fox");
- // 向employee元素中添加sex元素
- Element sex2Elem = emp2Elem.addElement("sex");
- // 使用setText()方法设置sex元素的文本
- sex2Elem.setText("f");
- // 在employee元素中增加age元素 并设置该元素的文本。
- Element age2Elem = emp2Elem.addElement("age");
- age2Elem.setText("24");
- // 可以使用 addDocType()方法添加文档类型说明。
- // document.addDocType("employees", null, "file://E:/Dtds/dom4j.dtd");
- // 这样就向 XML 文档中增加文档类型说明:
- // <!DOCTYPE employees SYSTEM "file://E:/Dtds/dom4j.dtd">
- // 如果文档要使用文档类型定义(DTD)文档验证则必须有 Doctype。
- try {
- XMLWriter output = new XMLWriter(new FileWriter(file));
- output.write(document);
- output.close();
- } catch (IOException e) {
- System.out.println(e.getMessage());
- }
- }
- /**
- * 利用dom4j进行xml文档的读取操作
- */
- public void parserXml(File file) {
- Document document = null;
- // 使用 SAXReader 解析 XML 文档 catalog.xml:
- SAXReader saxReader = new SAXReader();
- try {
- document = saxReader.read(file);
- } catch (DocumentException e) {
- e.printStackTrace();
- }
- // 将字符串转为XML
- // document = DocumentHelper.parseText(fileString);
- // 获取根节点
- Element root = document.getRootElement();
- // 打印节点名称
- System.out.println("<" + root.getName() + ">");
- // 获取根节点下的子节点遍历
- Iterator<?> iter = root.elementIterator("employee");
- // 遍历employee节点
- while (iter.hasNext()) {
- // 获取当前子节点
- Element empEle = (Element) iter.next();
- System.out.println("<" + empEle.getName() + ">");
- // 获取当前子节点的属性遍历
- Iterator<?> attrList = empEle.attributeIterator();
- while (attrList.hasNext()) {
- Attribute attr = (Attribute) attrList.next();
- System.out.println(attr.getName() + "=" + attr.getValue());
- }
- // 遍历employee节点下所有子节点
- Iterator<?> eleIte = empEle.elementIterator();
- while (eleIte.hasNext()) {
- Element ele = (Element) eleIte.next();
- System.out.println("<" + ele.getName() + ">" + ele.getTextTrim());
- }
- // 获取employee节点下的子节点sex值
- // String sex = empEle.elementTextTrim("sex");
- // System.out.println("sex:" + sex);
- }
- System.out.println("</" + root.getName() + ">");
- }
- public static void main(String[] args) {
- Dom4jDemo dom4j = new Dom4jDemo();
- File file = new File("e:/dom4j.xml");
- // dom4j.createXml(file);
- dom4j.parserXml(file);
- }
- }
/*修改xml文档*/
- public static void modifyxml(){
- //使用SAXReader去解析xml文件
- SAXReader reader=new SAXReader();
- Document document;
- try {
- File file =new File("C:\\workspace\\Test\\myxml.xml");
- //获取document对象
- document=reader.read(file);
- //通过selectNodes寻找节点或者属性
- List list=document.selectNodes("/student/call/@show");
- Iterator it=list.iterator();
- while(it.hasNext()){
- //Attribute属性的操作方法
- Attribute attribute=(Attribute)it.next();
- if(attribute.getValue().equals("yes"))
- {
- attribute.setValue("no");
- }
- }
- list =document.selectNodes("/student/call/name");
- it=list.iterator();
- while(it.hasNext()){
- //标签内容的操作方法
- Element nameElment=(Element)it.next();
- nameElment.setText("studentname");
- }
- //删除某个节点是要用两层循环,因为删除当前节点必须用父节点去删除。
- list=document.selectNodes("/student/call");
- it=list.iterator();
- while(it.hasNext()){
- //获取父节点
- Element scoreElement=(Element)it.next();
- System.out.println(scoreElement);
- @SuppressWarnings("unused")
- //获取该父节点下面的需要查找的子节点
- Iterator itera=scoreElement.elementIterator("English");
- while(itera.hasNext()){
- Element scoreEnglish=(Element)itera.next();
- if(scoreEnglish.getText().equals("77")){
- //利用父节点去删除
- scoreElement.remove(scoreEnglish);
- }
- }
- }
- @SuppressWarnings("unused")
- /*Iterator itera=document.getRootElement().elementIterator("call");
- while(itera.hasNext()){
- Element ele=(Element)itera.next();
- System.out.println(ele);
- }*/
- OutputFormat format = OutputFormat.createPrettyPrint();
- format.setEncoding("UTF-8");
- XMLWriter writer;
- try {
- writer = new XMLWriter(new FileWriter("myxml.xml"),format);
- writer.write(document);
- writer.close();
- }catch (IOException e) {
- e.printStackTrace();
- }catch (DocumentException e) {
- e.printStackTrace();
- }
- }
二、JDOM
1、原理:纯Java的处理XML的API,要实现的功能简单,如解析、创建等,但在底层,JDOM还是使用SAX、DOM、Xanan文档。(需要导入外部jar包:jdom.jar)
2、优点:a、是基于树的处理XML的Java API,把树加载在内存中,具有DOM方式的优点。
b、没有向下兼容的限制,因此比DOM简单
c、可速度快,缺陷少
d、具有SAX的JAVA规则
3、 缺点:a、不能处理大于内存的文档。Dom方式的缺点
b、JDOM表示XML文档逻辑模型。不能保证每个字节真正变换。
c、针对实例文档不提供DTD与模式的任何实际模型。
d、不支持与DOM中相应遍历包
4、场合:在需要平衡时使用。JDOM具有树的便利,也有SAX的JAVA规则。
- //导入jar包:jdom.jar import java.io.File;
- import java.io.FileNotFoundException;
- import java.io.FileOutputStream;
- import java.io.IOException;
- import java.util.List;
- import org.jdom.Attribute;
- import org.jdom.Comment;
- import org.jdom.Document;
- import org.jdom.Element;
- import org.jdom.JDOMException;
- import org.jdom.input.SAXBuilder;
- import org.jdom.output.Format;
- import org.jdom.output.XMLOutputter;
- /**
- * jdom生成与解析XML文档
- */
- public class JdomDemo {
- Document document = new Document();
- /**
- * 利用JDom进行xml文档的写入操作
- */
- public void createXml(File file) {
- // 1.创建元素 及 设置为根元素
- Element employees = new Element("employees");
- document.setContent(employees);
- // 2.创建注释 及 设置到根元素上
- Comment commet = new Comment("this is my comment");
- employees.addContent(commet);
- // 3.创建元素
- Element element1 = new Element("employee");
- // 3.1 设置元素的属性名及属性值
- element1.setAttribute(new Attribute("id", "0001"));
- // 3.2 创建元素的属性名及属性值
- Attribute nameAttr = new Attribute("name", "wanglp");
- // 3.3 设置元素名及文本
- Element sexEle = new Element("sex");
- sexEle.setText("m");
- // 设置到上层元素上
- element1.addContent(sexEle);
- // 设置元素
- Element ageEle = new Element("age");
- ageEle.setText("22");
- element1.addContent(ageEle);
- // 设置为根元素的子元素
- employees.addContent(element1);
- // 将元素属性设置到元素上
- element1.setAttribute(nameAttr);
- // 3.创建元素
- Element element2 = new Element("employee");
- // 3.1 设置元素的属性名及属性值
- element2.setAttribute(new Attribute("id", "0002"));
- // 3.2 创建元素的属性名及属性值
- Attribute name2Attr = new Attribute("name", "fox");
- // 3.3 设置元素名及文本
- Element sex2Ele = new Element("sex");
- sex2Ele.setText("f");
- // 设置到上层元素上
- element2.addContent(sex2Ele);
- // 设置元素
- Element age2Ele = new Element("age");
- age2Ele.setText("21");
- element2.addContent(age2Ele);
- // 设置为根元素的子元素
- employees.addContent(element2);
- // 将元素属性设置到元素上
- element2.setAttribute(name2Attr);
- Element element3 = new Element("employee");
- element3.setText("title");
- element3.addContent(new Element("name").addContent(new Element("hello")));
- employees.addContent(element3);
- // 设置xml文档输出的格式
- Format format = Format.getPrettyFormat();
- XMLOutputter out = new XMLOutputter(format);
- // 将得到的xml文档输出到文件流中
- try {
- out.output(document, new FileOutputStream(file));
- } catch (FileNotFoundException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- /**
- * 利用JDom进行xml文档的读取操作
- */
- public void parserXml(File file) {
- // 建立解析器
- SAXBuilder builder = new SAXBuilder();
- try {
- // 将解析器与文档关联
- document = builder.build(file);
- } catch (JDOMException e1) {
- e1.printStackTrace();
- } catch (IOException e1) {
- e1.printStackTrace();
- }
- // 读取根元素
- Element root = document.getRootElement();
- // 输出根元素的名字
- System.out.println("<" + root.getName() + ">");
- // 读取元素集合
- List<?> employeeList = root.getChildren("employee");
- for (int i = 0; i < employeeList.size(); i++) {
- Element ele = (Element) employeeList.get(i);
- // 得到元素的名字
- System.out.println("<" + ele.getName() + ">");
- // 读取元素的属性集合
- List<?> empAttrList = ele.getAttributes();
- for (int j = 0; j < empAttrList.size(); j++) {
- Attribute attrs = (Attribute) empAttrList.get(j);
- // 将属性的名字和值 并 输出
- String name = attrs.getName();
- String value = (String) attrs.getValue();
- System.out.println(name + "=" + value);
- }
- try {
- Element sex = ele.getChild("sex");
- System.out.println("<sex>" + sex.getText());
- Element age = ele.getChild("age");
- System.out.println("<age>" + age.getText());
- } catch (NullPointerException e) {
- System.out.println(ele.getTextTrim());
- Element name = ele.getChild("name");
- System.out.println("<name>" + name.getName());
- }
- System.out.println("</employee>");
- }
- System.out.println("</employees>");
- }
- /**
- * 测试
- */
- public static void main(String[] args) {
- JdomDemo jdom = new JdomDemo();
- File file = new File("E://jdom.xml");
- jdom.createXml(file);
- jdom.parserXml(file);
- }
- }
三、DOM
1、原理:DOM是基于树的结构,解析器读入-整个-文档,然后构建一个驻留内存的树结构,使用 DOM 接 口来操作这个树结构。2、优点:a、由于整棵树在内存中,便于操作,可以对xml文档随机访问
b、可以对xml文档进行删除、修改、重新排列等多种功能;访问效率高
c、较sax,dom使用也更简单。
3、缺点:a、整个文档必须一次性解析完(无用的节点也会解析),浪费时间和空间.
b、由于整个文档都需要载入内存,对于大文档成本高
4、 场合:小型xml文档;一旦解析了文档还需多次访问这些数据;
- import java.io.File;
- import java.io.FileNotFoundException;
- import java.io.FileOutputStream;
- import java.io.IOException;
- import java.io.PrintWriter;
- import javax.xml.parsers.DocumentBuilder;
- import javax.xml.parsers.DocumentBuilderFactory;
- import javax.xml.parsers.ParserConfigurationException;
- import javax.xml.transform.OutputKeys;
- import javax.xml.transform.Transformer;
- import javax.xml.transform.TransformerConfigurationException;
- import javax.xml.transform.TransformerException;
- import javax.xml.transform.TransformerFactory;
- import javax.xml.transform.dom.DOMSource;
- import javax.xml.transform.stream.StreamResult;
- import org.w3c.dom.Attr;
- 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;
- /**
- * DOM生成与解析XML文档
- *
- * @author 莫小哆_ly 2012-2-20
- */
- public class DomDemo {
- /*
- * 解析器读入整个文档,然后构建一个驻留内存的树结构,
- *
- * 然后代码就可以使用 DOM 接口来操作这个树结构。
- *
- * 优点:整个文档树在内存中,便于操作;支持删除、修改、重新排列等多种功能;
- *
- * 缺点:将整个文档调入内存(包括无用的节点),浪费时间和空间;
- *
- * 使用场合:一旦解析了文档还需多次访问这些数据;硬件资源充足(内存、CPU)
- */
- // 表示整个HTML或 XML文档。从概念上讲,它是文档树的根,并提供对文档数据的基本访问
- private Document document;
- /**
- * 创建DOM树
- *
- * 要读入一个XML文档,首先要一个DocumentBuilder对象
- */
- public void init() {
- // 获取 DocumentBuilderFactory 的新实例
- DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
- // 使用当前配置的参数创建一个新的 DocumentBuilder 实例
- DocumentBuilder builder = null;
- try {
- builder = factory.newDocumentBuilder();
- } catch (ParserConfigurationException e) {
- e.printStackTrace();
- }
- // 获取 DOM Document 对象的一个新实例来生成一个 DOM 树
- this.document = builder.newDocument();
- }
- /**
- * xml文档的写入操作
- *
- * @param file
- */
- public void createXml(File file) {
- // 创建DOM树
- this.init();
- // 创建XML根节点employees
- Element root = this.document.createElement("employees");
- // Adds the node newChild to the end of the list of children of this
- // node.
- // If the newChild is already in the tree, it is first removed.
- this.document.appendChild(root);
- // 1.创建根节点的子节点employee
- Element employee = this.document.createElement("employee");
- // 向根节点添加属性节点
- Attr id = this.document.createAttribute("id");
- id.setNodeValue("0001");
- // 把属性节点对象,追加到达employee节点;
- employee.setAttributeNode(id);
- // 声明employee的子节点name
- Element name = this.document.createElement("name");
- // 向XML文件name节点追加数据
- name.appendChild(this.document.createTextNode("wanglp"));
- // 把子节点的属性追加到employee子节点中元素中
- employee.appendChild(name);
- // 声明employee的子节点sex
- Element sex = this.document.createElement("sex");
- // 向XML文件sex节点追加数据
- sex.appendChild(this.document.createTextNode("m"));
- // 把子节点的属性追加到employee子节点中元素中
- employee.appendChild(sex);
- // 声明employee的子节点age
- Element age = this.document.createElement("age");
- // 向XML文件age节点追加数据
- age.appendChild(this.document.createTextNode("25"));
- // 把子节点的属性追加到employee子节点中元素中
- employee.appendChild(age);
- // employee节点定义完成,追加到root
- root.appendChild(employee);
- // 2.创建根节点的子节点employee
- employee = this.document.createElement("employee");
- // 向根节点添加属性节点
- id = this.document.createAttribute("id");
- id.setNodeValue("0002");
- // 把属性节点对象,追加到达employee节点;
- employee.setAttributeNode(id);
- // 声明employee的子节点name
- name = this.document.createElement("name");
- // 向XML文件name节点追加数据
- name.appendChild(this.document.createTextNode("huli"));
- // 把子节点的属性追加到employee子节点中元素中
- employee.appendChild(name);
- // 声明employee的子节点sex
- sex = this.document.createElement("sex");
- // 向XML文件sex节点追加数据
- sex.appendChild(this.document.createTextNode("f"));
- // 把子节点的属性追加到employee子节点中元素中
- employee.appendChild(sex);
- // 声明employee的子节点age
- age = this.document.createElement("age");
- // 向XML文件age节点追加数据
- age.appendChild(this.document.createTextNode("12"));
- // 把子节点的属性追加到employee子节点中元素中
- employee.appendChild(age);
- // employee节点定义完成,追加到root
- root.appendChild(employee);
- // 获取 TransformerFactory 的新实例。
- TransformerFactory tf = TransformerFactory.newInstance();
- // 创建执行从 Source 到 Result 的复制的新 Transformer。能够将源树转换为结果树
- Transformer transformer = null;
- try {
- transformer = tf.newTransformer();
- } catch (TransformerConfigurationException e) {
- e.printStackTrace();
- }
- // 设置转换中实际的输出属性
- // 指定首选的字符编码
- transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
- // indent="yes"|"no".指定了当输出结果树时,Transformer是否可以添加额外的空白
- transformer.setOutputProperty(OutputKeys.INDENT, "yes");
- // 声明文件流
- PrintWriter pw = null;
- try {
- pw = new PrintWriter(new FileOutputStream(file));
- } catch (FileNotFoundException e) {
- e.printStackTrace();
- System.out.println("文件没有找到!");
- }
- // 充当转换结果的持有者,可以为 XML、纯文本、HTML 或某些其他格式的标记
- StreamResult result = new StreamResult(pw);
- // DOMSource implements Source
- DOMSource source = new DOMSource(document);
- try {
- // 将 XML Source 转换为 Result
- transformer.transform(source, result);
- } catch (TransformerException e) {
- e.printStackTrace();
- System.out.println("生成XML文件失败!");
- }
- System.out.println("生成XML文件成功!");
- }
- /**
- * xml文档的读取操作
- */
- public void parserXml(File file) {
- // 获取 DocumentBuilderFactory 的新实例
- DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
- // 使用当前配置的参数创建一个新的 DocumentBuilder 实例
- DocumentBuilder builder;
- try {
- builder = factory.newDocumentBuilder();
- // 将给定 URI的内容解析为一个 XML文档,并且返回一个新的 DOM Document 对象
- document = builder.parse(file);
- } catch (ParserConfigurationException e) {
- e.printStackTrace();
- } catch (SAXException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- }
- // 获得文档根元素对对象;
- Element root = document.getDocumentElement();
- // 获得文档根元素下一级子元素所有元素;
- NodeList nodeList = root.getChildNodes();
- System.out.print("<employees>");
- System.out.println(root.getNodeName());
- if (null != root) {
- for (int i = 0; i < nodeList.getLength(); i++) {
- Node child = nodeList.item(i);
- // 输出child的属性;
- System.out.print("<test>");
- System.out.println(child);
- if (child.getNodeType() == Node.ELEMENT_NODE) {
- System.out.print("<id>");
- System.out.println(child.getAttributes().getNamedItem("id").getNodeValue());
- }
- for (Node node = child.getFirstChild(); node != null; node = node.getNextSibling()) {
- if (node.getNodeType() == Node.ELEMENT_NODE) {
- if ("name".equals(node.getNodeName())) {
- System.out.print("<name>");
- System.out.println(node.getFirstChild().getNodeValue());
- }
- }
- if (node.getNodeType() == Node.ELEMENT_NODE) {
- if ("sex".equals(node.getNodeName())) {
- System.out.print("<sex>");
- System.out.println(node.getFirstChild().getNodeValue());
- }
- }
- if (node.getNodeType() == Node.ELEMENT_NODE) {
- if ("age".equals(node.getNodeName())) {
- System.out.print("<age>");
- System.out.println(node.getFirstChild().getNodeValue());
- }
- }
- if (node.getNodeType() == Node.ELEMENT_NODE) {
- if ("email".equals(node.getNodeName())) {
- System.out.print("<email>");
- System.out.println(node.getFirstChild().getNodeValue());
- }
- }
- }
- }
- }
- System.out.println("解析完毕");
- }
- /**
- * 测试
- */
- public static void main(String[] args) {
- // 为什么有类似于这样东西[#text:]
- // 原因是XML文件元素之间的空白字符也是一个元素,<employees></employees>包含的空白
- DomDemo dom = new DomDemo();
- File file = new File("E://dom.xml");
- dom.createXml(file);
- dom.parserXml(file);
- }
- }
四、SAX
1、原理:SAX类似流媒体,它基于事件驱动,当解析器发现元素开始、元素结束、文本、文档的开始或结束 等时,发送事件,程序员编写响应这些事件的代码,保存数据。无需将整个文档载入内存,使用者 只需要监听自己感兴趣的事件即可。2、优点:a、无需将整个xml文档载入内存,因此消耗内存少
b、SAX解析器代码比DOM解析器代码小,适于Applet,下载。
c、可以注册多个ContentHandler
3、缺点:a、不能随机的访问xml中的节点
b、只支持读,不能修改文档。非持久,事件过后,若没保存数据,那么数据就丢了
c、无状态性;从事件中只能得到文本,但不知该文本属于哪个元素
4、场合:大型xml文档;Applet;只需XML文档的少量内容,很少回头访问;
- import java.io.File;
- import javax.xml.parsers.SAXParser;
- import javax.xml.parsers.SAXParserFactory;
- import org.xml.sax.Attributes;
- import org.xml.sax.SAXException;
- import org.xml.sax.helpers.DefaultHandler;
- /**
- * startDocument(),endDocument(),startElement(),endElement(),characters()
- */
- public class SAXParseDemo extends DefaultHandler {
- private String tagValue; // 标签值
- // 开始解析XML文件
- public void startDocument() throws SAXException {
- System.out.println("开始解析");
- }
- // 结束解析XML文件
- public void endDocument() throws SAXException {
- System.out.println("结束解析");
- }
- // 解析元素
- /**
- * 开始解析一个元素
- * @param qName 标签名
- * @param attributes 属性
- */
- @Override
- public void startElement(String uri, String localName, String qName, Attributes attributes)
- throws SAXException {
- System.out.println(qName + "开始");
- // 属性
- if (attributes != null && attributes.getLength() != 0) {
- System.out.println("属性:");
- for (int i = 0; i < attributes.getLength(); i++) {
- System.out.print(attributes.getQName(i) + "="); // 属性名
- System.out.print(attributes.getValue(i) + " "); // 属性值
- }
- System.out.println();
- }
- }
- /**
- * 结束一个元素的解析 遇到结束标签时调用此方法 通常在此方法对标签取值并处理
- */
- @Override
- public void endElement(String uri, String localName, String qName) throws SAXException {
- System.out.println(qName + "标签值:" + tagValue);
- System.out.println(qName + "结束");
- }
- // 所有xml文件中的字符都会放到ch[]中
- public void characters(char ch[], int start, int length) throws SAXException {
- tagValue = new String(ch, start, length).trim();
- }
- public static void main(String[] args) {
- File file = new File("src/cn/main/example/demo.xml");
- SAXParserFactory saxParFac = SAXParserFactory.newInstance();
- try {
- SAXParser saxParser = saxParFac.newSAXParser();
- saxParser.parse(file, new SAXParseDemo());
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
五、资料(关于Xpath)
1、选取节点
XPath 使用路径表达式在 XML 文档中选取节点,节点是沿着路径或者 step 来选取的。
常见的路径表达式:
表达式 | 描述 |
nodename | 选取当前节点的所有子节点 |
/ | 从根节点选取 |
// | 从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置 |
. | 选取当前节点 |
.. | 选取当前节点的父节点 |
@ | 选取属性 |
实例
路径表达式 | 结果 |
bookstore | 选取 bookstore 元素的所有子节点 |
/bookstore | 选取根元素 bookstore |
bookstore/book | 选取bookstore 下名字为 book的所有子元素。 |
//book | 选取所有 book 子元素,而不管它们在文档中的位置。 |
bookstore//book | 选取bookstore 下名字为 book的所有后代元素,而不管它们位于 bookstore 之下的什么位置。 |
//@lang | 选取所有名为 lang 的属性。 |
2、谓语(Predicates)
谓语用来查找某个特定的节点或者包含某个指定的值的节点。
谓语被嵌在方括号中。
实例
常见的谓语的一些路径表达式:
路径表达式 | 结果 |
/bookstore/book[1] | 选取属于 bookstore 子元素的第一个 book 元素。 |
/bookstore/book[last()] | 选取属于 bookstore 子元素的最后一个 book 元素。 |
/bookstore/book[last()-1] | 选取属于 bookstore 子元素的倒数第二个 book 元素。 |
/bookstore/book[position()<3] | 选取最前面的两个属于 bookstore 元素的子元素的 book 元素。 |
//title[@lang] | 选取所有拥有名为 lang 的属性的 title 元素。 |
//title[@lang='eng'] | 选取所有 title 元素,要求这些元素拥有值为 eng 的 lang 属性。 |
/bookstore/book[price>35.00] | 选取所有 bookstore 元素的 book 元素,要求book元素的子元素 price 元素的值须大于 35.00。 |
/bookstore/book[price>35.00]/title | 选取所有 bookstore 元素中的 book 元素的 title 元素,要求book元素的子元素 price 元素的值须大于 35.00 |
3、选取未知节点
XPath 通配符可用来选取未知的 XML 元素。
通配符 | 描述 |
* | 匹配任何元素节点 |
@* | 匹配任何属性节点 |
node() | 匹配任何类型的节点 |
实例
路径表达式 | 结果 |
/bookstore/* | 选取 bookstore 元素的所有子节点 |
//* | 选取文档中的所有元素 |
//title[@*] | 选取所有带有属性的 title 元素。 |
4、选取若干路径
通过在路径表达式中使用“|”运算符,您可以选取若干个路径。
实例
路径表达式 | 结果 |
//book/title | //book/price | 选取所有 book 元素的 title 和 price 元素。 |
//title | //price | 选取所有文档中的 title 和 price 元素。 |
/bookstore/book/title|//price | 选取所有属于 bookstore 元素的 book 元素的 title 元素,以及文档中所有的 price 元素。 |
5、XPath 轴
轴可定义某个相对于当前节点的节点集。
轴名称 | 结果 |
ancestor | 选取当前节点的所有先辈(父、祖父等) |
ancestor-or-self | 选取当前节点的所有先辈(父、祖父等)以及当前节点本身 |
attribute | 选取当前节点的所有属性 |
child | 选取当前节点的所有子元素。 |
descendant | 选取当前节点的所有后代元素(子、孙等)。 |
descendant-or-self | 选取当前节点的所有后代元素(子、孙等)以及当前节点本身。 |
following | 选取文档中当前节点的结束标签之后的所有节点。 |
namespace | 选取当前节点的所有命名空间节点 |
parent | 选取当前节点的父节点。 |
preceding | 选取文档中当前节点的开始标签之前的所有节点。 |
preceding-sibling | 选取当前节点之前的所有同级节点。 |
self | 选取当前节点。 |
6、路径
- 位置路径表达式
位置路径可以是绝对的,也可以是相对的。
绝对路径起始于正斜杠( / ),而相对路径不会这样。在两种情况中,位置路径均包括一个或多个步,每个步均被斜杠分割:
- 绝对位置路径:
- 相对位置路径:
/step/step/...
step/step/...
每个步均根据当前节点集之中的节点来进行计算。
- 步(step)包括:
轴(axis):定义所选节点与当前节点之间的树关系
节点测试(node-test):识别某个轴内部的节点
零个或者更多谓语(predicate):更深入地提炼所选的节点集
步的语法:轴名称::节点测试[谓语]
实例
例子 | 结果 |
child::book | 选取所有属于当前节点的子元素的 book 节点 |
attribute::lang | 选取当前节点的 lang 属性 |
child::* | 选取当前节点的所有子元素 |
attribute::* | 选取当前节点的所有属性 |
child::text() | 选取当前节点的所有文本子节点 |
child::node() | 选取当前节点的所有子节点 |
descendant::book | 选取当前节点的所有 book 后代 |
ancestor::book | 选择当前节点的所有 book 先辈 |
ancestor-or-self::book | 选取当前节点的所有book先辈以及当前节点(假如此节点是book节点的话) |
child::*/child::price | 选取当前节点的所有 price 孙。 |
7、XPath 运算符
运算符 | 描述 | 实例 | 返回值 |
| | 计算两个节点集 | //book | //cd | 返回所有带有 book 和 ck 元素的节点集 |
+ | 加法 | 6 + 4 | 10 |
- | 减法 | 6 - 4 | 2 |
* | 乘法 | 6 * 4 | 24 |
div | 除法 | 8 div 4 | 2 |
= | 等于 | price=9.80 | 如果 price 是 9.80,则返回 true。 如果 price 是 9.90,则返回 fasle。 |
!= | 不等于 | price!=9.80 | 如果 price 是 9.90,则返回 true。 如果 price 是 9.80,则返回 fasle。 |
< | 小于 | price<9.80 | 如果 price 是 9.00,则返回 true。 如果 price 是 9.90,则返回 fasle。 |
<= | 小于或等于 | price<=9.80 | 如果 price 是 9.00,则返回 true。 如果 price 是 9.90,则返回 fasle。 |
> | 大于 | price>9.80 | 如果 price 是 9.90,则返回 true。 如果 price 是 9.80,则返回 fasle。 |
>= | 大于或等于 | price>=9.80 | 如果 price 是 9.90,则返回 true。 如果 price 是 9.70,则返回 fasle。 |
or | 或 | price=9.80 or price=9.70 | 如果 price 是 9.80,则返回 true。 如果 price 是 9.50,则返回 fasle。 |
and | 与 | price>9.00 and price<9.90 | 如果 price 是 9.80,则返回 true。 如果 price 是 8.50,则返回 fasle。 |
mod | 计算除法的余数 | 5 mod 2 | 1 |
大部分源代码来源于:http://blog.csdn.net/sdsky1987/article/details/7286306
部分资料来源于:http://sharep.blog.51cto.com/539048/170467
Dom4j大部分资料来源于:http://blog.csdn.net/dy_smile/article/details/5926811
Xpath部分内容来源于:http://nemogu.iteye.com/blog/1305503