dom4j
首先需要在项目下(与src并列)创建一个lib文件夹,然后放入第三方包(dom4j-1.6.1.jar),并build path一下,如图:
接下来是获取dom4j的Document对象:
Document dom = new SAXReader().read("./xml/users.xml");
获取根节点:
@Test
public void hello() throws Exception {
SAXReader reader = new SAXReader();
Document dom = reader.read("./xml/users.xml");
Element root = dom.getRootElement();// 得到根节点
String name = root.getName();
System.out.println(name);
}
读取第一个<user>中的信息
// 需求:读取第一个<user>中的信息
@Test
public void demo1() throws DocumentException {
SAXReader reader = new SAXReader();
Document dom = reader.read("./xml/users.xml");
Element eRoot = dom.getRootElement();
Element eUser = eRoot.element("user");
String id = eUser.attributeValue("id");
String eName = eUser.element("name").getText();
String eAge = eUser.element("age").getText();
System.out.println("id:" + id + "name:" + eName + "," + "age:" + eAge);
}
结果;
查,需求:遍历出文档中的所有<user>的信息
有两种遍历方法,一种是用集合的for循环,一种是迭代器迭代。
@Test
public void queryAll() throws Exception {
Document dom = new SAXReader().read("./xml/users.xml");
Element root = dom.getRootElement();
List<Element> list = root.elements();
// 法一//获取root下的所有子节点 且封装到一个java.util.List中
for (int i = 0; i < list.size(); i++) {
Element eUser = list.get(i);
String id = eUser.attributeValue("id");
String eName = eUser.elementText("name");
String eAge = eUser.elementText("age");
System.out.println(id + "," + eName + "," + eAge);
}
System.out.println("-----------------");
// 法二
Iterator<Element> it = root.elementIterator();// 获取root下的所有子节点
// 且封装到一个迭代器中
while (it.hasNext()) {
Element e = it.next();
String id = e.attributeValue("id");
String name = e.elementText("name");
String age = e.elementText("age");
System.out.println(id + "," + name + "," + age);
}
}
结果:
两种序列化方式:(即增删改操作都是在内存,从内存写到磁盘文件)
// /序列化///
// 法1: 普通方式
XMLWriter xw = new XMLWriter(new PrintWriter("./xml/users.xml"));
xw.write(dom);
xw.close();
// 法2: 利用OutputFormat类进行格式化输出,如采用指定的编码
OutputFormat format = OutputFormat.createPrettyPrint();
format.setEncoding("GBK");
XMLWriter w2 = new XMLWriter(new FileOutputStream("./xml/users2.xml"),
format);
w2.write(dom);
w2.close();
}
增,需求:给xml文档添加一个<stu>元素
@Test
public void addElement() throws Exception {
Document dom = new SAXReader().read("./xml/users.xml");
Element root = dom.getRootElement();
// 添加并封装一个<stu>子节点
Element eStu = root.addElement("stu");
eStu.addAttribute("id", "S002");
Element eName = eStu.addElement("name");
eName.addText("李同学");// 添加文本内容,法1
Element eAge = eStu.addElement("age");
eAge.setText("22");// 添加文本内容,法2---原来没有内容,因此添加和设置效果是一样的
// /序列化///
// 法1: 普通方式
XMLWriter xw = new XMLWriter(new PrintWriter("./xml/users.xml"));
xw.write(dom);
xw.close();
// 法2: 利用OutputFormat类进行格式化输出,如采用指定的编码
OutputFormat format = OutputFormat.createPrettyPrint();
format.setEncoding("GBK");
XMLWriter w2 = new XMLWriter(new FileOutputStream("./xml/users2.xml"),
format);
w2.write(dom);
w2.close();
}
删,需求:删除root下的最后一个子元素
改,需求:修改root下的最后一个子元素
@Test
public void delAndUpdateElement() throws Exception {
Document dom = new SAXReader().read("./xml/users.xml");
Element root = dom.getRootElement();
List<Element> list = root.elements();// 所有子元素
Element lastE = list.get(list.size() - 1);
//
// 删除最后一个元素---找父亲删自己
// lastE.getParent().remove(lastE);
// 修改最后一个元素
lastE.addAttribute("id", "S007");
lastE.element("name").setText("OKOK");
lastE.element("age").setText("111");
// ///
XMLWriter xw = new XMLWriter(new PrintWriter("./xml/users.xml"));
xw.write(dom);
xw.close();
}
从零开始创建一个新的xml文档
@Test
public void createNewXML() throws IOException {
Document dom = DocumentHelper.createDocument();
Element root = dom.addElement("cities");
Element eCity = root.addElement("city");
eCity.addAttribute("id", "C001");
eCity.addElement("name").setText("益阳");
eCity.addElement("addr").setText("湖南");
// 序列化
XMLWriter w = new XMLWriter(new FileWriter("./xml/citys.xml"));
w.write(dom);
w.close();
}
重点是第一句
Document dom = DocumentHelper.createDocument();
Xpath
dom4j+Xpath技术演示,注意要导一个支持jar包:jaxen
使用xpath时,dom4j的代码套路:
1) 通过dom调用Node中的如下方法进行节点选择(有时也选择对象如属性值),参
数用xpath表达式: selectNodes(xpath)---最常用, selectSingleNode(xpath),
selectObject(xpath)
2)一点小细节: 以上3个方法是Node的,因此任意节点对象都可以调用,但结果却
是dom下符合xpath的所有节点或对象,不是当前调用节点的子树范围(局部), 而是整
棵树(全局),因此为避免歧义,建议使用dom调用
Xpath的格式可自询Xpath文档查阅
@Test
public void xpathDemo1() throws Exception {
Document dom = new SAXReader().read("./xml/contact.xml");
String xpath = "//name";// 查找整个文档树中的所有<name>元素
// String xpath="//aa//name";//查找整个文档树中的所有<aa>子孙节点中的<name>元素
// String xpath="//aa/name";//查找整个文档树中的<aa>的直接儿子节点<name>元素
List<Element> list = dom.selectNodes(xpath);// 技术入口
for (Element e : list) {
System.out.println(e.getText());
}
}
结果:
@Test
// 有关登录方面的xpath用法演示
public void xpathDemo2() throws Exception {
Document dom = new SAXReader().read("./xml/contact.xml");
// 模拟用户登录功能
Scanner sc = new Scanner(System.in);
String name = sc.nextLine();
String pwd = sc.nextLine();// 模拟用户登录功能
//构造登录的xpath
//String xpath = "//user[@name='lx'][@pwd='1234']";//写死的
//String xpath ="//user[@name='"+name+"'][@pwd='"+pwd+"']";//写活的
//name忽略大小写
name = name.toLowerCase();
String xpath="//user[fn:lower-case(@name)='"+name+"'][@pwd='"+pwd+"']";//活的
//Node eUser= dom.selectSingleNode(xpath);
List<Element> list = dom.selectNodes(xpath);
if (list.size() > 0) {
System.out.println("success:" + list.get(0).attributeValue("name"));
} else {
System.out.println("failure!");
}
}
结果: