XML解析方式之DOM、SAX、JDOM、DOM4J

一、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 对象的处理器
被  ElementHandler  使用,用于取得当前正在处理的路径层次信息
Entity定义 XML entity
Node为所有的dom4j中XML节点定义了多态行为
NodeFilter 定义了在dom4j节点中产生的一个滤镜或谓词的行为(predicate)
ProcessingInstruction 定义 XML 处理指令.
Text 定义XML 文本节点.
Visitor 用于实现Visitor模式.
XPath 在分析一个字符串后会提供一个XPath 表达式


[java]  view plain copy print ?
  1. SAXReader reader = new SAXReader();                                                                                                                       Document doc = reader.read(File xmlfile);     
  2. List childNodes = doc.selectNodes("//Config/Child/ChildNode" );     
  3. for (Object obj:childNodes) {     
  4. Node childNode = (Node)obj;     
  5. String name = childNode.valueOf("@name" );     
  6. String text = childNode.getText();     
  7. }     
  8. 一.Document对象相关    
  9. 1 .读取XML文件,获得document对象.    
  10.              SAXReader reader = new SAXReader();    
  11.              Document    document = reader.read(new File( "input.xml" ));     
  12. 2 .解析XML形式的文本,得到document对象.    
  13.               String text = "<members></members>" ;    
  14.               Document document = DocumentHelper.parseText(text);    
  15. 3 .主动创建document对象.    
  16.               Document document = DocumentHelper.createDocument();    
  17.               Element root = document.addElement("members" ); // 创建根节点     
  18. 二.节点相关    
  19. 1 .获取文档的根节点.    
  20. Element rootElm = document.getRootElement();    
  21. 2 .取得某节点的单个子节点.    
  22. Element memberElm=root.element("member" ); // "member"是节点名     
  23. 3 .取得节点的文字    
  24. String text=memberElm.getText();也可以用:    
  25. String text=root.elementText("name" );这个是取得根节点下的name字节点的文字.    
  26. 4 .取得某节点下名为 "member" 的所有字节点并进行遍历.    
  27. List nodes = rootElm.elements("member" );    
  28. for (Iterator it = nodes.iterator(); it.hasNext();) {    
  29.      Element elm = (Element) it.next();    
  30.    // do something     
  31. }    
  32. 5 .对某节点下的所有子节点进行遍历.    
  33.             for (Iterator it=root.elementIterator();it.hasNext();){    
  34.                   Element element = (Element) it.next();    
  35.                 // do something     
  36.               }    
  37. 6 .在某节点下添加子节点.    
  38. Element ageElm = newMemberElm.addElement("age" );    
  39. 7 .设置节点文字.    
  40. ageElm.setText("29" );    
  41. 8 .删除某节点.    
  42. parentElm.remove(childElm);// childElm是待删除的节点,parentElm是其父节点     
  43. 9 .添加一个CDATA节点.    
  44.           Element contentElm = infoElm.addElement("content" );    
  45.           contentElm.addCDATA(diary.getContent());    
  46.     
  47. 三.属性相关.    
  48. 1 .取得某节点下的某属性    
  49.               Element root=document.getRootElement();        
  50.               Attribute attribute=root.attribute("size" ); // 属性名name     
  51. 2 .取得属性的文字    
  52.               String text=attribute.getText();也可以用:    
  53. String text2=root.element("name" ).attributeValue( "firstname" );这个是取得根节点下name字节点的属性firstname的值.    
  54. 3 .遍历某节点的所有属性    
  55.               Element root=document.getRootElement();        
  56.             for (Iterator it=root.attributeIterator();it.hasNext();){    
  57.                   Attribute attribute = (Attribute) it.next();    
  58.                   String text=attribute.getText();    
  59.                  System.out.println(text);    
  60.               }    
  61. 4 .设置某节点的属性和文字.    
  62. newMemberElm.addAttribute("name" , "sitinspring" );    
  63. 5 .设置属性的文字    
  64.               Attribute attribute=root.attribute("name" );    
  65.               attribute.setText("sitinspring" );    
  66. 6 .删除某属性    
  67.               Attribute attribute=root.attribute("size" ); // 属性名name     
  68.               root.remove(attribute);    
  69. 四.将文档写入XML文件.    
  70. 1 .文档中全为英文,不设置编码,直接写入的形式.    
  71. XMLWriter writer = new XMLWriter( new FileWriter( "output.xml" ));    
  72. writer.write(document);    
  73. writer.close();    
  74. 2 .文档中含有中文,设置编码格式写入的形式.(或以美化的格式输出到文件)    
  75.               OutputFormat format = OutputFormat.createPrettyPrint();    
  76.               format.setEncoding("GBK" );     // 指定XML编码             
  77.               XMLWriter writer = new XMLWriter( new FileWriter( "output.xml" ),format);    
  78.               writer.write(document);    
  79.               writer.close();    
  80. 五.字符串与XML的转换    
  81. 1 .将字符串转化为XML    
  82. String text = "<members> <member>sitinspring</member> </members>" ;    
  83. Document document = DocumentHelper.parseText(text);    
  84. 2 .将文档或节点的XML转化为字符串.    
  85.               SAXReader reader = new SAXReader();    
  86.               Document    document = reader.read(new File( "input.xml" ));                
  87.               Element root=document.getRootElement();                    
  88.               String docXmlText=document.asXML();    
  89.               String rootXmlText=root.asXML();    
  90.               Element memberElm=root.element("member" );    
  91.               String memberXmlText=memberElm.asXML();    
  92. dom4j API 包含一个解析 XML 文档的工具。本文中将使用这个解析器创建一个示例 XML 文档。清单 1 显示了这个示例 XML 文档,catalog.xml。    
  93. 与 W3C DOM API 相比,使用 dom4j 所包含的解析器的好处是 dom4j 拥有本地的 XPath 支持。DOM 解析器不支持使用 XPath 选择节点。    

[java]  view plain copy print ?
  1. /*DOM4J提供至少3种遍历节点的方法*/  
  2. //1) 枚举(Iterator)  
  3.  // 枚举所有子节点  
  4.     for ( Iterator i = root.elementIterator(); i.hasNext(); ) {  
  5.        Element element = (Element) i.next();  
  6.        // do something  
  7.     }  
  8.     // 枚举名称为foo的节点  
  9.     for ( Iterator i = root.elementIterator(foo); i.hasNext();) {  
  10.        Element foo = (Element) i.next();  
  11.        // do something  
  12.     }  
  13.     // 枚举属性  
  14.     for ( Iterator i = root.attributeIterator(); i.hasNext(); ) {  
  15.        Attribute attribute = (Attribute) i.next();  
  16.        // do something  
  17.     }  
  18. //2)递归  
  19. //递归也可以采用Iterator作为枚举手段,但文档中提供了另外的做法  
  20. public void treeWalk() {  
  21.        treeWalk(getRootElement());  
  22.     }  
  23.     public void treeWalk(Element element) {  
  24.        for (int i = 0, size = element.nodeCount(); i < size; i++)     {  
  25.            Node node = element.node(i);  
  26.            if (node instanceof Element) {  
  27.               treeWalk((Element) node);  
  28.            } else { // do something....  
  29.            }  
  30.        }  
  31. }  
  32. //3) Visitor模式  
  33. //主要原理就是两种类互相保有对方的引用,并且一种作为Visitor去访问许多Visitable。只需要自定一个类实现Visitor接口即可。  
  34. public class MyVisitor extends VisitorSupport {  
  35.        public void visit(Element element){  
  36.               System.out.println(element.getName());  
  37.        }  
  38.        public void visit(Attribute attr){  
  39.               System.out.println(attr.getName());  
  40.        }  
  41. }  
  42. //调用:  root.accept(new MyVisitor())  
[java]  view plain copy print ?
  1. import java.io.File;  
  2. import java.io.FileWriter;  
  3. import java.io.IOException;  
  4. import java.util.Iterator;  
  5. import org.dom4j.Attribute;  
  6. import org.dom4j.Document;  
  7. import org.dom4j.DocumentException;  
  8. import org.dom4j.DocumentHelper;  
  9. import org.dom4j.Element;  
  10. import org.dom4j.io.SAXReader;  
  11. import org.dom4j.io.XMLWriter;  
  12.   
  13. /** 
  14.  * dom4j生成与解析XML文档 
  15.  */  
  16. public class Dom4jDemo {  
  17.   
  18.     /** 
  19.      * 利用dom4j进行xml文档的写入操作 
  20.      */  
  21.     public void createXml(File file) {  
  22.   
  23.         // XML 声明 <?xml version="1.0" encoding="UTF-8"?> 自动添加到 XML文档中  
  24.   
  25.         // 使用DocumentHelper类创建文档实例(生成 XML文档节点的 dom4j API工厂类)  
  26.         Document document = DocumentHelper.createDocument();  
  27.   
  28.         // 使用addElement()方法创建根元素 employees(用于向 XML 文档中增加元素)  
  29.         Element root = document.addElement("employees");  
  30.   
  31.         // 在根元素中使用 addComment()方法添加注释"An XML Note"  
  32.         root.addComment("An XML Note");  
  33.   
  34.         // 在根元素中使用 addProcessingInstruction()方法增加一个处理指令  
  35.         root.addProcessingInstruction("target""text");  
  36.   
  37.         // 在根元素中使用 addElement()方法增加employee元素。  
  38.         Element empElem = root.addElement("employee");  
  39.   
  40.         // 使用 addAttribute()方法向employee元素添加id和name属性  
  41.         empElem.addAttribute("id""0001");  
  42.         empElem.addAttribute("name""wanglp");  
  43.   
  44.         // 向employee元素中添加sex元素  
  45.         Element sexElem = empElem.addElement("sex");  
  46.         // 使用setText()方法设置sex元素的文本  
  47.         sexElem.setText("m");  
  48.   
  49.         // 在employee元素中增加age元素 并设置该元素的文本。  
  50.         Element ageElem = empElem.addElement("age");  
  51.         ageElem.setText("25");  
  52.   
  53.         // 在根元素中使用 addElement()方法增加employee元素。  
  54.         Element emp2Elem = root.addElement("employee");  
  55.   
  56.         // 使用 addAttribute()方法向employee元素添加id和name属性  
  57.         emp2Elem.addAttribute("id""0002");  
  58.         emp2Elem.addAttribute("name""fox");  
  59.   
  60.         // 向employee元素中添加sex元素  
  61.         Element sex2Elem = emp2Elem.addElement("sex");  
  62.         // 使用setText()方法设置sex元素的文本  
  63.         sex2Elem.setText("f");  
  64.   
  65.         // 在employee元素中增加age元素 并设置该元素的文本。  
  66.         Element age2Elem = emp2Elem.addElement("age");  
  67.         age2Elem.setText("24");  
  68.   
  69.         // 可以使用 addDocType()方法添加文档类型说明。  
  70.         // document.addDocType("employees", null, "file://E:/Dtds/dom4j.dtd");  
  71.         // 这样就向 XML 文档中增加文档类型说明:  
  72.         // <!DOCTYPE employees SYSTEM "file://E:/Dtds/dom4j.dtd">  
  73.         // 如果文档要使用文档类型定义(DTD)文档验证则必须有 Doctype。  
  74.   
  75.         try {  
  76.             XMLWriter output = new XMLWriter(new FileWriter(file));  
  77.             output.write(document);  
  78.             output.close();  
  79.         } catch (IOException e) {  
  80.             System.out.println(e.getMessage());  
  81.         }  
  82.     }  
  83.   
  84.     /** 
  85.      * 利用dom4j进行xml文档的读取操作 
  86.      */  
  87.     public void parserXml(File file) {  
  88.   
  89.         Document document = null;  
  90.   
  91.         // 使用 SAXReader 解析 XML 文档 catalog.xml:  
  92.         SAXReader saxReader = new SAXReader();  
  93.   
  94.         try {  
  95.             document = saxReader.read(file);  
  96.         } catch (DocumentException e) {  
  97.             e.printStackTrace();  
  98.         }  
  99.         // 将字符串转为XML  
  100.         // document = DocumentHelper.parseText(fileString);  
  101.   
  102.         // 获取根节点  
  103.         Element root = document.getRootElement();  
  104.         // 打印节点名称  
  105.         System.out.println("<" + root.getName() + ">");  
  106.   
  107.         // 获取根节点下的子节点遍历  
  108.         Iterator<?> iter = root.elementIterator("employee");  
  109.         // 遍历employee节点  
  110.         while (iter.hasNext()) {  
  111.             // 获取当前子节点  
  112.             Element empEle = (Element) iter.next();  
  113.             System.out.println("<" + empEle.getName() + ">");  
  114.   
  115.             // 获取当前子节点的属性遍历  
  116.             Iterator<?> attrList = empEle.attributeIterator();  
  117.             while (attrList.hasNext()) {  
  118.                 Attribute attr = (Attribute) attrList.next();  
  119.                 System.out.println(attr.getName() + "=" + attr.getValue());  
  120.             }  
  121.   
  122.             // 遍历employee节点下所有子节点  
  123.             Iterator<?> eleIte = empEle.elementIterator();  
  124.             while (eleIte.hasNext()) {  
  125.                 Element ele = (Element) eleIte.next();  
  126.                 System.out.println("<" + ele.getName() + ">" + ele.getTextTrim());  
  127.             }  
  128.   
  129.             // 获取employee节点下的子节点sex值  
  130.             // String sex = empEle.elementTextTrim("sex");  
  131.             // System.out.println("sex:" + sex);  
  132.   
  133.         }  
  134.         System.out.println("</" + root.getName() + ">");  
  135.     }                                                                                                                                                      
  136.     public static void main(String[] args) {  
  137.         Dom4jDemo dom4j = new Dom4jDemo();  
  138.         File file = new File("e:/dom4j.xml");  
  139.         // dom4j.createXml(file);  
  140.         dom4j.parserXml(file);  
  141.     }  
  142. }  

/*修改xml文档*/ 

[html]  view plain copy print ?
  1. public static void modifyxml(){  
  2. //使用SAXReader去解析xml文件  
  3. SAXReader reader=new SAXReader();  
  4. Document document;  
  5. try {  
  6. File file =new File("C:\\workspace\\Test\\myxml.xml");  
  7. //获取document对象  
  8.        document=reader.read(file);  
  9.        //通过selectNodes寻找节点或者属性  
  10.        List list=document.selectNodes("/student/call/@show");  
  11. Iterator it=list.iterator();  
  12. while(it.hasNext()){  
  13.     //Attribute属性的操作方法  
  14.     Attribute attribute=(Attribute)it.next();  
  15.     if(attribute.getValue().equals("yes"))  
  16.     {  
  17.           
  18.         attribute.setValue("no");  
  19.     }  
  20. }  
  21. list =document.selectNodes("/student/call/name");  
  22. it=list.iterator();  
  23. while(it.hasNext()){  
  24. //标签内容的操作方法  
  25. Element nameElment=(Element)it.next();  
  26. nameElment.setText("studentname");  
  27. }  
  28. //删除某个节点是要用两层循环,因为删除当前节点必须用父节点去删除。  
  29. list=document.selectNodes("/student/call");  
  30. it=list.iterator();  
  31. while(it.hasNext()){  
  32.       //获取父节点  
  33.       Element scoreElement=(Element)it.next();  
  34.       System.out.println(scoreElement);  
  35.       @SuppressWarnings("unused")  
  36.       //获取该父节点下面的需要查找的子节点  
  37.       Iterator itera=scoreElement.elementIterator("English");  
  38.       while(itera.hasNext()){  
  39.          Element scoreEnglish=(Element)itera.next();  
  40.          if(scoreEnglish.getText().equals("77")){  
  41.          //利用父节点去删除  
  42.          scoreElement.remove(scoreEnglish);  
  43.          }  
  44.       }  
  45. }  
  46. @SuppressWarnings("unused")  
  47. /*Iterator itera=document.getRootElement().elementIterator("call");  
  48.   while(itera.hasNext()){  
  49.     Element ele=(Element)itera.next();  
  50.     System.out.println(ele);  
  51.   }*/  
  52.       
  53. OutputFormat format = OutputFormat.createPrettyPrint();  
  54. format.setEncoding("UTF-8");  
  55. XMLWriter writer;  
  56. try {  
  57.     writer = new XMLWriter(new FileWriter("myxml.xml"),format);  
  58.     writer.write(document);  
  59.     writer.close();  
  60. }catch (IOException e) {  
  61.         e.printStackTrace();  
  62. }catch (DocumentException e) {  
  63.         e.printStackTrace();  
  64. }  
  65. }  

二、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规则。
[java]  view plain copy print ?
  1. //导入jar包:jdom.jar                                                                                                                                     import java.io.File;  
  2. import java.io.FileNotFoundException;  
  3. import java.io.FileOutputStream;  
  4. import java.io.IOException;  
  5. import java.util.List;  
  6.   
  7. import org.jdom.Attribute;  
  8. import org.jdom.Comment;  
  9. import org.jdom.Document;  
  10. import org.jdom.Element;  
  11. import org.jdom.JDOMException;  
  12. import org.jdom.input.SAXBuilder;  
  13. import org.jdom.output.Format;  
  14. import org.jdom.output.XMLOutputter;  
  15.   
  16. /**  
  17.  * jdom生成与解析XML文档 
  18.  */  
  19. public class JdomDemo {  
  20.   
  21.     Document document = new Document();  
  22.     /** 
  23.      * 利用JDom进行xml文档的写入操作 
  24.      */  
  25.     public void createXml(File file) {  
  26.   
  27.         // 1.创建元素 及 设置为根元素  
  28.         Element employees = new Element("employees");  
  29.         document.setContent(employees);  
  30.   
  31.         // 2.创建注释 及 设置到根元素上  
  32.         Comment commet = new Comment("this is my comment");  
  33.         employees.addContent(commet);  
  34.   
  35.         // 3.创建元素  
  36.         Element element1 = new Element("employee");  
  37.   
  38.         // 3.1 设置元素的属性名及属性值  
  39.         element1.setAttribute(new Attribute("id""0001"));  
  40.   
  41.         // 3.2 创建元素的属性名及属性值  
  42.         Attribute nameAttr = new Attribute("name""wanglp");  
  43.   
  44.         // 3.3 设置元素名及文本  
  45.         Element sexEle = new Element("sex");  
  46.         sexEle.setText("m");  
  47.         // 设置到上层元素上  
  48.         element1.addContent(sexEle);  
  49.   
  50.         // 设置元素  
  51.         Element ageEle = new Element("age");  
  52.         ageEle.setText("22");  
  53.         element1.addContent(ageEle);  
  54.   
  55.         // 设置为根元素的子元素  
  56.         employees.addContent(element1);  
  57.         // 将元素属性设置到元素上  
  58.         element1.setAttribute(nameAttr);  
  59.   
  60.         // 3.创建元素  
  61.         Element element2 = new Element("employee");  
  62.   
  63.         // 3.1 设置元素的属性名及属性值  
  64.         element2.setAttribute(new Attribute("id""0002"));  
  65.   
  66.         // 3.2 创建元素的属性名及属性值  
  67.         Attribute name2Attr = new Attribute("name""fox");  
  68.   
  69.         // 3.3 设置元素名及文本  
  70.         Element sex2Ele = new Element("sex");  
  71.         sex2Ele.setText("f");  
  72.         // 设置到上层元素上  
  73.         element2.addContent(sex2Ele);  
  74.   
  75.         // 设置元素  
  76.         Element age2Ele = new Element("age");  
  77.         age2Ele.setText("21");  
  78.         element2.addContent(age2Ele);  
  79.   
  80.         // 设置为根元素的子元素  
  81.         employees.addContent(element2);  
  82.         // 将元素属性设置到元素上  
  83.         element2.setAttribute(name2Attr);  
  84.   
  85.         Element element3 = new Element("employee");  
  86.         element3.setText("title");  
  87.         element3.addContent(new Element("name").addContent(new Element("hello")));  
  88.         employees.addContent(element3);  
  89.   
  90.         // 设置xml文档输出的格式  
  91.         Format format = Format.getPrettyFormat();  
  92.         XMLOutputter out = new XMLOutputter(format);  
  93.         // 将得到的xml文档输出到文件流中  
  94.         try {  
  95.             out.output(document, new FileOutputStream(file));  
  96.         } catch (FileNotFoundException e) {  
  97.             e.printStackTrace();  
  98.         } catch (IOException e) {  
  99.             e.printStackTrace();  
  100.         }  
  101.     }  
  102.   
  103.     /** 
  104.      * 利用JDom进行xml文档的读取操作 
  105.      */  
  106.     public void parserXml(File file) {  
  107.         // 建立解析器  
  108.         SAXBuilder builder = new SAXBuilder();  
  109.         try {  
  110.             // 将解析器与文档关联  
  111.             document = builder.build(file);  
  112.         } catch (JDOMException e1) {  
  113.             e1.printStackTrace();  
  114.         } catch (IOException e1) {  
  115.             e1.printStackTrace();  
  116.         }  
  117.         // 读取根元素  
  118.         Element root = document.getRootElement();  
  119.         // 输出根元素的名字  
  120.         System.out.println("<" + root.getName() + ">");  
  121.   
  122.         // 读取元素集合  
  123.         List<?> employeeList = root.getChildren("employee");  
  124.         for (int i = 0; i < employeeList.size(); i++) {  
  125.             Element ele = (Element) employeeList.get(i);  
  126.             // 得到元素的名字  
  127.             System.out.println("<" + ele.getName() + ">");  
  128.   
  129.             // 读取元素的属性集合  
  130.             List<?> empAttrList = ele.getAttributes();  
  131.             for (int j = 0; j < empAttrList.size(); j++) {  
  132.                 Attribute attrs = (Attribute) empAttrList.get(j);  
  133.                 // 将属性的名字和值 并 输出  
  134.                 String name = attrs.getName();  
  135.                 String value = (String) attrs.getValue();  
  136.                 System.out.println(name + "=" + value);  
  137.             }  
  138.             try {  
  139.                 Element sex = ele.getChild("sex");  
  140.                 System.out.println("<sex>" + sex.getText());  
  141.                 Element age = ele.getChild("age");  
  142.                 System.out.println("<age>" + age.getText());  
  143.             } catch (NullPointerException e) {  
  144.                 System.out.println(ele.getTextTrim());  
  145.                 Element name = ele.getChild("name");  
  146.                 System.out.println("<name>" + name.getName());  
  147.                   
  148.             }  
  149.             System.out.println("</employee>");  
  150.         }  
  151.         System.out.println("</employees>");  
  152.     }  
  153.   
  154.     /** 
  155.      * 测试 
  156.      */  
  157.     public static void main(String[] args) {  
  158.   
  159.         JdomDemo jdom = new JdomDemo();  
  160.         File file = new File("E://jdom.xml");  
  161.         jdom.createXml(file);  
  162.         jdom.parserXml(file);  
  163.     }  
  164. }  

三、DOM

       1、原理:DOM是基于树的结构,解析器读入-整个-文档,然后构建一个驻留内存的树结构,使用 DOM 接 口来操作这个树结构。
       2、优点:a、由于整棵树在内存中,便于操作,可以对xml文档随机访问
                         b、可以对xml文档进行删除、修改、重新排列等多种功能;访问效率高
                         c、较sax,dom使用也更简单。
       3、缺点:a、整个文档必须一次性解析完(无用的节点也会解析),浪费时间和空间.
                       b、由于整个文档都需要载入内存,对于大文档成本高
       4、 场合:小型xml文档;一旦解析了文档还需多次访问这些数据;
[java]  view plain copy print ?
  1. import java.io.File;  
  2. import java.io.FileNotFoundException;  
  3. import java.io.FileOutputStream;  
  4. import java.io.IOException;  
  5. import java.io.PrintWriter;  
  6. import javax.xml.parsers.DocumentBuilder;  
  7. import javax.xml.parsers.DocumentBuilderFactory;  
  8. import javax.xml.parsers.ParserConfigurationException;  
  9. import javax.xml.transform.OutputKeys;  
  10. import javax.xml.transform.Transformer;  
  11. import javax.xml.transform.TransformerConfigurationException;  
  12. import javax.xml.transform.TransformerException;  
  13. import javax.xml.transform.TransformerFactory;  
  14. import javax.xml.transform.dom.DOMSource;  
  15. import javax.xml.transform.stream.StreamResult;  
  16. import org.w3c.dom.Attr;  
  17. import org.w3c.dom.Document;  
  18. import org.w3c.dom.Element;  
  19. import org.w3c.dom.Node;  
  20. import org.w3c.dom.NodeList;  
  21. import org.xml.sax.SAXException;  
  22.   
  23. /** 
  24.  * DOM生成与解析XML文档 
  25.  *  
  26.  * @author 莫小哆_ly 2012-2-20 
  27.  */  
  28. public class DomDemo {  
  29.   
  30.     /* 
  31.      * 解析器读入整个文档,然后构建一个驻留内存的树结构, 
  32.      *  
  33.      * 然后代码就可以使用 DOM 接口来操作这个树结构。 
  34.      *  
  35.      * 优点:整个文档树在内存中,便于操作;支持删除、修改、重新排列等多种功能; 
  36.      *  
  37.      * 缺点:将整个文档调入内存(包括无用的节点),浪费时间和空间; 
  38.      *  
  39.      * 使用场合:一旦解析了文档还需多次访问这些数据;硬件资源充足(内存、CPU) 
  40.      */  
  41.   
  42.     // 表示整个HTML或 XML文档。从概念上讲,它是文档树的根,并提供对文档数据的基本访问  
  43.     private Document document;  
  44.   
  45.     /** 
  46.      * 创建DOM树 
  47.      *  
  48.      * 要读入一个XML文档,首先要一个DocumentBuilder对象 
  49.      */  
  50.     public void init() {  
  51.         // 获取 DocumentBuilderFactory 的新实例  
  52.         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();  
  53.         // 使用当前配置的参数创建一个新的 DocumentBuilder 实例  
  54.         DocumentBuilder builder = null;  
  55.         try {  
  56.             builder = factory.newDocumentBuilder();  
  57.         } catch (ParserConfigurationException e) {  
  58.             e.printStackTrace();  
  59.         }  
  60.         // 获取 DOM Document 对象的一个新实例来生成一个 DOM 树  
  61.         this.document = builder.newDocument();  
  62.     }  
  63.   
  64.     /** 
  65.      * xml文档的写入操作 
  66.      *  
  67.      * @param file 
  68.      */  
  69.     public void createXml(File file) {  
  70.   
  71.         // 创建DOM树  
  72.         this.init();  
  73.   
  74.         // 创建XML根节点employees  
  75.         Element root = this.document.createElement("employees");  
  76.         // Adds the node newChild to the end of the list of children of this  
  77.         // node.  
  78.         // If the newChild is already in the tree, it is first removed.  
  79.         this.document.appendChild(root);  
  80.   
  81.         // 1.创建根节点的子节点employee  
  82.         Element employee = this.document.createElement("employee");  
  83.   
  84.         // 向根节点添加属性节点  
  85.         Attr id = this.document.createAttribute("id");  
  86.         id.setNodeValue("0001");  
  87.         // 把属性节点对象,追加到达employee节点;  
  88.         employee.setAttributeNode(id);  
  89.   
  90.         // 声明employee的子节点name  
  91.         Element name = this.document.createElement("name");  
  92.         // 向XML文件name节点追加数据  
  93.         name.appendChild(this.document.createTextNode("wanglp"));  
  94.         // 把子节点的属性追加到employee子节点中元素中  
  95.         employee.appendChild(name);  
  96.   
  97.         // 声明employee的子节点sex  
  98.         Element sex = this.document.createElement("sex");  
  99.         // 向XML文件sex节点追加数据  
  100.         sex.appendChild(this.document.createTextNode("m"));  
  101.         // 把子节点的属性追加到employee子节点中元素中  
  102.         employee.appendChild(sex);  
  103.   
  104.         // 声明employee的子节点age  
  105.         Element age = this.document.createElement("age");  
  106.         // 向XML文件age节点追加数据  
  107.         age.appendChild(this.document.createTextNode("25"));  
  108.         // 把子节点的属性追加到employee子节点中元素中  
  109.         employee.appendChild(age);  
  110.   
  111.         // employee节点定义完成,追加到root  
  112.         root.appendChild(employee);  
  113.   
  114.         // 2.创建根节点的子节点employee  
  115.         employee = this.document.createElement("employee");  
  116.   
  117.         // 向根节点添加属性节点  
  118.         id = this.document.createAttribute("id");  
  119.         id.setNodeValue("0002");  
  120.         // 把属性节点对象,追加到达employee节点;  
  121.         employee.setAttributeNode(id);  
  122.   
  123.         // 声明employee的子节点name  
  124.         name = this.document.createElement("name");  
  125.         // 向XML文件name节点追加数据  
  126.         name.appendChild(this.document.createTextNode("huli"));  
  127.         // 把子节点的属性追加到employee子节点中元素中  
  128.         employee.appendChild(name);  
  129.   
  130.         // 声明employee的子节点sex  
  131.         sex = this.document.createElement("sex");  
  132.         // 向XML文件sex节点追加数据  
  133.         sex.appendChild(this.document.createTextNode("f"));  
  134.         // 把子节点的属性追加到employee子节点中元素中  
  135.         employee.appendChild(sex);  
  136.   
  137.         // 声明employee的子节点age  
  138.         age = this.document.createElement("age");  
  139.         // 向XML文件age节点追加数据  
  140.         age.appendChild(this.document.createTextNode("12"));  
  141.         // 把子节点的属性追加到employee子节点中元素中  
  142.         employee.appendChild(age);  
  143.   
  144.         // employee节点定义完成,追加到root  
  145.         root.appendChild(employee);  
  146.   
  147.         // 获取 TransformerFactory 的新实例。  
  148.         TransformerFactory tf = TransformerFactory.newInstance();  
  149.         // 创建执行从 Source 到 Result 的复制的新 Transformer。能够将源树转换为结果树  
  150.         Transformer transformer = null;  
  151.         try {  
  152.             transformer = tf.newTransformer();  
  153.         } catch (TransformerConfigurationException e) {  
  154.             e.printStackTrace();  
  155.         }  
  156.   
  157.         // 设置转换中实际的输出属性  
  158.         // 指定首选的字符编码  
  159.         transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");  
  160.         // indent="yes"|"no".指定了当输出结果树时,Transformer是否可以添加额外的空白  
  161.         transformer.setOutputProperty(OutputKeys.INDENT, "yes");  
  162.         // 声明文件流  
  163.         PrintWriter pw = null;  
  164.         try {  
  165.             pw = new PrintWriter(new FileOutputStream(file));  
  166.         } catch (FileNotFoundException e) {  
  167.             e.printStackTrace();  
  168.             System.out.println("文件没有找到!");  
  169.         }  
  170.         // 充当转换结果的持有者,可以为 XML、纯文本、HTML 或某些其他格式的标记  
  171.         StreamResult result = new StreamResult(pw);  
  172.         // DOMSource implements Source  
  173.         DOMSource source = new DOMSource(document);  
  174.   
  175.         try {  
  176.             // 将 XML Source 转换为 Result  
  177.             transformer.transform(source, result);  
  178.         } catch (TransformerException e) {  
  179.             e.printStackTrace();  
  180.             System.out.println("生成XML文件失败!");  
  181.         }  
  182.         System.out.println("生成XML文件成功!");  
  183.     }  
  184.   
  185.     /** 
  186.      * xml文档的读取操作 
  187.      */  
  188.     public void parserXml(File file) {  
  189.         // 获取 DocumentBuilderFactory 的新实例  
  190.         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();  
  191.         // 使用当前配置的参数创建一个新的 DocumentBuilder 实例  
  192.         DocumentBuilder builder;  
  193.         try {  
  194.             builder = factory.newDocumentBuilder();  
  195.             // 将给定 URI的内容解析为一个 XML文档,并且返回一个新的 DOM Document 对象  
  196.             document = builder.parse(file);  
  197.         } catch (ParserConfigurationException e) {  
  198.             e.printStackTrace();  
  199.         } catch (SAXException e) {  
  200.             e.printStackTrace();  
  201.         } catch (IOException e) {  
  202.             e.printStackTrace();  
  203.         }  
  204.         // 获得文档根元素对对象;  
  205.         Element root = document.getDocumentElement();  
  206.         // 获得文档根元素下一级子元素所有元素;  
  207.         NodeList nodeList = root.getChildNodes();  
  208.   
  209.         System.out.print("<employees>");  
  210.         System.out.println(root.getNodeName());  
  211.   
  212.         if (null != root) {  
  213.             for (int i = 0; i < nodeList.getLength(); i++) {  
  214.                 Node child = nodeList.item(i);  
  215.   
  216.                 // 输出child的属性;  
  217.                 System.out.print("<test>");  
  218.                 System.out.println(child);  
  219.   
  220.                 if (child.getNodeType() == Node.ELEMENT_NODE) {  
  221.                     System.out.print("<id>");  
  222.                     System.out.println(child.getAttributes().getNamedItem("id").getNodeValue());  
  223.                 }  
  224.                 for (Node node = child.getFirstChild(); node != null; node = node.getNextSibling()) {  
  225.                     if (node.getNodeType() == Node.ELEMENT_NODE) {  
  226.                         if ("name".equals(node.getNodeName())) {  
  227.                             System.out.print("<name>");  
  228.                             System.out.println(node.getFirstChild().getNodeValue());  
  229.                         }  
  230.                     }  
  231.                     if (node.getNodeType() == Node.ELEMENT_NODE) {  
  232.                         if ("sex".equals(node.getNodeName())) {  
  233.                             System.out.print("<sex>");  
  234.                             System.out.println(node.getFirstChild().getNodeValue());  
  235.                         }  
  236.                     }  
  237.                     if (node.getNodeType() == Node.ELEMENT_NODE) {  
  238.                         if ("age".equals(node.getNodeName())) {  
  239.                             System.out.print("<age>");  
  240.                             System.out.println(node.getFirstChild().getNodeValue());  
  241.                         }  
  242.                     }  
  243.                     if (node.getNodeType() == Node.ELEMENT_NODE) {  
  244.                         if ("email".equals(node.getNodeName())) {  
  245.                             System.out.print("<email>");  
  246.                             System.out.println(node.getFirstChild().getNodeValue());  
  247.                         }  
  248.                     }  
  249.                 }  
  250.             }  
  251.         }  
  252.         System.out.println("解析完毕");  
  253.     }  
  254.   
  255.     /** 
  256.      * 测试 
  257.      */  
  258.     public static void main(String[] args) {  
  259.   
  260.         // 为什么有类似于这样东西[#text:]  
  261.         // 原因是XML文件元素之间的空白字符也是一个元素,<employees></employees>包含的空白  
  262.         DomDemo dom = new DomDemo();  
  263.         File file = new File("E://dom.xml");  
  264.           
  265.         dom.createXml(file);  
  266.         dom.parserXml(file);  
  267.     }  
  268. }  

四、SAX

       1、原理:SAX类似流媒体,它基于事件驱动,当解析器发现元素开始、元素结束、文本、文档的开始或结束 等时,发送事件,程序员编写响应这些事件的代码,保存数据。无需将整个文档载入内存,使用者 只需要监听自己感兴趣的事件即可。
       2、优点:a、无需将整个xml文档载入内存,因此消耗内存少
                         b、SAX解析器代码比DOM解析器代码小,适于Applet,下载。
                        c、可以注册多个ContentHandler
       3、缺点:a、不能随机的访问xml中的节点
                        b、只支持读,不能修改文档。非持久,事件过后,若没保存数据,那么数据就丢了
                        c、无状态性;从事件中只能得到文本,但不知该文本属于哪个元素
      4、场合:大型xml文档;Applet;只需XML文档的少量内容,很少回头访问;
[java]  view plain copy print ?
  1. import java.io.File;  
  2. import javax.xml.parsers.SAXParser;  
  3. import javax.xml.parsers.SAXParserFactory;  
  4. import org.xml.sax.Attributes;  
  5. import org.xml.sax.SAXException;  
  6. import org.xml.sax.helpers.DefaultHandler;  
  7.   
  8. /** 
  9.  * startDocument(),endDocument(),startElement(),endElement(),characters() 
  10.  */  
  11. public class SAXParseDemo extends DefaultHandler {  
  12.   
  13.     private String tagValue; // 标签值  
  14.   
  15.     // 开始解析XML文件  
  16.     public void startDocument() throws SAXException {  
  17.         System.out.println("开始解析");  
  18.     }  
  19.   
  20.     // 结束解析XML文件  
  21.     public void endDocument() throws SAXException {  
  22.         System.out.println("结束解析");  
  23.     }  
  24.   
  25.     // 解析元素  
  26.     /** 
  27.      * 开始解析一个元素 
  28.      * @param qName 标签名 
  29.      * @param attributes 属性 
  30.      */  
  31.     @Override  
  32.     public void startElement(String uri, String localName, String qName, Attributes attributes)  
  33.             throws SAXException {  
  34.         System.out.println(qName + "开始");  
  35.         // 属性  
  36.         if (attributes != null && attributes.getLength() != 0) {  
  37.             System.out.println("属性:");  
  38.             for (int i = 0; i < attributes.getLength(); i++) {  
  39.                 System.out.print(attributes.getQName(i) + "="); // 属性名  
  40.                 System.out.print(attributes.getValue(i) + " "); // 属性值  
  41.             }  
  42.             System.out.println();  
  43.         }  
  44.     }  
  45.   
  46.     /** 
  47.      * 结束一个元素的解析 遇到结束标签时调用此方法 通常在此方法对标签取值并处理 
  48.      */  
  49.     @Override  
  50.     public void endElement(String uri, String localName, String qName) throws SAXException {  
  51.         System.out.println(qName + "标签值:" + tagValue);  
  52.         System.out.println(qName + "结束");  
  53.     }  
  54.   
  55.     // 所有xml文件中的字符都会放到ch[]中  
  56.     public void characters(char ch[], int start, int length) throws SAXException {  
  57.         tagValue = new String(ch, start, length).trim();  
  58.     }  
  59.   
  60.     public static void main(String[] args) {  
  61.         File file = new File("src/cn/main/example/demo.xml");  
  62.         SAXParserFactory saxParFac = SAXParserFactory.newInstance();  
  63.         try {  
  64.             SAXParser saxParser = saxParFac.newSAXParser();  
  65.             saxParser.parse(file, new SAXParseDemo());  
  66.         } catch (Exception e) {  
  67.             e.printStackTrace();  
  68.         }  
  69.   
  70.     }  
  71. }  

五、资料(关于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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值