加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

XML-解析技术(dom解析,sax解析)

发布时间:2020-12-16 05:15:27 所属栏目:百科 来源:网络整理
导读:XML 解析方式分为两种: dom 和 sax dom : (Document Object Model, 即文档对象模型 ) 是 W3C 组织推荐的处理 XML 的一种方式。 sax : (Simple API for XML) 不是官方标准,但它是 XML 社区事实上的标准,几乎所有的 XML 解析器都支持。 XML 解析开发包 Ja
XML 解析方式分为两种: dom sax
dom (Document Object Model, 即文档对象模型 ) W3C 组织推荐的处理 XML 的一种方式。
sax (Simple API for XML) 不是官方标准,但它是 XML 社区事实上的标准,几乎所有的 XML 解析器都支持。
XML 解析开发包
Jaxp Jdomdom4j
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 名称(带前缀),如果限定名不可用,则为空字符串


3.characters方法

java]view plaincopy

24void characters(char[] ch,248)">25int start,

26int length)

27 SAXException

28接收字符数据的通知,可以通过new String(ch,length)构造器,创建解析出来的字符串文本.

29参数:

30ch - 来自 XML文档的字符

31start - 数组中的开始位置

length- 从数组中读取的字符的个数
那么同dom解析的是,sax解析也是依赖于由工厂对象生成解析器对象,再由解析器对象生成读取器对象进行文件的解析。
总结就是:
使用SAXParserFactory创建SAX解析工厂

SAXParserFactoryspf =SAXParserFactory.newInstance();

通过SAX解析工厂得到解析器对象

SAXParsersp =spf.newSAXParser();

通过解析器对象得到一个XML的读取器

XMLReaderxmlReader =sp.getXMLReader();

设置读取器的事件处理器

xmlReader.setContentHandler(newBookParserHandler());

解析xml文件

xmlReader.parse("book.xml");

希望对大家能有所帮助!

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读