XML解析
2013-10-31 10:27
591 查看
一、简介
在得到一个XML文档之后,利用程序按照其中元素的定义名称取出对应的内容,这样的操作即为:XML解析。在XML解析中,W3C定义了SAX和DOM两种解析方式,者两种解析方式的程序操作如下图所示:
由上图即可发现,应用程序不是直接对XMl文档进行操作的,而是先由XML分析器对文档进行分析,然后应用程序通过XML分析器所提供的DOM接口或SAX接口对分析结果进行操作,从而间接地实现了对XML文档的访问。
二、DOM解析操作
基于DOM(Document Object Model, 文档对象模型)的XML解析器将一个XML文档转换成一个对象模型的集合(即:DOM树),应用程序通过对这个对象模型的操作,来实现对XNL文档数据的操作。通过DOM接口,应用程序可以在任何时候访问XML文档中的任何一部分数据,因此这种利用DOM接口的机制也被称为随机访问机制。DOM树所提供的随机访问方式给应用程序的开发带来了很大的灵活性,可以任意的控制整个XML文档中的内容。但是,由于DOM分析器把整个XML文档转化成DOM树放在内存中,因此,此文档比较大或者结构比较复杂时,堆内存的要求就比较高,而且对于结构复杂的树的遍历也是一项耗时的操作。所以,DOM分析器对及其性能的要求比较高,程序的效率并不十分理想。
运行结果:
张三
李四
XML源文件dom_demo_1.xml内容:
以上程序完成了一个简单的DOM解析操作,从指定的XML文件中读取指定节点的内容,当使用builder.parse()操作时实际上就相当于将所有的XML文档读取到内存中,从而将所有的XML文件内容按照节点的定义顺序将其变成一颗内存中的DOM树,供用户解析使用。
在DOM操作中,除了可以使用DOM完成XML的读取之外,还可以使用DOM进行XML文件的新建输出。此时就需要必须newDocument方法建立一个新的DOOM树,并手工设置各个节点的关系。
运行结果文件dom_demo_2.xml:
以上程序可以发现,在XML创建中的所有节点(ELement)都是通过Document接口创建的,在创建时本身并没有任何父子节点关系,而是通过appendChild()方法设置的,而且根节点(addresslist)也要加入到document中,这样才是一棵完整的DOM。从以上两个demo中可以发现,使用DOM操作不仅可以读取文件,本身也可以生成和修改XML文件。
三、SAX解析操作
SAX(Simple APIS for XML, 操作XML的简单接口),采用的是一种顺序的模式进行访问,是一种快速读取XML数据的方式。如果在开发中想要使用SAX解析,则首先应该编写一个SAX解析器,再直接定义一个类,并使该类继承自DefaultHandler类,同时覆写其方法即可。当使用SAX解析器进行操作时会触发一系列的事件,如:当扫描到文档开始与结束、元素开始与结束是都会调用相关的处理方法,并由这些操作方法做出相应的操作,直至整个文档扫描结束。
新建解析器,继承DefaultHandler类:
使用SAX解析器:
被解析XML文档sax_demo_1.xml:
四、DOM解析和SAX解析比较
既然DOM解析适合于修改,SAX解析适合于读取大文件,那么如果将两者的优点集合起来操作岂不是更加方便?如:JDOM、DOM4J等。
五、JDOM
JDOM是使用Java语言编写的,用于读、写、操作XML的一套组件。一定要记住:JDOM = DOM修改文件的优点 + SAX读取快速的优点 。
1)使用JDOM进行XML的写操作(新建):
被JDOM新建的XML文档jdom_demo_1.xml:
2)使用JDOM进行XML的读操作:
其中jdom_demo_1.xml即为前文中所示。
六、DOM4J
DOM4J也是一组XML操作的组件包,主要用来读写XML文件。由于DOM4J性能优异,功能强大,而且易用性强,所以应用广泛,如:Hibernate和Spring框架中都使用了DOM4J进行XML的解析操作。其操作与JDOM类似。
1)使用DOM4进行XML的写操作:
输出的XML文档如下:
2)使用DOM4进行XML的读操作:
程序运行结果:
姓名: 张三, 编号: zs
邮件: zhangsan@qq.com
七、总结
从以上程序中可以看出,读取文件需要使用SAX建立解析器,然后通过文档依次找到根节点,再通过根节点找到每一个节点的内容。
在得到一个XML文档之后,利用程序按照其中元素的定义名称取出对应的内容,这样的操作即为:XML解析。在XML解析中,W3C定义了SAX和DOM两种解析方式,者两种解析方式的程序操作如下图所示:
由上图即可发现,应用程序不是直接对XMl文档进行操作的,而是先由XML分析器对文档进行分析,然后应用程序通过XML分析器所提供的DOM接口或SAX接口对分析结果进行操作,从而间接地实现了对XML文档的访问。
二、DOM解析操作
基于DOM(Document Object Model, 文档对象模型)的XML解析器将一个XML文档转换成一个对象模型的集合(即:DOM树),应用程序通过对这个对象模型的操作,来实现对XNL文档数据的操作。通过DOM接口,应用程序可以在任何时候访问XML文档中的任何一部分数据,因此这种利用DOM接口的机制也被称为随机访问机制。DOM树所提供的随机访问方式给应用程序的开发带来了很大的灵活性,可以任意的控制整个XML文档中的内容。但是,由于DOM分析器把整个XML文档转化成DOM树放在内存中,因此,此文档比较大或者结构比较复杂时,堆内存的要求就比较高,而且对于结构复杂的树的遍历也是一项耗时的操作。所以,DOM分析器对及其性能的要求比较高,程序的效率并不十分理想。
package com.wbf.dom; import java.io.File; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import org.w3c.dom.Document; import org.w3c.dom.NodeList; public class TestDOMDemo { public static void main(String args[]) { //建立DocumentBuilderFactory,用于取得DocumentBuilder DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); //建立DocumentBuilder DocumentBuilder builder = null; //实例化Document Document doc = null; try { builder = factory.newDocumentBuilder(); //读取指定路径的xml文档 doc = builder.parse("d:" + File.separator + "dom_demo_1.xml"); //查找tagName="name"的节点 NodeList nl = doc.getElementsByTagName("name"); int len = nl.getLength(); for (int i = 0; i < len; i++) { //输出文本节点的内容 System.out.println(nl.item(i).getFirstChild().getNodeValue()); } } catch (Exception e) { e.printStackTrace(); } } }
运行结果:
张三
李四
XML源文件dom_demo_1.xml内容:
<?xml version="1.0" encoding="GBK"?> <addresslist> <linkman> <name>张三</name> <email>zhangsan@qq.com</email> </linkman> <linkman> <name>李四</name> <email>lisi@qq.com</email> </linkman> </addresslist>
以上程序完成了一个简单的DOM解析操作,从指定的XML文件中读取指定节点的内容,当使用builder.parse()操作时实际上就相当于将所有的XML文档读取到内存中,从而将所有的XML文件内容按照节点的定义顺序将其变成一颗内存中的DOM树,供用户解析使用。
在DOM操作中,除了可以使用DOM完成XML的读取之外,还可以使用DOM进行XML文件的新建输出。此时就需要必须newDocument方法建立一个新的DOOM树,并手工设置各个节点的关系。
package com.wbf.dom; import java.io.File; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.transform.OutputKeys; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import org.w3c.dom.Document; import org.w3c.dom.Element; public class TestDOMDemo1 { public static void main(String args[]) throws Exception { //建立DocumentBuilderFactory,用于取得DocumentBuilder DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); //建立DocumentBuilder DocumentBuilder builder = factory.newDocumentBuilder(); //新建一个Document文档 Document doc = builder.newDocument(); //建立各个操作节点 Element addresslist = doc.createElement("addresslist"); Element linkman = doc.createElement("linkman"); Element name = doc.createElement("name"); Element email = doc.createElement("email"); //为需要节点添加文本节点 name.appendChild(doc.createTextNode("张三")); email.appendChild(doc.createTextNode("zhangsan@qq.com")); //设置节点关系 linkman.appendChild(name); linkman.appendChild(email); addresslist.appendChild(linkman); doc.appendChild(addresslist); //输出文档到文件中 TransformerFactory tf = TransformerFactory.newInstance(); Transformer t = tf.newTransformer(); t.setOutputProperty(OutputKeys.ENCODING, "GBk");//设置编码格式 DOMSource source = new DOMSource(doc);//输出文档 //设置输出位置 StreamResult result = new StreamResult(new File("d:" + File.separator + "dom_demo_2.xml")); //输出 t.transform(source, result); } }
运行结果文件dom_demo_2.xml:
<?xml version="1.0" encoding="GBk" standalone="no"?> <addresslist> <linkman> <name>张三</name> <email>zhangsan@qq.com</email> </linkman> </addresslist>
以上程序可以发现,在XML创建中的所有节点(ELement)都是通过Document接口创建的,在创建时本身并没有任何父子节点关系,而是通过appendChild()方法设置的,而且根节点(addresslist)也要加入到document中,这样才是一棵完整的DOM。从以上两个demo中可以发现,使用DOM操作不仅可以读取文件,本身也可以生成和修改XML文件。
三、SAX解析操作
SAX(Simple APIS for XML, 操作XML的简单接口),采用的是一种顺序的模式进行访问,是一种快速读取XML数据的方式。如果在开发中想要使用SAX解析,则首先应该编写一个SAX解析器,再直接定义一个类,并使该类继承自DefaultHandler类,同时覆写其方法即可。当使用SAX解析器进行操作时会触发一系列的事件,如:当扫描到文档开始与结束、元素开始与结束是都会调用相关的处理方法,并由这些操作方法做出相应的操作,直至整个文档扫描结束。
新建解析器,继承DefaultHandler类:
package com.wbf.sax; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; public class MySAX extends DefaultHandler { @Override public void characters(char[] ch, int start, int length) throws SAXException { /* 接收元素中字符数据的通知 * 默认情况下,不执行任何操作。 * 应用程序编写者可以重写此方法,以便对每块字符数据采取特定的措施(如将该数据添加到节点或缓冲区,或者将该数据打印到文件)。 * */ System.out.println(new String(ch, start, length)); } @Override public void endDocument() throws SAXException { /* 接收文档结束的通知。 * 默认情况下,不执行任何操作。应用程序编写者可以在子类中重写此方法,以便在文档的结束处采取特定的操作(如,结束树或关闭输出文件)。 * */ System.out.println("\n文档读取结束。。。"); } @Override public void endElement(String uri 4000 , String localName, String qName) throws SAXException { /* 接收元素结束的通知。 * 默认情况下,不执行任何操作。应用程序编写者可以在子类中重写此方法,以便在每个元素的结束处采取特定的操作(如,结束树节点或将输出写入文件)。 * */ System.out.print("</"); System.out.print(qName);//输出元素名称 System.out.print(">"); } @Override public void startDocument() throws SAXException { /* 接收文档开始的通知。 * 默认情况下,不执行任何操作。应用程序编写者可以在子类中重写此方法,以便在文档的开始采取特定的措施(如分配树的根节点或创建输出文件)。 * */ System.out.println("<?xml version=\"1.0\" encoding=\"GBK\"?>"); } @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { /* 接收元素开始的通知。 * 默认情况下,不执行任何操作。应用程序编写者可以在子类中重写此方法,以便在每个元素的开始处采取特定的操作(如,分配新的树节点或将输出写入文件)。 * */ System.out.print("<"); System.out.print(qName); if (attributes != null){ for (int i = 0; i < attributes.getLength(); i++){ System.out.print(" " + attributes.getQName(i) + "=\"" + attributes.getValue(i) + "\""); } } System.out.println(">"); } }
使用SAX解析器:
package com.wbf.sax; import java.io.File; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; public class TestSAXDemo { public static void main(String[] args) throws Exception { //建立SAX解析工厂 SAXParserFactory factory = SAXParserFactory.newInstance(); //构造解析器 SAXParser parser = factory.newSAXParser(); //使用DefaultHandler解析XML parser.parse("d:" + File.separator + "sax_demo_1.xml", new MySAX()); } }
被解析XML文档sax_demo_1.xml:
<?xml version="1.0" encoding="GBK"?> <addresslist> <linkman> <name>张三</name> <email>zhangsan@qq.com</email> </linkman> <linkman> <name>李四</name> <email>lisi@qq.com</email> </linkman> </addresslist>
四、DOM解析和SAX解析比较
既然DOM解析适合于修改,SAX解析适合于读取大文件,那么如果将两者的优点集合起来操作岂不是更加方便?如:JDOM、DOM4J等。
五、JDOM
JDOM是使用Java语言编写的,用于读、写、操作XML的一套组件。一定要记住:JDOM = DOM修改文件的优点 + SAX读取快速的优点 。
1)使用JDOM进行XML的写操作(新建):
package com.wbf.jdom; import java.io.File; import java.io.FileOutputStream; import org.jdom2.Attribute; import org.jdom2.Document; import org.jdom2.Element; import org.jdom2.output.XMLOutputter; public class WriteXML { public static void main(String[] args) throws Exception { Element addresslist = new Element("addresslist");//定义根节点 Element linkman = new Element("linkman");//定义linkman节点 Element name = new Element("name");//定义name节点 Element email = new Element("email");//定义email节点 Attribute id = new Attribute("id", "zs");//定义属性 Document doc = new Document(addresslist);//定义一个document对象,并设置根节点 //设置节点的文本节点 name.setText("zhangsan"); email.setText("zhangsan@qq.com"); //设置节点的属性 linkman.setAttribute(id); //设置节点的父子关系 linkman.addContent(name); linkman.addContent(email); addresslist.addContent(linkman); XMLOutputter out = new XMLOutputter();//用来输出XML文件 out.setFormat(out.getFormat().setEncoding("GBK"));//设置输出的编码格式 //输出XML文件 out.output(doc, new FileOutputStream("d:" + File.separator + "jdom_demo_1.xml")); } }
被JDOM新建的XML文档jdom_demo_1.xml:
<?xml version="1.0" encoding="GBK"?> <addresslist> <linkman id="zs"> <name>zhangsan</name> <email>zhangsan@qq.com</email> </linkman> </addresslist>
2)使用JDOM进行XML的读操作:
package com.wbf.jdom; import java.io.File; import java.util.List; import org.jdom2.Document; import org.jdom2.Element; import org.jdom2.input.SAXBuilder; public class ReadXML { public static void main(String[] args) throws Exception { //使用JDOM读取XML文件 SAXBuilder builder = new SAXBuilder();//建立SAX解析 //被解析的XML文档 Document read_doc = builder.build("d:" + File.separator + "jdom_demo_1.xml"); Element root = read_doc.getRootElement(); List<Element> elements = root.getChildren("linkman"); for (int i = 0; i < elements.size(); i++) { Element e = elements.get(i);//取出一个linkman子元素 String name = e.getChildText("name");//取得name元素内容或文本节点的value String id = e.getAttribute("id").getValue();//获取linkman节点的属性id //String email = e.getChild("email").getText();//取得email元素内容 //String email = e.getChild("email").getValue();//取得email元素内容 String email = e.getChildText("email");//与前两句等价 System.out.println("------联系人-----"); System.out.println("姓名: " + name + " 编号: " + id); System.out.println("EMAIL:" + email); System.out.println("----------------"); System.out.println(); } } }
其中jdom_demo_1.xml即为前文中所示。
六、DOM4J
DOM4J也是一组XML操作的组件包,主要用来读写XML文件。由于DOM4J性能优异,功能强大,而且易用性强,所以应用广泛,如:Hibernate和Spring框架中都使用了DOM4J进行XML的解析操作。其操作与JDOM类似。
1)使用DOM4进行XML的写操作:
package com.wbf.dom4j; import java.io.File; import java.io.FileOutputStream; import org.dom4j.Document; import org.dom4j.DocumentHelper; import org.dom4j.Element; import org.dom4j.io.OutputFormat; import org.dom4j.io.XMLWriter; public class Dom4JWriter { public static void main(String[] args) throws Exception { Document doc = DocumentHelper.createDocument();//新建文档 Element addresslist = doc.addElement("addresslist");//定义根节点 Element linkman = addresslist.addElement("linkman");//定义子节点 Element name = linkman.addElement("name");//定义子节点 Element email = linkman.addElement("email");//定义子节点 linkman.addAttribute("id", "zs"); name.setText("张三");//设置name节点内容 email.setText("zhangsan@qq.com");//设置email节点内容 OutputFormat format = OutputFormat.createPrettyPrint();//设置输出格式 format.setEncoding("GBK"); //指定输出目标文件和格式 XMLWriter writer = new XMLWriter(new FileOutputStream(new File("d:" + File.separator + "dom4j_demo_1.xml")), format); //输出文件内容 writer.write(doc); //关闭输出流 writer.close(); } }
输出的XML文档如下:
<?xml version="1.0" encoding="GBK"?> <addresslist> <linkman id="zs"> <name>张三</name> <email>zhangsan@qq.com</email> </linkman> </addresslist>
2)使用DOM4进行XML的读操作:
package com.wbf.dom4j; import java.io.File; import java.util.Iterator; import org.dom4j.Document; import org.dom4j.Element; import org.dom4j.io.SAXReader; public class DOM4JReader { public static void main(String[] args) throws Exception{ //新建即将被读取的文件 File file = new File("d:" + File.separator + "dom4j_demo_1.xml"); SAXReader reader = new SAXReader();//建立SAX解析 Document doc = reader.read(file);//读取文档 Element root = doc.getRootElement();//获取根节点 Iterator iter = root.elementIterator(); while(iter.hasNext()) { Element linkman = (Element)iter.next(); System.out.println("姓名: " + linkman.elementText("name") + ", 编号: " + linkman.attributeValue("id")); System.out.println("邮件: " + linkman.elementText("email")); } } }
程序运行结果:
姓名: 张三, 编号: zs
邮件: zhangsan@qq.com
七、总结
从以上程序中可以看出,读取文件需要使用SAX建立解析器,然后通过文档依次找到根节点,再通过根节点找到每一个节点的内容。
相关文章推荐
- dom4j解析xml
- SAP ABAP解析XML方法
- XML解析 JSON解析
- Simplexml_load_string函数解析xml
- Java眼中的XML--文件读取--2 应用SAX方式解析XML
- day10_XML的解析和生成
- packages.xml和packages.list全解析
- 解析.Net框架下的XML编程技术
- Android开发:碎片Fragment完全解析fragment_main.xml/activity_main.xml
- 使用Dom4j解析XML
- Xml解析Pull解析,基础实现
- 时间:2014年3月28日21:00:49DOM解析XML
- XML的解析方式
- Delphi之通过代码示例学习XML解析、StringReplace的用法(异常控制 good)
- XmlPullParser解析xml文件
- 后台解析XML为DataTable
- xml 解析 python
- servlet获取并解析post请求发送过来的xml字符串
- android xml解析
- XML解析之PULL