XML文件可以用来作为一种小型数据库存在,但更多时候在项目中都是用来当成配置文件用的,也就避免不了对XML文件的增上改查操作。
在java中,解析XML文件的方式大致分为两种:DOM解析,SAX解析
先来说DOM解析方式:xml解析器一次性把整个xml文档加载进内存,然后在内存中构建一颗Document的对象树,通过Document对象,得到树上的节点对象,通过节点对象访问(操作)到xml文档的内容。
用的较为多的是Dom4j工具(非官方)解析,简单介绍下Dom4j的使用,具体API文档请下载
Dom4j读取xml文件
SAXReader reader = new SAXReader(); //1.创建一个xml解析器对象 Document doc = reader.read(new File("xxx.xml"));//2.读取xml文档,返回Document对象 获取节点: Iterator<Node> doc.nodeIterator(); //获取当前标签节点下的所有子节点 获取标签: Element elem = doc.getRootElement(); //获取xml文档的根标签(一般创建doc对象后回先调用此方法得到根标签) Element e = elem.element("标签名") //指定名称的第一个子标签 Iterator<Element> iterator = elem.elementIterator("标签名");// 指定名称的所有子标签 List<Element> list = elem.elements(); //获取所有子标签 获取属性: String sttrValue = elem.attributeValue("属性名") //获取指定名称的属性值 Attribute attr = Element.attribute("属性名");//获取指定名称的属性对象 attr.getName() //获取属性名称 attr.getValue() //获取属性值 List<Attribute> elem.attributes(); //获取所有属性对象 Iterator<Attribute> elem.attributeIterator(); //获取所有属性对象 获取文本: elem.getText(); //获取当前标签的文本 elem.elementText("标签名") //获取当前标签的指定名称的子标签的文本内容
Dom4j修改xml文件
增加: DocumentHelper.createDocument() 增加文档 addElement("名称") 增加标签 addAttribute("名称",“值”) 增加属性 修改: Attribute.setValue("值") 修改属性值 Element.addAtribute("同名的属性名","值") 修改同名的属性值 Element.setText("内容") 修改文本内容 删除 Element.detach(); 删除标签 Attribute.detach(); 删除属性 写出文件 XMLWriter writer = new XMLWriter(OutputStream, OutputForamt) wirter.write(Document);
简单代码操作步骤:
1 //1、读取文件
2 Document doc = new SAXReader().read(new File("xxx.xml"));
3
4 //2、修改文件
5
6 //3、写出文件
7 FileOutputStream out = new FileOutputStream("f:/xxx.xml");//指定文件输出的位置
8 //指定写出的格式
9 OutputFormat format = OutputFormat.createCompactFormat(); //紧凑的格式.去除空格换行.
10 //OutputFormat format = OutputFormat.createPrettyPrint(); //格式好的格式.有空格和换行.
11 format.setEncoding("utf-8");//2.指定生成的xml文档的编码
12 XMLWriter writer = new XMLWriter(out,format);//创建写出对象
13 writer.write(doc);//写出对象
14 writer.close();//关闭流
值得注意的是Dom4j还支持xPath,这让我们获取标签得到极大的方便。基本就需要记住两个方法,一句代码,便可以获取所有想获取到的元素
导入xPath支持jar包 jaxen-1.1-beta-6.jar,上面给的文档有。
List<Node> selectNodes("xpath表达式"); // 查询多个节点对象 Node selectSingleNode("xpath表达式"); // 查询一个节点对象
例子:假设有如下这段xml,想要获取 二班赵六 的学生的姓名
1 <?xml version="1.0" encoding="UTF-8"?>
2 <root>
3 <class id="001">
4 <student id="001">
5 <name>一班--张三</name>
6 <age>20</age>
7 </student>
8 <student id="002">
9 <name>一班--李四</name>
10 <age>20</age>
11 </student>
12 </class>
13 <class id="002">
14 <student id="001">
15 <name>二班--王五</name>
16 <age>20</age>
17 </student>
18 <student id="002">
19 <name>二班--赵六</name>
20 <age>20</age>
21 </student>
22 </class>
23 </root>
普通方式获取标签与xpath方式获取标签比较
1 public static void main(String[] args) throws Exception {
2 SAXReader reader = new SAXReader();
3 Document read = reader.read("./src/NewFile.xml");
4 Element rootElement = read.getRootElement();
5
6 //普通方式
7 List<Element> elements = rootElement.elements();
8 for (Element element : elements) {
9 if("002".equals(element.attributeValue("id"))){
10 List<Element> elem = element.elements();
11 for (Element e : elem) {
12 if("002".equals(e.attributeValue("id"))){
13 Element nameElement = e.element("name");
14 System.out.println("普通方式: "+nameElement.getText());
15 }
16 }
17 }
18 }
19 //xpath方式
20 Element nameElement = (Element)rootElement.selectSingleNode("/root/class[@id='002']/student[@id='002']/name");
21 System.out.println("xpath方式: "+nameElement.getText());
22 }
执行结果:
普通方式: 二班--赵六
xpath方式: 二班--赵六
可见支持xpath对操作xml文档有多么方便
简单介绍xpath的语法,具体请参照:,http://www.w3cschool.cn/index-14.html,附实例文档
/ 绝对路径 表示从xml的根位置开始或子元素(一个层次结构) // 相对路径 表示不分任何层次结构的选择元素。 * 通配符 表示匹配所有元素 [] 条件 表示选择什么条件下的元素 @ 属性 表示选择属性节点 and 关系 表示条件的与关系(等价于&&) text() 文本 表示选择文本内容
SAX解析(官方):
这种解析方式原理是一边加载,一边处理,类似于事件的处理机制,适合xml文件较大的情况
核心API:
SAXParser类: 用于读取和解析xml文件对象
parse(File f, DefaultHandler dh)//解析xml文件 参数一: File,读取的xml文件。参数二: DefaultHandler,SAX事件处理程序。
简单代码实现:详细请查阅api文档
1 public class MyDefaultHandler extends DefaultHandler {
2
3 /**
4 * 开始文档时调用
5 */
6 @Override
7 public void startDocument() throws SAXException {
8 System.out.println("MyDefaultHandler.startDocument()");
9 }
10
11 /**
12 * 开始标签时调用
13 * @param qName: 表示开始标签的标签名
14 * @param attributes: 表示开始标签内包含的属性列表
15 */
16 @Override
17 public void startElement(String uri, String localName, String qName,
18 Attributes attributes) throws SAXException {
19 System.out.println("MyDefaultHandler.startElement()-->"+qName);
20 }
21
22 /**
23 * 结束标签时调用
24 * @param qName: 结束标签的标签名称
25 */
26 @Override
27 public void endElement(String uri, String localName, String qName)
28 throws SAXException {
29 System.out.println("MyDefaultHandler.endElement()-->"+qName);
30 }
31
32 /**
33 * 读到文本内容的时调用
34 * @param ch: 表示当前读完的所有文本内容
35 * @param start: 表示当前文本内容的开始位置
36 * @param length: 表示当前文本内容的长度
37 */
38 @Override
39 public void characters(char[] ch, int start, int length)
40 throws SAXException {
41 //得到当前文本内容
42 String content = new String(ch,start,length);
43 System.out.println("MyDefaultHandler.characters()-->"+content);
44 }
45
46 /**
47 * 结束文档时调用
48 */
49 @Override
50 public void endDocument() throws SAXException {
51 System.out.println("MyDefaultHandler.endDocument()");
52 }
53
54 }
55 public class Demo1 {
56 public static void main(String[] args) throws Exception{
57 //1.创建SAXParser对象
58 SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
59 //2.调用parse方法
60 /**
61 * 参数一: xml文档
62 * 参数二: DefaultHandler的子类
63 */
64 parser.parse(new File("./src/contact.xml"), new MyDefaultHandler());
65 }
66 }