dom4j 是一种解析 XML 文档的开放源代码 XML 框架。
本文主要记载了一些简单的使用方法。一、xml文件的解析
dom4j既可以解析普通的xml文件,也可以解析一个InputStream,先看看xml文件长什么样子:
1 Java编程思想 80 张三 2 三国演义 30 罗贯中 3 红楼梦 35 曹雪芹 4 西游记 25 吴承恩 5 水浒传 30 施耐庵
通过读取这一段xml文件并解析,将xml文件中的内容存储到javabean中。
private Listbs; private Book b; //读取xml文件获得Document对象 @Test public void test1(){ try { //1.读取xml文件,获取document对象 SAXReader reader = new SAXReader(); Document document = reader.read(new File("F:\\test\\books.xml")); //2.获取根节点 Element root = document.getRootElement(); bs = new ArrayList (); //3.迭代,获取根节点的所有子节点 for (Iterator es = root.elementIterator(); es.hasNext();) { Element e = es.next(); b = new Book(); //4.再次迭代,获取子节点的子节点 for (Iterator e_son = e.elementIterator();e_son.hasNext();) { Element ee = e_son.next(); if(ee.getName().equals("id")){ b.setId(Integer.parseInt(ee.getText().toString())); }else if(ee.getName().equals("name")){ b.setName(ee.getText()); }else if(ee.getName().equals("price")){ b.setPrice(Integer.parseInt(ee.getText())); }else if(ee.getName().equals("auhtor")){ b.setAuthor(ee.getText()); } } bs.add(b); } } catch (DocumentException e) { e.printStackTrace(); } for (Book bk : bs) { System.out.println(bk.getName()); } }
Book.java
public class Book { private int id; private String name; private int price; private String author; private Detail detail; private Attribute attribute; public Attribute getAttribute() { return attribute; } public void setAttribute(Attribute attribute) { this.attribute = attribute; } public Detail getDetail() { return detail; } public void setDetail(Detail detail) { this.detail = detail; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getPrice() { return price; } public void setPrice(int price) { this.price = price; } public String getAuthor() { return author; } public void setAuthor(String author) { this.author = author; }}
Attribute.java
public class Attribute { private String category; private String edition; public String getCategory() { return category; } public void setCategory(String category) { this.category = category; } public String getEdition() { return edition; } public void setEdition(String edition) { this.edition = edition; }}
Detail.java
public class Detail { private String pressTime; private String storyTime; public String getPressTime() { return pressTime; } public void setPressTime(String pressTime) { this.pressTime = pressTime; } public String getStoryTime() { return storyTime; } public void setStoryTime(String storyTime) { this.storyTime = storyTime; }}
好,我们稍微修改一下xml文件,再看看个该如何解析:
1 Java编程思想 80 张三 天朝 21世纪 2 三国演义 30 罗贯中 明朝 汉末 3 红楼梦 35 曹雪芹 清朝 不详 4 西游记 25 吴承恩 明朝 大唐 5 水浒传 30 施耐庵 明朝 大宋
又多了一层嵌套,看解析方式:
private Listbs; private Book b; private Detail detail; // 读取xml文件获得Document对象 @Test public void test1() { try { // 1.读取xml文件,获取document对象 SAXReader reader = new SAXReader(); Document document = reader.read(new File("F:\\test\\books.xml")); // 2.获取根节点 Element root = document.getRootElement(); bs = new ArrayList (); // 3.迭代,获取根节点的所有子节点 for (Iterator es = root.elementIterator(); es.hasNext();) { Element e = es.next(); b = new Book(); // 4.再次迭代,获取子节点的子节点 for (Iterator e_son = e.elementIterator(); e_son .hasNext();) { Element ee = e_son.next(); if (ee.getName().equals("id")) { b.setId(Integer.parseInt(ee.getText().toString())); } else if (ee.getName().equals("name")) { b.setName(ee.getText()); } else if (ee.getName().equals("price")) { b.setPrice(Integer.parseInt(ee.getText())); } else if (ee.getName().equals("auhtor")) { b.setAuthor(ee.getText()); } else if (ee.getName().equals("detail")) { detail = new Detail(); for (Iterator ds = ee.elementIterator(); ds .hasNext();) { Element d = ds.next(); if (d.getName().equals("pressTime")) { detail.setPressTime(d.getText()); } else if (d.getName().equals("storyTime")) { detail.setStoryTime(d.getText()); } } b.setDetail(detail); } } bs.add(b); } } catch (DocumentException e) { e.printStackTrace(); } for (Book bk : bs) { System.out.println(bk.getName()+","+bk.getDetail().getPressTime()); } }
继续修改xml文件,为之添加属性:
1 Java编程思想 80 张三 天朝 21世纪 2 三国演义 30 罗贯中 明朝 汉末 3 红楼梦 35 曹雪芹 清朝 不详 4 西游记 25 吴承恩 明朝 大唐 5 水浒传 30 施耐庵 明朝 大宋
给每一个book都添加了属性,又该怎么遍历呢?attribute的遍历和element的遍历非常类似,看代码:
// 读取xml文件获得Document对象 @Test public void test1() { try { // 1.读取xml文件,获取document对象 SAXReader reader = new SAXReader(); Document document = reader.read(new File("F:\\test\\books.xml")); // 2.获取根节点Element root = document.getRootElement(); bs = new ArrayList (); // 3.迭代,获取根节点的所有子节点 for (Iterator es = root.elementIterator(); es.hasNext();) { Element e = es.next(); b = new Book(); book_attr = new lenve.test.Attribute(); for (Iterator as = e.attributeIterator();as.hasNext();) { Attribute attr = as.next(); if(attr.getName().equals("category")){ book_attr.setCategory(attr.getText()); }else if(attr.getName().equals("edition")){ book_attr.setEdition(attr.getText()); } } b.setAttribute(book_attr); // 4.再次迭代,获取子节点的子节点 for (Iterator e_son = e.elementIterator(); e_son .hasNext();) { Element ee = e_son.next(); if (ee.getName().equals("id")) { b.setId(Integer.parseInt(ee.getText().toString())); } else if (ee.getName().equals("name")) { b.setName(ee.getText()); } else if (ee.getName().equals("price")) { b.setPrice(Integer.parseInt(ee.getText())); } else if (ee.getName().equals("auhtor")) { b.setAuthor(ee.getText()); } else if (ee.getName().equals("detail")) { detail = new Detail(); for (Iterator ds = ee.elementIterator(); ds .hasNext();) { Element d = ds.next(); if (d.getName().equals("pressTime")) { detail.setPressTime(d.getText()); } else if (d.getName().equals("storyTime")) { detail.setStoryTime(d.getText()); } } b.setDetail(detail); } } bs.add(b); } } catch (DocumentException e) { e.printStackTrace(); } for (Book bk : bs) { System.out.println(bk.getName()+","+bk.getDetail().getPressTime()+","+bk.getAttribute().getCategory()); } }
如果我们只想遍历某一个节点呢?比如我们只想遍历名称为id的节点,该怎么办?
private Listbs; private Book b; @Test public void test2() { try { // 1.读取xml文件,获取document对象 SAXReader reader = new SAXReader(); Document document = reader.read(new File("F:\\test\\books.xml")); // 2.获取根节点 Element root = document.getRootElement(); bs = new ArrayList (); // 3.迭代,获取根节点的所有子节点 for (Iterator es = root.elementIterator(); es.hasNext();) { Element e = es.next(); b = new Book(); // 4.再次迭代,获取子节点的子节点 for (Iterator e_son = e.elementIterator("id"); e_son .hasNext();) { Element ee = e_son.next(); b.setId(Integer.parseInt(ee.getText().toString())); } bs.add(b); } } catch (DocumentException e) { e.printStackTrace(); } for (Book bk : bs) { System.out.println(bk.getId()+","+bk.getAuthor()); } }
输出:
最后一个问题,怎样以字符串的形式拿到一个xml文件:
@Test public void test3(){ try { SAXReader reader = new SAXReader(); Document document = reader.read(new File("F:\\test\\books.xml")); String text = document.asXML(); System.out.println(text); } catch (DocumentException e) { e.printStackTrace(); } }
二、使用程序写一个xml文件
1.怎样把一个字符串文件写成xml文件:
@Test public void test4() { try { String text = ""; Document document = DocumentHelper.parseText(text); //两种方式皆可// FileWriter out = new FileWriter(new File("F:\\test\\str2xml.xml")); PrintWriter out = new PrintWriter(new File("F:\\test\\s2x.xml")); document.write(out); out.close(); } catch (DocumentException e) { e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } 苹果 red 3元
这样输出的xml文件没有格式,可读性较差,换个方式再看看:
@Test public void test5() { try { String text = ""; Document document = DocumentHelper.parseText(text); PrintWriter out = new PrintWriter(new File("F:\\test\\s2x1.xml")); XMLWriter writer = new XMLWriter(out, new OutputFormat().createPrettyPrint()); writer.write(document); writer.close(); } catch (DocumentException e) { e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } 苹果 red 3元
输出结果:
这样的输出格式也是极好的。
2.通过程序一个元素一个元素的写入:
@Test public void test6(){ int res = createXMLFile(); if(res==1){ System.out.println("xml文件创建成功!"); }else{ System.out.println("xml文件创建失败!"); } } public int createXMLFile(){ //返回0表示创建成功,返回1表示创建失败 int result = 0; Document document = DocumentHelper.createDocument(); //建立根节点 Element root = document.addElement("fruits"); //加入注释 root.addComment("this is a xml about fruit"); Element f1 = root.addElement("fruit"); f1.addAttribute("color", "red"); Element f11 = f1.addElement("price"); f11.setText("10元"); Element f12 = f1.addElement("shape"); f12.setText("圆形"); Element f13 = f1.addElement("name"); f13.setText("苹果"); //将xml写入文件中 try { PrintWriter out = new PrintWriter(new File("F:\\test\\111.xml")); XMLWriter writer = new XMLWriter(out, new OutputFormat().createPrettyPrint()); writer.write(document); writer.close(); result = 1; } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return result; }
再看看新创建的xml文件长什么样:
这里使用最多的就是三个方法,一个是addElement(),一个是addAttribute(),还有一个是setText(),对每一个节点都可以执行这三个操作,你想创建的任何形状的xml都可以通过层层的嵌套实现。
如果想手动指定输出编码格式:
@Test public void test6(){ int res = createXMLFile(); if(res==1){ System.out.println("xml文件创建成功!"); }else{ System.out.println("xml文件创建失败!"); } } public int createXMLFile(){ //返回0表示创建成功,返回1表示创建失败 int result = 0; Document document = DocumentHelper.createDocument(); //建立根节点 Element root = document.addElement("fruits"); //加入注释 root.addComment("this is a xml about fruit"); Element f1 = root.addElement("fruit"); f1.addAttribute("color", "red"); Element f11 = f1.addElement("price"); f11.setText("10元"); Element f12 = f1.addElement("shape"); f12.setText("圆形"); Element f13 = f1.addElement("name"); f13.setText("苹果"); //将xml写入文件中 try { PrintWriter out = new PrintWriter(new File("F:\\test\\111.xml")); OutputFormat format = OutputFormat.createPrettyPrint();//缩进显示 //默认输出编码是UTF-8,可以手动设置为GBK format.setEncoding("GBK"); XMLWriter writer = new XMLWriter(out, format); writer.write(document); writer.close(); result = 1; } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return result; }
输出的xml文件为(注意看编码):
三、修改xml文件
我们要修改一下xml文件:
1 Java编程思想 80 张三 天朝 21世纪 2 三国演义 30 罗贯中 明朝 汉末 3 红楼梦 35 曹雪芹 清朝 不详 4 西游记 25 吴承恩 明朝 大唐 5 水浒传 30 施耐庵 明朝 大宋
1.把所有的edition属性的值为8的修改为100
使用xpath查找对象时,依赖于jaxen.jar包,所以要先这个包。查找对象时,如果查找的是节点,直接写名称,如:/books/book/name,如果查找的是属性,要在属性前加上@,如:/books/book/@edition@Test public void modifyXmlFile(){ try { SAXReader reader = new SAXReader(); Document document = reader.read(new File("F:\\test\\books.xml")); //先利用xpath查找对象 Listns = document.selectNodes("/books/book/@edition"); Iterator iter = ns.iterator(); while(iter.hasNext()){ Attribute attr = (Attribute) iter.next(); if(Integer.parseInt(attr.getValue())==8){ attr.setValue("100"); } } //输出修改后的文件 PrintWriter out = new PrintWriter(new File("F:\\test\\m1.xml")); XMLWriter w = new XMLWriter(out,OutputFormat.createPrettyPrint()); w.write(document); w.close(); } catch (DocumentException e) { e.printStackTrace(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }
2.把“Java编程思想”修改为“Java语言程序设计”并在该name属性所在的book节点中添加buyTime节点,节点值为2015-04-27:
@Test public void modifyXmlFile(){ try { SAXReader reader = new SAXReader(); Document document = reader.read(new File("F:\\test\\books.xml")); //先利用xpath查找对象 Listns = document.selectNodes("/books/book/name"); Iterator iter = ns.iterator(); while(iter.hasNext()){ Element e = (Element) iter.next(); if(e.getText().equals("Java编程思想")){ e.setText("Java语言程序设计"); Element pe = e.getParent(); Element new_e = pe.addElement("buyTime"); new_e.setText("2015-04-27"); } } //输出修改后的文件 PrintWriter out = new PrintWriter(new File("F:\\test\\m2.xml")); XMLWriter w = new XMLWriter(out,OutputFormat.createPrettyPrint()); w.write(document); w.close(); } catch (DocumentException e) { e.printStackTrace(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }
3.若edition属性值为8,则删除该属性
@Test public void modifyXmlFile(){ try { SAXReader reader = new SAXReader(); Document document = reader.read(new File("F:\\test\\books.xml")); Listns = document.selectNodes("/books/book/@edition"); Iterator iter = ns.iterator(); while(iter.hasNext()){ Attribute attr = (Attribute) iter.next(); if(Integer.parseInt(attr.getValue())==8){ attr.getParent().remove(attr); } } try { PrintWriter out = new PrintWriter(new File("F:\\test\\m3.xml")); XMLWriter w = new XMLWriter(out,OutputFormat.createPrettyPrint()); w.write(document); w.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } catch (DocumentException e) { e.printStackTrace(); } }
4.把id为3的书的name节点删除:
@Testpublic void modifyXmlFile(){ try { SAXReader reader = new SAXReader(); Document document = reader.read(new File("F:\\test\\books.xml")); Listns = document.selectNodes("/books/book/id"); Iterator iter = ns.iterator(); while(iter.hasNext()){ Element e = (Element) iter.next(); if(e.getText().equals("3")){ e.getParent().remove(e.getParent().element("name")); } } PrintWriter out = new PrintWriter(new File("F:\\test\\m4.xml")); XMLWriter w = new XMLWriter(out, OutputFormat.createPrettyPrint()); w.write(document); w.close(); } catch (DocumentException e) { e.printStackTrace(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }}
5.移除所有文件的id属性:
方式一:
直接查找id节点,再删除@Test public void modifyXmlFile(){ try { SAXReader reader = new SAXReader(); Document document = reader.read(new File("F:\\test\\books.xml")); Listns = document.selectNodes("/books/book/id"); Iterator iter = ns.iterator(); while(iter.hasNext()){ Element e = (Element) iter.next(); e.getParent().remove(e); } PrintWriter out = new PrintWriter(new File("F:\\test\\m5.xml")); XMLWriter w = new XMLWriter(out,OutputFormat.createPrettyPrint()); w.write(document); w.close(); } catch (DocumentException e) { e.printStackTrace(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }
方法二:
查找book节点,再删除book节点的id节点:@Test public void modifyXmlFile(){ try { SAXReader reader = new SAXReader(); Document document = reader.read(new File("F:\\test\\books.xml")); Listns = document.selectNodes("/books/book"); Iterator iter = ns.iterator(); while(iter.hasNext()){ Element e = (Element) iter.next(); e.remove(e.element("id")); } PrintWriter out = new PrintWriter(new File("F:\\test\\m6.xml")); XMLWriter w = new XMLWriter(out,OutputFormat.createPrettyPrint()); w.write(document); w.close(); } catch (DocumentException e) { e.printStackTrace(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }
好了,先写这么多,这些东东基本上够项目使用了。