XML文件可以用来作为一种小型数据库存在,但更多时候在项目中都是用来当成配置文件用的,也就避免不了对XML文件的增上改查操作。
在java中,解析XML文件的方式大致分为4种:DOM,SAX,JDOM,Dom4j,本文只用dom4j
DOM解析方式:xml解析器一次性把整个xml文档加载进内存,然后在内存中构建一颗Document的对象树,通过Document对象,得到树上的节点对象,通过节点对象访问(操作)到xml文档的内容。
用的较为多的是Dom4j工具(非官方)解析,简单介绍下Dom4j的使用
下载地址:http://jareye.com/jar/list.html?q=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("标签名") //获取当前标签的指定名称的子标签的文本内容
修改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,想要获取 二班赵六 的学生的姓名
<?xml version="1.0" encoding="UTF-8"?>
<root>
<class id="001">
<student id="001">
<name>一班--张三</name>
<age>20</age>
</student>
<student id="002">
<name>一班--李四</name>
<age>20</age>
</student>
</class>
<class id="002">
<student id="001">
<name>二班--王五</name>
<age>20</age>
</student>
<student id="002">
<name>二班--赵六</name>
<age>20</age>
</student>
</class>
</root>
普通方式获取标签与xpath方式获取标签比较
public static void main(String[] args) throws Exception {
SAXReader reader = new SAXReader();
Document read = reader.read("./src/NewFile.xml");
Element rootElement = read.getRootElement();
//普通方式
List<Element> elements = rootElement.elements();
for (Element element : elements) {
if("002".equals(element.attributeValue("id"))){
List<Element> elem = element.elements();
for (Element e : elem) {
if("002".equals(e.attributeValue("id"))){
Element nameElement = e.element("name");
System.out.println("普通方式: "+nameElement.getText());
}
}
}
}
//xpath方式
Element nameElement = (Element)rootElement.selectSingleNode("/root/class[@id='002']/student[@id='002']/name");
System.out.println("xpath方式: "+nameElement.getText());
}
执行结果:
普通方式: 二班--赵六
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文档
public class MyDefaultHandler extends DefaultHandler { /** * 开始文档时调用 */ @Override public void startDocument() throws SAXException { System.out.println("MyDefaultHandler.startDocument()"); } /** * 开始标签时调用 * @param qName: 表示开始标签的标签名 * @param attributes: 表示开始标签内包含的属性列表 */ @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { System.out.println("MyDefaultHandler.startElement()-->"+qName); } /** * 结束标签时调用 * @param qName: 结束标签的标签名称 */ @Override public void endElement(String uri, String localName, String qName) throws SAXException { System.out.println("MyDefaultHandler.endElement()-->"+qName); } /** * 读到文本内容的时调用 * @param ch: 表示当前读完的所有文本内容 * @param start: 表示当前文本内容的开始位置 * @param length: 表示当前文本内容的长度 */ @Override public void characters(char[] ch, int start, int length) throws SAXException { //得到当前文本内容 String content = new String(ch,start,length); System.out.println("MyDefaultHandler.characters()-->"+content); } /** * 结束文档时调用 */ @Override public void endDocument() throws SAXException { System.out.println("MyDefaultHandler.endDocument()"); } } public class Demo1 { public static void main(String[] args) throws Exception{ //1.创建SAXParser对象 SAXParser parser = SAXParserFactory.newInstance().newSAXParser(); //2.调用parse方法 /** * 参数一: xml文档 * 参数二: DefaultHandler的子类 */ parser.parse(new File("./src/contact.xml"), new MyDefaultHandler()); } }