解析和操作XML文件
Dom4j工具
使用步骤:
1)导入dom4j的核心包。 dom4j-1.6.1.jar
2)编写Dom4j读取xml文件代码
1,Domj4读取xml文件
,准备工作:读取整个文档并获取根节点
//获取document
SAXReader reader = new SAXReader();
Document document = reader.read(new File("src/MyXml.xml"));
//获取根节点
Element rootElement = document.getRootElement();
节点:
Iterator Element.nodeIterator(); //获取当前标签节点下的所有子节点
标签:
Element Document.getRootElement(); //获取xml文档的根标签
Element ELement.element("标签名") //指定名称的第一个子标签
Iterator<Element> Element.elementIterator();//获取所有子标签
List<Element> Element.elements(); //获取所有子标签
Iterator<Element> Element.elementIterator("标签名");// 指定名称的所有子标签
List<Element> Element.elements("标签名"); //指定名称的所有子标签
属性:
String Element.attributeValue("属性名") //获取指定名称的属性值
Attribute Element.attribute("属性名");//获取指定名称的属性对象
Attribute.getName() //获取属性名称
Attibute.getValue() //获取属性值
List<Attribute> Element.attributes(); //获取所有属性对象
Iterator<Attribute> Element.attibuteIterator(); //获取所有属性对象
文本:
Element.getText(); //获取当前标签的文本
Element.getTextTrim()//获取当前标签的文本,不包含空格
Element.elementText("标签名") //获取当前标签的指定名称的子标签的文本内容
例子:
/** * 读取xml文件内容 * * 读取核心--获取document对象 * SAXReader reader = new SAXReader(); Document document = reader.read( File/URL/InputStream/InputSource/Reader object); * * 1.获取根节点(标签) document.getRootElement() * * 2.获取子节点 element.nodeIterator(),然后通过迭代器获取子节点 * * 3.获取标签 * 1)获取指定名称的标签 element.element(String elementName); * 2)获取当前标签下的指定名称的子标签集合--两种方法获取 * 迭代器接收:element.elementIterator(String elementName) * List接收:element.elements(String elementName) * 3)获取当前标签下的所有子标签--两种方法获取(同上) * 迭代器接收:element.elementIterator() * List接收:element.elements() */ public class Demo { public static void main(String[] args) { } /** * 获取文档所有Element(标签)节点,并打印 */ @Test public void readXML() throws DocumentException { //读取文档,获取document对象 SAXReader reader = new SAXReader(); Document document = reader.read(new File("src/MyXml.xml")); //得到根节点 Element rootElement = document.getRootElement(); //获取子节点 getChildrenNodes(rootElement); } //循环获取子节点,并打印其名称 private void getChildrenNodes(Element element) { //打印节点名字 System.out.println(element.getName()); @SuppressWarnings("unchecked") Iterator<Node> iter = element.nodeIterator(); while (iter.hasNext()) { Node node = iter.next(); if (node instanceof Element) { Element e = (Element) node; //递归获取所有子节点 getChildrenNodes(e); } } } /** * 获取标签 */ @Test public void readXML2() throws DocumentException { //1.读取文档,获取document对象 SAXReader reader = new SAXReader(); Document document = reader.read(new File("src/MyXml.xml")); //2.得到root(根)标签 Element rootElement = document.getRootElement(); System.out.println("根标签:" + rootElement.getName()); //3.获得第一个指定名称的子标签 Element element = rootElement.element("contract"); System.out.println("第一个contact子标签:" + element.getName()); // System.out.println(element.attribute(0).getName() + element.attribute(0).getValue()); //4.获取当前标签下的指定名字的子标签 // @SuppressWarnings("unchecked") // Iterator<Element> it = rootElement.elementIterator("contract"); // System.out.println("含有\"contract\"的子标签:"); // while (it.hasNext()) { // System.out.println(it.next().getName()); // } @SuppressWarnings("unchecked") List<Element> eList = rootElement.elements("contract"); System.out.println("含有\"contract\"的子标签:"); for (Element e : eList) { System.out.println(e.getName()); } //5.获取当前标签下的所有子标签 // @SuppressWarnings("unchecked") // Iterator<Element> iter = element.elementIterator(); // System.out.println("所有子标签:"); // while (iter.hasNext()) { // Element e = iter.next(); // System.out.println(e.getName()); // } //elementIterator可以,element.elements()方法也可以做到 @SuppressWarnings("unchecked") List<Element> elements = rootElement.elements(); Iterator<Element> eIter = elements.iterator(); System.out.println("所有子标签:"); while (eIter.hasNext()) { System.out.println(eIter.next().getName()); } } /** * 读取属性节点的信息 * @throws DocumentException */ @SuppressWarnings("unchecked") public void test3() throws DocumentException { //获取整个xml对象节点 SAXReader reader = new SAXReader(); Document document = reader.read(new File("src/MyXml.xml")); //获取根节点 Element contact = document.getRootElement().element("contact"); //获取指定名称的属性 // Attribute attribute = contact.attribute("id"); // System.out.println("通过指定名字获取:\nid:" + attribute.getValue() + "\n"); String value = contact.attributeValue("id"); System.out.println("通过指定名字获取:\nid:" + value + "\n"); //获取所有属性的名称 Iterator<Attribute> aIter = contact.attributeIterator(); System.out.println("获取所有属性:"); while (aIter.hasNext()) { Attribute a = aIter.next(); System.out.println(a.getName() + ":" +a.getValue()); } } /** * 获取文本 * 注意:空格和换行也是文本 * @throws DocumentException */ @Test public void test4() throws DocumentException { //获取整个xml对象节点 SAXReader reader = new SAXReader(); Document document = reader.read(new File("src/MyXml.xml")); //获取根节点 Element contact = document.getRootElement().element("contact"); //打印文本内容 // String text = contact.element("name").getText(); // String text = contact.element("name").getTextTrim(); String text = contact.elementText("name"); String text2 = contact.elementTextTrim("name"); System.out.println("elementText:" + text); System.out.println("elementTextTrim:" + text2); //空格和换行也是文本,但是getTextTrim可以去掉空格和换行 // String text3 = contact.getText().trim(); String text3 = contact.getTextTrim(); System.out.println(text3); } }
Dom4j修改xml文档
写出内容到xml文档
XMLWriter writer = new XMLWriter(OutputStream, OutputForamt)
wirter.write(Document);
修改xml文档的API
增加:
DocumentHelper.createDocument() 增加文档
addElement("名称") 增加标签
addAttribute("名称",“值”) 增加属性
修改:
Attribute.setValue("值") 修改属性值
Element.addAtribute("同名的属性名","值") 修改同名的属性值
Element.setText("内容") 修改文本内容
删除
Element.detach(); 删除标签
Attribute.detach(); 删除属性
例子:
/** * XML文档的增删改 * * 1. 增加--文档,注释,标签,属性,文本 * 2. 修改--属性,文本 * 3. 删除--标签,属性 * @author Administrator * */ public class Demo2 { public static void main(String[] args) { new Demo2().CRUD(); } /** * 对XML文件进行增删改 */ public void CRUD() { //增加 addXML(); //修改 updateXML(); //删除 delFromXML(); } /** * 增加节标签,属性,文本 */ public void addXML() { //创建新文档 Document document = DocumentHelper.createDocument(); //创建注释 document.addComment("学生信息..."); //创建根节点 Element rootElement = document.addElement("Students"); //创建第一个子节点 Element child = rootElement.addElement("childElement") .addAttribute("id", "1"); child.addElement("name").addText("张三"); child.addElement("sex").addText("男"); child.addElement("grade").addText("计算机一班"); child.addElement("address").setText("广州天河"); //第二个子节点 Element child2 = rootElement.addElement("childElement") .addAttribute("id", "2"); child2.addElement("name").addText("李四"); child2.addElement("sex").addText("女"); child2.addElement("grade").addText("计算机二班"); child2.addElement("address").setText("广州深圳"); //覆盖写入文档 writeToXML(document); } /** * 修改属性,文本 */ @SuppressWarnings("unchecked") public void updateXML() { //获取document对象 Document document = getDocumentFromXML(); //修改属性节点,把id为1的改成01 Element rootElement = document.getRootElement(); Iterator<Element> eIter = rootElement.elementIterator(); while (eIter.hasNext()) { Element stu = eIter.next(); Attribute a = stu.attribute("id"); if (a != null && a.getValue().equals("1")) { // stu.addAttribute("id", "01"); 方式一:通过添加相同名字的属性来修改 a.setValue("01"); // System.out.println("00000"); } if (a != null && a.getValue().equals("2")) { Iterator<Element> iter = stu.elementIterator(); while (iter.hasNext()) { Element element = iter.next(); if (element.getName().equals("name")) { element.setText("王丽"); } } } } writeToXML(document); } /** * 删除属性,标签 */ @SuppressWarnings("unchecked") public void delFromXML() { Document document = getDocumentFromXML(); Element rootElement = document.getRootElement(); //删除属性节点,其id=2 Iterator<Element> eIter = rootElement.elementIterator(); while (eIter.hasNext()) { Element stu = eIter.next(); Attribute a = stu.attribute("id"); if (a != null && a.getValue().equals("2")) { a.detach(); //删除标签 stu.detach(); } } writeToXML(document); } /** * 写入文档 */ public void writeToXML(Document document) { try { //输出流 OutputStream out = new FileOutputStream("src/MyXML.xml"); //输出格式 OutputFormat format = OutputFormat.createPrettyPrint(); format.setEncoding("UTF-8"); //创建XMLWriter对象 XMLWriter writer = new XMLWriter(out, format); writer.write(document); //关闭流 out.close(); writer.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } /** * 读取文档 */ public Document getDocumentFromXML() { try { SAXReader reader = new SAXReader(); return reader.read(new File("src/MyXml.xml")); } catch (DocumentException e) { e.printStackTrace(); System.exit(0); } return null; } }
xPath技术
引入
问题:当使用dom4j查询比较深的层次结构的节点(标签,属性,文本),比较麻烦!!!
xPath作用
主要是用于快速获取所需的节点对象。
在dom4j中如何使用xPath技术
1)导入xPath支持jar包 。 jaxen-1.1-beta-6.jar
2)使用xpath方法
List<Node> selectNodes("xpath表达式"); 查询多个节点对象
Node selectSingleNode("xpath表达式"); 查询一个节点对象
xPath语法
/ 绝对路径 表示从xml的根位置开始或子元素(一个层次结构)
// 相对路径 表示不分任何层次结构的选择元素。
* 通配符 表示匹配所有元素
[] 条件 表示选择什么条件下的元素
@ 属性 表示选择属性节点
and 关系 表示条件的与关系(等价于&&)
text() 文本 表示选择文本内容
例子:
public class Demo2 { @SuppressWarnings("unchecked") public static void main(String[] args) throws DocumentException { //获取整个xml对象节点 Document document = new SAXReader().read(new File("src/MyXml.xml")); String xPath; //定义查找规则 xPath = "/contactList";//根节点 xPath = "//contact";//子节点的两种形式 xPath = "//contactList/*"; xPath = "//contactList/*/name";//绝对路径和相对论路径查找标签 xPath = "//contactList//name"; xPath = "//contact[@id]";//获取contact节点 xPath = "//@id";//获取名字为id的属性 xPath = "//*[not(@*)]";//获取没有属性的节点 xPath = "//contact/name[text()='李四']";//获取名字为李四的节点 xPath = "//contact/name[normalize-space(text())='董十三']";//忽略文本前后的空格,获取名字为董十三的节点 xPath = "//contact/qq[string-length(text())>7]";//获取QQ号大于七位的标签 xPath = "//contact/*[string-length(text())>7]";//获取文本大于七位的标签 xPath = "//contact/*[string-length(name())>4]";//获取标签名大于四位的标签 List<Node> nList = document.selectNodes(xPath); for (Node node : nList) { System.out.println(node); } } }
SAX解析
4.1回顾DOM解析
DOM解析原理:一次性把xml文档加载进内存,然后在内存中构建Document树。
对内存要求比较要。
缺点: 不适合读取大容量的xml文件,容易导致内存溢出。
SAX解析原理: 加载一点,读取一点,处理一点。对内存要求比较低。
SAX解析工具
SAX解析工具- Sun公司提供的。内置在jdk中。org.xml.sax.*
核心的API:
SAXParser类: 用于读取和解析xml文件对象
parse(File f,
DefaultHandler dh
)方法: 解析xml文件
参数一: File:表示 读取的xml文件。
参数二: DefaultHandler: SAX事件处理程序。使用DefaultHandler的子类
1.创建SAXParser对象
SAXParser parser=SAXParserFactory.newInstance().newSAXParser();
2.调用parse方法
parser.parse(new File("./src/contact.xml"), new MyDefaultHandler());
[一个类继承class 类名(extends DefaultHandler) 在调用是创建传进去
DefaultHandler类的API:
void startDocument() : 在读到文档开始时调用
void endDocument() :在读到文档结束时调用
void startElement(String uri, String localName, String qName, Attributes attributes) :读到开始标签时调用
void endElement(String uri, String localName, String qName) :读到结束标签时调用
void characters(char[] ch, int start, int length) : 读到文本内容时调用
例子:
1 /* 2 * 需求:把xml文档完整的打印出来 3 */ 4 public class Demo2 { 5 6 public static void main(String[] args) throws Exception { 7 8 //SAXParser对象 9 SAXParser saxParser = SAXParserFactory.newInstance().newSAXParser(); 10 MyDefaultHandler2 dh = new MyDefaultHandler2(); 11 saxParser.parse(new File("src/MyXml.xml"), dh); 12 System.out.println(dh.getContent()); 13 } 14 15 } 16 17 class MyDefaultHandler2 extends DefaultHandler { 18 19 //读出内容 20 private StringBuffer sb = new StringBuffer(1000); 21 //返回内容结果 22 public String getContent() { 23 return sb.toString(); 24 } 25 26 @Override 27 public void startElement(String uri, String localName, String qName, 28 Attributes attributes) throws SAXException { 29 sb.append("<" + qName); 30 31 for (int i = 0, len = attributes.getLength(); i < len; i++) { 32 sb.append(" " + attributes.getQName(i) + "=\"" 33 + attributes.getValue(i) + "\""); 34 } 35 36 sb.append(">"); 37 } 38 39 @Override 40 public void characters(char[] ch, int start, int length) 41 throws SAXException { 42 sb.append(new String(ch, start, length)); 43 } 44 45 @Override 46 public void endElement(String uri, String localName, String qName) 47 throws SAXException { 48 sb.append("</" + qName + ">"); 49 } 50 51 }
============DOM解析 vs SAX解析 ========
DOM解析 |
SAX解析 |
原理: 一次性加载xml文档,不适合大容量的文件读取 |
原理: 加载一点,读取一点,处理一点。适合大容量文件的读取 |
DOM解析可以任意进行增删改成 |
SAX解析只能读取 |
DOM解析任意读取任何位置的数据,甚至往回读 |
SAX解析只能从上往下,按顺序读取,不能往回读 |
DOM解析面向对象的编程方法(Node,Element,Attribute),Java开发者编码比较简单。 |
SAX解析基于事件的编程方法。java开发编码相对复杂。 |