XML-解析技术(dom解析,sax解析)
XML
解析方式分为两种:
dom
和
sax
dom
:
(Document Object Model,
即文档对象模型
)
是
W3C
组织推荐的处理
XML
的一种方式。
sax
:
(Simple API for XML)
不是官方标准,但它是
XML
社区事实上的标准,几乎所有的
XML
解析器都支持。
XML
解析开发包
Jaxp
、Jdom、dom4j
JAXP
开发包是
J2SE
的一部分,它由
javax.xml
、
org.w3c.dom
、
org.xml.sax
包及其子包组成。
在
javax.xml.parsers
包中,定义了几个工厂类,程序员调用这些工厂类,可以得到对
xml
文档进行解析的
DOM
或
SAX
的解析器对象。那么接下来就让我们来通过一个实例来看看该如何使用JAXP进行DOM解析吧。
XML文件:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE classes SYSTEM "bin//parsers//java.dtd"> <classes> <java班 name="CSDNJava01班"> <teachers> <teacher name="军哥" sex="男" age="28" /> <teacher name="刘丽华" sex="女" age="28" /> </teachers> <students> <student id="x121"> <name>王亮</name> <sex>男</sex> <age>28</age> </student> </students> </java班> <!-- 注释 --> <net班 name="CSDNNet01班"> <teachers> <teacher name="Boss姚" sex="男" age="28" /> <teacher name="石老师" sex="女" age="28" /> </teachers> </net班> <php班 name="CSDNPhp01班"></php班> <ios班 name="CSDNIos01班"></ios班> </classes> <!-- 对java.xml文件进行CRUD的操作 --> <!-- 节点 nodeName nodeValue nodeType 名称 元素 element 标签 null 1 文本 text #text 文本值 3 属性 Attr 属性名 属性值 2 声明类型 10 注释 8--> 约束文件: <!ELEMENT classes (java班,net班,php班,ios班)> <!ELEMENT java班 (teachers?,students?)> <!ELEMENT net班 (teachers?,students?)> <!ELEMENT php班 (teachers?,students?)> <!ELEMENT ios班 (teachers?,students?)> <!ELEMENT teachers (teacher*)> <!ELEMENT teacher EMPTY> <!ELEMENT students (student*)> <!ELEMENT student (name,sex,age)> <!ATTLIST java班 name CDATA #IMPLIED> <!ATTLIST net班 name CDATA #IMPLIED> <!ATTLIST php班 name CDATA #IMPLIED> <!ATTLIST ios班 name CDATA #IMPLIED> <!ATTLIST teacher name CDATA #IMPLIED> <!ATTLIST teacher sex CDATA #IMPLIED> <!ATTLIST teacher age CDATA #IMPLIED> <!ELEMENT name (#PCDATA)> <!ELEMENT sex (#PCDATA)> <!ELEMENT age (#PCDATA)> <!ATTLIST student id ID #IMPLIED> 解析测试类: import java.io.IOException; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.junit.Test; import org.w3c.dom.Attr; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; public class Dom { @Test public void test() throws ParserConfigurationException,SAXException,IOException { // 调用 DocumentBuilderFactory.newInstance() 方法得到创建 DOM 解析器的工厂。 DocumentBuilderFactory builderFactory = DocumentBuilderFactory .newInstance(); // 调用工厂对象的 newDocumentBuilder方法得到 DOM 解析器对象。 DocumentBuilder builder = builderFactory.newDocumentBuilder(); // 解析指定的文件(返回Document对象) Document document = builder.parse(this.getClass().getClassLoader() .getResourceAsStream("parsers//java.xml")); // System.out.println(document + "-----"); // getInfo(document); //list(document); listNodes(document.getDocumentElement());//这是一种便捷属性,该属性允许直接访问文档的文档元素的子节点 // System.out.println("URI为:"+document.getDocumentURI()); } /** * 根据document对象获取一些相关的信息 * * @param document */ public void getInfo(Document document) { System.out.println("当前文件版本为:" + document.getXmlVersion()); System.out.println("DOCTYPE:" + document.getDoctype().getNodeType()); System.out.println("根标签:" + document.getDoctype().getName()); System.out.println("SYSTEMID:" + document.getDoctype().getSystemId()); } /** * 遍历文档 */ public void list(Document document) { // javaScript NodeList nodeList = document.getElementsByTagName(document.getDoctype() .getName()); for (int i = 0; i < nodeList.getLength(); i++) { // 获取指定的节点 Node node = nodeList.item(i); listNodes(node); // 节点是什么类型的节点 // System.out.println(node.getNodeType());// 返回整形 /* * if (node.getNodeType() == 1) {// 判断是否是元素节点 Element element = * (Element) node; NodeList listnode = * element.getChildNodes();//获取所有子元素 //遍历 for(int * j=0;j<listnode.getLength();j++){ Node nd=listnode.item(j); * listNodes(node); } } */ /* * if (node instanceof Element) { * System.out.println("node---------"); } */ } } /** * 遍历根据节点对象下面的所有的节点对象 * * @param node */ public void listNodes(Node node) { if (node.getNodeType() == Node.ELEMENT_NODE) {// 判断是否是元素节点 Element element = (Element) node; if (element.hasAttributes()) { NamedNodeMap namenm = element.getAttributes(); // 遍历 for (int k = 0; k < namenm.getLength(); k++) { Attr attr = (Attr) namenm.item(k); System.out.println("name:" + attr.getNodeName() + " value:" + attr.getNodeValue() + " type:" + attr.getNodeType()); } } NodeList listnode = element.getChildNodes();// 获取所有子元素 // 遍历 for (int j = 0; j < listnode.getLength(); j++) { Node nd = listnode.item(j); System.out.println("name:" + nd.getNodeName() + " value:" + nd.getNodeValue() + " type:" + nd.getNodeType()); listNodes(nd); } } } } 再来看看sax解析,在解析之前我们先来看看两者的区别:
在使用
DOM
解析
XML
文档时,需要读取整个
XML
文档,在内存中构架代表整个
DOM
树的
Doucment
对象,从而再对
XML
文档进行操作。此种情况下,如果
XML
文档特别大,就会消耗计算机的大量内存,并且容易导致内存溢出。
SAX
解析允许在读取文档的时候,即对文档进行处理,而不必等到整个文档装载完才会文档进行操作。
具体操作:
SAX
采用事件处理的方式解析
XML
文件,利用
SAX
解析
XML
文档,涉及两个部分:解析器和事件处理器:
解析器可以使用
JAXP
的
API
创建,创建出
SAX
解析器后,就可以指定解析器去解析某个
XML
文档。
解析器采用
SAX
方式在解析某个
XML
文档时,它只要解析到
XML
文档的一个
组成部分
,都会去调用事件处理器的一个方法,解析器在调用事件处理器的方法时,会把当前解析到的
xml
文件内容作为
方法的参数
传递给事件处理器。
事件处理器由程序员编写,程序员通过事件处理器中方法的参数,就可以很轻松地得到
sax
解析器解析到的数据,从而可以决定如何对数据进行处理。
那么接下来就通过一个实例来看看那该如何用sax进行对xml文件的解析:
xml文件:
<!DOCTYPE 四大名著[ <!ELEMENT 四大名著 (西游记,红楼梦)> <!ATTLIST 西游记 id ID #IMPLIED> ]> <四大名著> <西游记 id="x001"> <作者>吴承恩</作者> </西游记> <红楼梦 id="x002"> <作者>曹雪芹</作者> </红楼梦> </四大名著> 两种解析的方法(通过实现处理器接口,以及继承处理器的实现类): import java.io.File; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import org.junit.Test; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; public class SaxTest { @Test public void test() throws Exception{ //sax解析器工厂对象 SAXParserFactory factory=SAXParserFactory.newInstance(); //工厂对象 创建解析器对象 SAXParser saxParser=factory.newSAXParser(); //已学的几种模式 工厂模式 装饰模式 单例模式 saxParser.parse(new File("src//sax//sida.xml"),new MyDefaultHandler()); } class MyDefaultHandler extends DefaultHandler{ boolean isOk=false; @Override public void startDocument() throws SAXException { super.startDocument(); System.out.println("文档开始解析了。。。。。"); } @Override public void startElement(String uri,String localName,String qName,Attributes attributes) throws SAXException { super.startElement(uri,localName,qName,attributes); if("作者".equals(qName)){ isOk=true; System.out.println("作者---开始"); } } @Override public void characters(char[] ch,int start,int length) throws SAXException { super.characters(ch,start,length); if(isOk){ System.out.println(new String(ch,length)); } } @Override public void endElement(String uri,String qName) throws SAXException { super.endElement(uri,qName); if("作者".equals(qName)){ System.out.println("作者---完毕"); isOk=false; } } @Override public void endDocument() throws SAXException { super.endDocument(); System.out.println("文档解析完毕了。。。。。"); } } }
效果:
import java.io.InputStream; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import org.junit.Test; import org.xml.sax.Attributes; import org.xml.sax.ContentHandler; import org.xml.sax.InputSource; import org.xml.sax.Locator; import org.xml.sax.SAXException; import org.xml.sax.XMLReader; public class SaxTest1 { @Test public void test() throws Exception{ //sax机械器工厂 SAXParserFactory factory=SAXParserFactory.newInstance(); //工厂对象 创建解析器对象 SAXParser saxParser=factory.newSAXParser(); XMLReader reader=saxParser.getXMLReader(); InputStream is=this.getClass().getClassLoader().getResourceAsStream("sax//sida.xml"); //设置解析的操作 reader.setContentHandler(new MyContentHandler()); //进行解析 reader.parse(new InputSource(is)); } class MyContentHandler implements ContentHandler{ boolean isOk=false; @Override public void setDocumentLocator(Locator locator) { } @Override public void startDocument() throws SAXException { System.out.println("文档开始解析了。。。。。"); } @Override public void endDocument() throws SAXException { System.out.println("文档解析完毕了。。。。。"); } @Override public void startPrefixMapping(String prefix,String uri) throws SAXException { // TODO Auto-generated method stub } @Override public void endPrefixMapping(String prefix) throws SAXException { // TODO Auto-generated method stub } @Override public void startElement(String uri,Attributes atts) throws SAXException { if("作者".equals(qName)){ isOk=true; System.out.println("作者---开始"); } } @Override public void endElement(String uri,String qName) throws SAXException { if("作者".equals(qName)){ isOk=false; System.out.println("作者---结束"); } } @Override public void characters(char[] ch,int length) throws SAXException { if(isOk){ System.out.println(new String(ch,length)); } } @Override public void ignorableWhitespace(char[] ch,int length) throws SAXException { // TODO Auto-generated method stub } @Override public void processingInstruction(String target,String data) throws SAXException { // TODO Auto-generated method stub } @Override public void skippedEntity(String name) throws SAXException { // TODO Auto-generated method stub } } } 效果:
在这里再给大家说些读取器内部的一些方法的使用:
1.startElement方法说明 1void startElement(String uri, 2String localName, 3String qName, 4Attributes atts) 5throws SAXException 6方法说明: 7解析器在XML 文档中的每个元素的开始调用此方法;对于每个 startElement 事件都将有相应的 endElement 事件(即使该元素为空时)。所有元素的内容都将在相应的endElement 事件之前顺序地报告。 8 9参数说明: 10uri - 名称空间URI,如果元素没有名称空间 URI,或者未执行名称空间处理,则为空字符串 11localName - 本地名称(不带前缀),如果未执行名称空间处理,则为空字符串 12qName - 限定名(带有前缀),如果限定名不可用,则为空字符串 13atts - 连接到元素上的属性。如果没有属性,则它将是空 Attributes 对象。在 startElement 返回后,此对象的值是未定义的 2.endElement方法说明 [java]view plaincopy
14void endElement(String uri,248)">1516StringqName) 17throws SAXException接收元素结束的通知。 18SAX 解析器会在XML 文档中每个元素的末尾调用此方法;对于每个 endElement 事件都将有相应的 startElement 事件(即使该元素为空时)。 19 20参数: 21名称空间URI,如果元素没有名称空间 URI,或者未执行名称空间处理,则为空字符串 22localName - 本地名称(不带前缀),如果未执行名称空间处理,则为空字符串 23限定的 XML 名称(带前缀),如果限定名不可用,则为空字符串
java]view plaincopy 24void characters(char[] ch,248)">25int start, 26int length) 27 SAXException 28接收字符数据的通知,可以通过new String(ch,length)构造器,创建解析出来的字符串文本. 29参数: 30ch - 来自 XML文档的字符 31start - 数组中的开始位置
那么同dom解析的是,sax解析也是依赖于由工厂对象生成解析器对象,再由解析器对象生成读取器对象进行文件的解析。
总结就是:
使用SAXParserFactory创建SAX解析工厂
SAXParserFactoryspf =SAXParserFactory.newInstance();
通过SAX解析工厂得到解析器对象
SAXParsersp =spf.newSAXParser();
通过解析器对象得到一个XML的读取器
XMLReaderxmlReader =sp.getXMLReader();
设置读取器的事件处理器
xmlReader.setContentHandler(newBookParserHandler());
解析xml文件
xmlReader.parse("book.xml");
希望对大家能有所帮助! (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |