DOM4J与JDOM解析xml文档
1. JDOM方式解析XML
JDOM并不是java官方解析xml文档的方法,所以在进行文档解析前,需要下载JDOM的jar包:http://www.jdom.org/downloads/;并将其路径添加到当前项目中,或者把jar包拷贝到当前项目中。
同样地使用前面的books.xml文档进行解析:
books.xml:
<?xml version="1.0" encoding="UTF-8"?> <bookstore> <book category="COOKING"> <title lang="en">Everyday Italian</title> <author>Giada De Laurentiis</author> <year>2005</year> <price>30.0</price> </book> <book category="CHILDREN"> <title lang="en">Harry Potter</title> <author>J K. Rowling</author> <year>2005</year> <price>29.99</price> </book> <book category="WEB"> <title lang="en">Learing XML</title> <author>Erik T. Ray</author> <year>2010</year> <price>48.99</price> </book> </bookstore>
Books抽象类:
1 package demo; 2 3 /** 4 * 根据xml “books”文档,新创建Books类 5 * Created by luts on 2015/12/21. 6 */ 7 public class Books { 8 private String category; 9 private String title; 10 private String language; 11 private String author; 12 private String year; 13 private String price; 14 15 public String getCategory() { 16 return category; 17 } 18 19 public void setCategory(String category) { 20 this.category = category; 21 } 22 23 public String getTitle() { 24 return title; 25 } 26 27 public void setTitle(String title) { 28 this.title = title; 29 } 30 31 public String getLanguage() { 32 return language; 33 } 34 35 public void setLanguage(String language) { 36 this.language = language; 37 } 38 39 public String getAuthor() { 40 return author; 41 } 42 43 public void setAuthor(String author) { 44 this.author = author; 45 } 46 47 public String getYear() { 48 return year; 49 } 50 51 public void setYear(String year) { 52 this.year = year; 53 } 54 55 public String getPrice() { 56 return price; 57 } 58 59 public void setPrice(String price) { 60 this.price = price; 61 } 62 }
JDOM解析xml文档:
1 package demo; 2 3 import org.jdom2.Attribute; 4 import org.jdom2.Element; 5 import org.jdom2.JDOMException; 6 import org.jdom2.input.JDOMParseException; 7 import org.jdom2.input.SAXBuilder; 8 import org.jdom2.Document; 9 10 11 import javax.imageio.IIOException; 12 import java.io.*; 13 import java.util.ArrayList; 14 import java.util.List; 15 16 /** 17 * Created by luts on 2015/12/21. 18 */ 19 public class JDOMTest { 20 private static ArrayList<Books> booksList = new ArrayList<Books>(); 21 22 public static void main(String[]args){ 23 //创建一个SAXBuilder的对象 24 SAXBuilder saxBuilder = new SAXBuilder(); 25 InputStream inputStream; 26 try { 27 //创建一个输入流,将xml文件加载到输入流中 28 inputStream = new FileInputStream("books.xml"); 29 InputStreamReader isr = new InputStreamReader(inputStream, "UTF-8"); 30 //通过saxBuilder的build方法,将输入流加载到saxBuilder中 31 Document document = saxBuilder.build(isr); 32 //通过document对象获取xml文件的根节点 33 Element rootElement = document.getRootElement(); 34 //获取节点下的的子节点的List结合 35 List<Element> bookList = rootElement.getChildren(); 36 //继续解析 37 for (Element book : bookList){ 38 Books bookEntry = new Books(); 39 System.out.println("-------------开始解析第" + (bookList.indexOf(book) + 1) + "书------------"); 40 //解析book的属性集合 41 List<Attribute> attrList = book.getAttributes(); 42 //知道节点下的属性名称时,获取节点值 43 //book.getAttribute("category"); 44 for (Attribute attr : attrList){ 45 46 //获取属性名 47 String attrName = attr.getName(); 48 //获取属性值 49 String attrValue = attr.getValue(); 50 System.out.println("属性名: " + attrName + "----属性值:" + attrValue); 51 if (attrName.equals("category")) { 52 bookEntry.setCategory(attrValue); 53 } 54 } 55 56 //对book节点的子节点名以及节点值的遍历 57 List<Element> bookChilds = book.getChildren(); 58 for (Element child : bookChilds){ 59 System.out.println("节点名: " + child.getName() + "----属性值: "+ child.getValue()); 60 if (child.getName().equals("title")){ 61 62 bookEntry.setTitle(child.getValue()); 63 //知道节点下的属性名称时,获取节点值 64 String lang = child.getAttributeValue("lang"); 65 bookEntry.setLanguage(lang); 66 System.out.println("title 包含的属性 lang 的属性值为: " + child.getAttributeValue("lang")); 67 /* List<Attribute> childAttrList = child.getAttributes(); 68 for (Attribute childAttr : childAttrList){ 69 70 //获取属性名 71 String childAttrName = childAttr.getName(); 72 //获取属性值 73 String childAttrValue = childAttr.getValue(); 74 System.out.println("属性名: " + childAttrName + "----属性值:" + childAttrValue); 75 if (childAttrName.equals("lang")) { 76 bookEntry.setLanguage(childAttrName); 77 } 78 }*/ 79 } 80 else if (child.getName().equals("author")){ 81 bookEntry.setAuthor(child.getValue()); 82 } 83 else if (child.getName().equals("year")){ 84 bookEntry.setYear(child.getValue()); 85 } 86 else if (child.getName().equals("price")){ 87 bookEntry.setPrice(child.getValue()); 88 } 89 } 90 System.out.println("------结束解析第" + (bookList.indexOf(book) + 1) + "本书-------"); 91 booksList.add(bookEntry); 92 bookEntry = null; 93 System.out.println(booksList.size()); 94 System.out.println(booksList.get(0).getCategory()); 95 System.out.println(booksList.get(0).getTitle()); 96 System.out.println(booksList.get(0).getAuthor()); 97 System.out.println(booksList.get(0).getLanguage()); 98 } 99 } 100 catch (FileNotFoundException e){ 101 e.printStackTrace(); 102 } 103 catch (JDOMException e){ 104 e.printStackTrace(); 105 } 106 catch (IOException e){ 107 e.printStackTrace(); 108 } 109 110 } 111 }
测试结果:
-------------开始解析第1书------------ 属性名: category----属性值:COOKING 节点名: title----属性值: Everyday Italian title 包含的属性 lang 的属性值为: en 节点名: author----属性值: Giada De Laurentiis 节点名: year----属性值: 2005 节点名: price----属性值: 30.0 ------结束解析第1本书------- 1 COOKING Everyday Italian Giada De Laurentiis en -------------开始解析第2书------------ 属性名: category----属性值:CHILDREN 节点名: title----属性值: Harry Potter title 包含的属性 lang 的属性值为: en 节点名: author----属性值: J K. Rowling 节点名: year----属性值: 2005 节点名: price----属性值: 29.99 ------结束解析第2本书------- 2 COOKING Everyday Italian Giada De Laurentiis en -------------开始解析第3书------------ 属性名: category----属性值:WEB 节点名: title----属性值: Learing XML title 包含的属性 lang 的属性值为: en 节点名: author----属性值: Erik T. Ray 节点名: year----属性值: 2010 节点名: price----属性值: 48.99 ------结束解析第3本书------- 3 COOKING Everyday Italian Giada De Laurentiis en
2. DOM4J方法解析xml
同样的,因为DOM4J不是java官方定义的xml文档解析方法,所以得下载DOM4J的jar包:http://www.dom4j.org/dom4j-1.6.1/
实例:
book.xml
1 <?xml version="1.0" encoding="UTF-8"?> 2 <bookstore> 3 <book category="COOKING"> 4 <title lang="en">Everyday Italian</title> 5 <author>Giada De Laurentiis</author> 6 <year>2005</year> 7 <price>30.0</price> 8 </book> 9 <book category="CHILDREN"> 10 <title lang="en">Harry Potter</title> 11 <author>J K. Rowling</author> 12 <year>2005</year> 13 <price>29.99</price> 14 </book> 15 <book category="WEB"> 16 <title lang="en">Learing XML</title> 17 <author>Erik T. Ray</author> 18 <year>2010</year> 19 <price>48.99</price> 20 </book> 21 </bookstore>
Book.java
1 package demo; 2 3 /** 4 * 根据xml “books”文档,新创建Books类 5 * Created by luts on 2015/12/21. 6 */ 7 public class Books { 8 private String category; 9 private String title; 10 private String language; 11 private String author; 12 private String year; 13 private String price; 14 15 public String getCategory() { 16 return category; 17 } 18 19 public void setCategory(String category) { 20 this.category = category; 21 } 22 23 public String getTitle() { 24 return title; 25 } 26 27 public void setTitle(String title) { 28 this.title = title; 29 } 30 31 public String getLanguage() { 32 return language; 33 } 34 35 public void setLanguage(String language) { 36 this.language = language; 37 } 38 39 public String getAuthor() { 40 return author; 41 } 42 43 public void setAuthor(String author) { 44 this.author = author; 45 } 46 47 public String getYear() { 48 return year; 49 } 50 51 public void setYear(String year) { 52 this.year = year; 53 } 54 55 public String getPrice() { 56 return price; 57 } 58 59 public void setPrice(String price) { 60 this.price = price; 61 } 62 }
DOM4J解析xml文档
1 package demo; 2 3 import jdk.internal.org.xml.sax.Attributes; 4 import org.dom4j.Attribute; 5 import org.dom4j.Document; 6 import org.dom4j.DocumentException; 7 import org.dom4j.Element; 8 import org.dom4j.io.SAXReader; 9 10 import java.io.File; 11 import java.util.ArrayList; 12 import java.util.Iterator; 13 import java.util.List; 14 15 /** 16 * 使用DOM4J方法解析xml文档 17 * Created by luts on 2015/12/21. 18 */ 19 public class DOM4JTest { 20 private static ArrayList<Books>bookList = new ArrayList<Books>(); 21 22 public static void main(String[]args){ 23 24 //创建SAXReader的对象 25 SAXReader reader = new SAXReader(); 26 try { 27 //通过reader对象的read方法加载books.xml文档,获取document对象 28 Document document = reader.read(new File("books.xml")); 29 //通过document对象获取根节点bookstore 30 Element bookStore = document.getRootElement(); 31 //通过element对象的elementIterator方法获取迭代器 32 Iterator it = bookStore.elementIterator(); 33 while (it.hasNext()){ 34 Books bookAdd = new Books(); 35 System.out.println("-------开始解析某一本书-----------"); 36 Element book = (Element) it.next(); 37 //获取book的属性名以及属性值 38 List<Attribute> bookAttrs = book.attributes(); 39 for (Attribute attr: bookAttrs){ 40 System.out.println("属性名: " + attr.getName() + "----属性值: " + attr.getValue()); 41 if (attr.getName().equals("category")){ 42 bookAdd.setCategory(attr.getValue()); 43 } 44 } 45 Iterator itt = book.elementIterator(); 46 while (itt.hasNext()){ 47 Element bookChild = (Element) itt.next(); 48 System.out.println("节点名: " + bookChild.getName() + "----节点值:" + bookChild.getStringValue()); 49 if (bookChild.getName().equals("title")){ 50 bookAdd.setTitle(bookChild.getStringValue()); 51 List<Attribute> bookChildAttrs = bookChild.attributes(); 52 for (Attribute attrChild: bookChildAttrs){ 53 System.out.println("属性名: " + attrChild.getName() + "----属性值: " + attrChild.getValue()); 54 bookAdd.setLanguage(attrChild.getValue()); 55 } 56 } 57 else if (bookChild.getName().equals("author")){ 58 bookAdd.setAuthor(bookChild.getStringValue()); 59 } 60 else if (bookChild.getName().equals("year")){ 61 bookAdd.setYear(bookChild.getStringValue()); 62 } 63 else if (bookChild.getName().equals("price")){ 64 bookAdd.setPrice(bookChild.getStringValue()); 65 } 66 67 68 } 69 System.out.println("------遍历完某一本书---------"); 70 bookList.add(bookAdd); 71 bookAdd = null; 72 } 73 74 System.out.println(); 75 76 System.out.println("队列中有" + bookList.size() + "本书\n" + "------开始遍历队列中的书本---------"); 77 78 Iterator listIt = bookList.iterator(); 79 for (Books bookitem : bookList){ 80 System.out.println("第" +( bookList.indexOf(bookitem) + 1) + "本书包含的属性为: "); 81 System.out.println(bookitem.getCategory()); 82 System.out.println(bookitem.getLanguage()); 83 System.out.println(bookitem.getTitle()); 84 System.out.println(bookitem.getAuthor()); 85 System.out.println(bookitem.getYear()); 86 System.out.println(bookitem.getPrice()); 87 } 88 89 } 90 catch (DocumentException E){ 91 E.printStackTrace(); 92 } 93 } 94 }
结果:
-------开始解析某一本书----------- 属性名: category----属性值: COOKING 节点名: title----节点值:Everyday Italian 属性名: lang----属性值: en 节点名: author----节点值:Giada De Laurentiis 节点名: year----节点值:2005 节点名: price----节点值:30.0 ------遍历完某一本书--------- -------开始解析某一本书----------- 属性名: category----属性值: CHILDREN 节点名: title----节点值:Harry Potter 属性名: lang----属性值: en 节点名: author----节点值:J K. Rowling 节点名: year----节点值:2005 节点名: price----节点值:29.99 ------遍历完某一本书--------- -------开始解析某一本书----------- 属性名: category----属性值: WEB 节点名: title----节点值:Learing XML 属性名: lang----属性值: en 节点名: author----节点值:Erik T. Ray 节点名: year----节点值:2010 节点名: price----节点值:48.99 ------遍历完某一本书--------- 队列中有3本书 ------开始遍历队列中的书本--------- 第1本书包含的属性为: COOKING en Everyday Italian Giada De Laurentiis 2005 30.0 第2本书包含的属性为: CHILDREN en Harry Potter J K. Rowling 2005 29.99 第3本书包含的属性为: WEB en Learing XML Erik T. Ray 2010 48.99
3. 4 种解析方法的比较
1)DOM(Document Object Model)
文档对象模型分析方式。以层次结构(类似于树型)来组织节点和信息片段,映射XML文档的结构,允许获取和操作文档的任意部分。是W3C的官方标准。
优点:
1、允许应用程序对数据和结构做出更改。
2、访问是双向的,可以在任何时候在树中上下导航,获取和操作任意部分的数据。
缺点:
1、通常需要加载整个XML文档来构造层次结构,消耗资源大
2)SAX(Simple API for XML)
流模型中的推模型分析方式。通过事件驱动,每发现一个节点就引发一个事件,通过回调方法完成解析工作,解析XML文档的逻辑需要应用程序完成。
优点:
1、不需要等待所有数据都被处理,分析就能立即开始。
2、只在读取数据时检查数据,不需要保存在内存中。
3、可以在某个条件得到满足时停止解析,不必解析整个文档。
4、效率和性能较高,能解析大于系统内存的文档。
缺点:
1、需要应用程序自己负责TAG的处理逻辑(例如维护父/子关系等),使用麻烦。
2、单向导航,很难同时访问同一文档的不同部分数据,不支持XPath。
3)JDOM(Java-based Document Object Model)
Java特定的文档对象模型。自身不包含解析器,使用SAX。
优点:
1、使用具体类而不是接口,简化了DOM的API。
2、大量使用了Java集合类,方便了Java开发人员。
缺点:
1、没有较好的灵活性。
2、性能较差。
4)DOM4J(Document Object Model for Java)
简单易用,采用Java集合框架,并完全支持DOM、SAX和JAXP。
优点:
1、大量使用了Java集合类,方便Java开发人员,同时提供一些提高性能的替代方法。
2、支持XPath。
3、有很好的性能。
缺点:
1、大量使用了接口,API较为复杂