大发pk10彩金 _Java解析XML文件的方式

  • 时间:
  • 浏览:0

    在项目里,我们歌词 我们歌词 我们歌词 我们歌词 歌词 往往会把你这个 配置信息插进xml文件里,以前各部门间会通过xml文件来交换业务数据,很多很多 有以前我们歌词 我们歌词 我们歌词 我们歌词 歌词 会遇到“解析xml文件”的需求。一般来讲,有基于DOM树和SAX的两种生活解析xml文件的办法 ,在这要素里,将分别给我们歌词 我们歌词 我们歌词 我们歌词 歌词 演示通过你你这个 种生活办法 解析xml文件的一般步骤。

1 XML的文件格式

    XML是可扩展标记语言(Extensible Markup Language)的缩写,在其中,结束了了了英文标签和结束了了了英文标签不能 配套地冒出,我们歌词 我们歌词 我们歌词 我们歌词 歌词 来看下book.xml你你这个 例子。   

1	<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2	<books>
3	    <book id="01">
4	        <name>Java</name>
5	        <price>15</price>
6	        <memo>good book</memo>
7	    </book>
8	    <book id="02">
9	       <name>FrameWork</name>
10	       <price>20</price>
11	       <memo>new book</memo>
12	    </book>
13	</books>

    整个xml文件是一个多文档(document),其中第1行表示文件头,在第2和第13行里,我们歌词 我们歌词 我们歌词 我们歌词 歌词 能看过配套冒出的books标签,从标签头到标签尾的要素原来们称之为元素(element)。

    很多很多 我们歌词 我们歌词 我们歌词 我们歌词 歌词 还不能原来说,在books元素里,我们歌词 我们歌词 我们歌词 我们歌词 歌词 分别于第3到第7行和第8到第12行定义了一个多book元素,在每个book元素,比如从第4到第6行,又涵盖着5个元素,比如第一本书的name元素是<name>Java</name>,它的name元素值是Java。

    在第3行里,我们歌词 我们歌词 我们歌词 我们歌词 歌词 还能看过元素里的属性(attribute),比如你你这个 book元素具有id你你这个 属性,具体id的属性值是01。

2 基于DOM树的解析办法

    DOM是Document Object Model(文档对象模型)的缩写,在基于DOM树的解析办法 里,解析代码会先把xml文档读到内存里,并挂接成DOM树的形式,而是再读取。根据以不能 素里给出的book.xml文档,我们歌词 我们歌词 我们歌词 我们歌词 歌词 还不能绘制出如下形式的DOM树。

    

     其中,books属于根(root)结点,也叫根元素,以前它涵盖着一个多book元素,很多很多 第二层是一个多book结点,每个book元素涵盖着5个元素,很多很多 第三层是6个元素。在下面的ParserXmlByDom.java的代码里,我们歌词 我们歌词 我们歌词 我们歌词 歌词 来看下通过DOM树办法 解析book.xml文档的删改步骤。

1	//省略import相关类库的代码
2	public class ParserXmlByDom {
3		public static void main(String[] args) {
4	        //创建DOM工厂
5			DocumentBuilderFactory domFactory=DocumentBuilderFactory.newInstance();
6			InputStream input = null;
7	        try {
8	            //通过DOM工厂获得DOM解析器
9	            DocumentBuilder domBuilder=domFactory.newDocumentBuilder();
10	            //把XML文档转化为输入流
11	            input=new FileInputStream("src/book.xml");            
12	            //解析XML文档的输入流,得到一个多Document
13	            Document doc=domBuilder.parse(input);

    从第5行到第13行,我们歌词 我们歌词 我们歌词 我们歌词 歌词 完成了用DOM树解析XML文件的准备工作,具体包括,在第5行里创建了DOM工厂,在第9行通过DOM工厂创建了解析xml文件DocumentBuilder类型对象,在第11行把待解析的xml文件插进到一个多InputStream类型的对象里,在第13行通过parse办法 把xml文档解析成一个多基于DOM树形态学 的Document类型对象。    

14	            //得到XML文档的根节点,非要根节点是Element类型
15	            Element root=doc.getDocumentElement();
16	            // 得到子节点
17	            NodeList books = root.getChildNodes();

    整个XML文件涵盖在第13行定义的doc对象里,在第15行里,我们歌词 我们歌词 我们歌词 我们歌词 歌词 通过getDocumentElement办法 得到了根节点(也我希望books节点),在第17行,通过getChildNoes办法 得到该books节点下的所有子节点,而是结束了了了英文解析整个xml文档。

    不能 说明的是,在解析前,我们歌词 我们歌词 我们歌词 我们歌词 歌词 会通过观察xml文档来了解其中的元素名和属性名,很多很多 在后继的代码里,我们歌词 我们歌词 我们歌词 我们歌词 歌词 会针对元素名和属性名进行编程。    

18	            if(books!=null){
19	                for(int i=0;i<books.getLength();i++){
20	                    Node book=books.item(i);
21	                    //获取id属性                      
22	                    if(book.getNodeType()==Node.ELEMENT_NODE){
23	                        String id=book.getAttributes().getNamedItem("id").getNodeValue();
24	                        System.out.println("id is:" + id);
25	                        //遍历book下的子节点
26	                        for(Node node=book.getFirstChild(); node!=null;node=node.getNextSibling()){
27	if(node.getNodeType()==Node.ELEMENT_NODE){
28	    //依次读取book里的name,price和memo一个多子元素
29	    if(node.getNodeName().equals("name")){
400	        String name=node.getFirstChild().getNodeValue();
31	        System.out.println("name is:" + name);                                    
32	    }
33	    if(node.getNodeName().equals("price")){
34	        String price=node.getFirstChild().getNodeValue();
35	        System.out.println("price is:" + price);
36	    }
37	    if(node.getNodeName().equals("memo")){
38	          String memo=node.getFirstChild().getNodeValue();
39	          System.out.println("memo is:" + memo);
40	     }
41	   }
42	 }
43	}
44	}
45	}

    第19行的for循环里,我们歌词 我们歌词 我们歌词 我们歌词 歌词 是遍历book元素通过观察xml文件,我们歌词 我们歌词 我们歌词 我们歌词 歌词 发现book元素冒出了2次,所有你你这个 循环会运行两次,而是,book元素二个多id属性,所有我们歌词 我们歌词 我们歌词 我们歌词 歌词 不能 通过第23行的代码,得到id属性的值。

    在文档里,book元素有5个子节点,分别是name,price和memo,很多很多 在代码的26行里,再次使用for循环遍历其中的子节点。在遍历时,我们歌词 我们歌词 我们歌词 我们歌词 歌词 通过29到32行的代码获取到了book元素里name的值,通过类似的代码后继的33到40行代码里得到了price和memo你你这个 个多元素的值。    

46	        } catch (ParserConfigurationException e) {
47	            e.printStackTrace();
48	        } catch (FileNotFoundException e) {
49	            e.printStackTrace();
400	        } catch (IOException e) {
51	            e.printStackTrace();
52	        } catch (SAXException e) {			
53				e.printStackTrace();
54			} catch (Exception e) {			
55				e.printStackTrace();
56			}
57	        //在finally里关闭io流 
58	        finally{
59	        	try {
400					input.close();
61				} catch (IOException e) {
62					e.printStackTrace();
63				}
64	        }
65		}
66	}

    同样地,在解析完成后,在finally从句里,我们歌词 我们歌词 我们歌词 我们歌词 歌词 关闭了以前用到的IO流(input对象)。

3 基于事件的解析办法

    SAX是Simple API for XML的缩写,不同于DOM的文档驱动,它是事件驱动的,也我希望说,它是两种生活基于回调(callback)函数的解析办法 ,比如结束了了了英文解析xml文档时,会调用我们歌词 我们歌词 我们歌词 我们歌词 歌词 此人 定义的startDocument函数,从下表里,我们歌词 我们歌词 我们歌词 我们歌词 歌词 能看过基于SAX办法 里的各种回调函数以及它们被调用的时间点。

函数名

调用时间点

startDocument

结束了了了英文解析xml文档时(解析xml文档第一个多字符时)会被调用

endDocument

当解析完xml文档时(解析到xml文档最后一个多字符时)会被调用

startElement

当解析到结束了了了英文标签后要 被调用,比如在解析“<name>FrameWork</name>”你你这个 element时,当读到结束了了了英文标签“<name>”时,会被调用

endElement

当解析到结束了了了英文标签后要 被调用,比如在解析“<name>FrameWork</name>”你你这个 element时,当读到结束了了了英文标签“</name>”时,会被调用

characters

1行结束了了了英文后,遇到结束了了了英文或结束了了了英文标签以前居于字符,则会调用

2一个多标签之间,居于字符,则会调用,比如在解析“<name>FrameWork</name>”时,发现居于FrameWork,则会被调用

3标签和行结束了了了英文符以前居于字符,则会调用

    从上表里我们歌词 我们歌词 我们歌词 我们歌词 歌词 能看过characters办法 会在多个场合被回调,但我们歌词 我们歌词 我们歌词 我们歌词 歌词 最期望的调用场景是第2种,这就要求我们歌词 我们歌词 我们歌词 我们歌词 歌词 最好在解析xml文档前挂接下它的格式,尽量出理 第1和第3种情况汇报。在ParserXmlBySAX.java你你这个 案例中,我们歌词 我们歌词 我们歌词 我们歌词 歌词 通过了编写上述的回调函数,实现了SAX办法 解析xml文档的功能。    

1	//省略import的代码
2	//基于SAX的解析代码不能

继承DefaultHandler类
3	public class ParserXmlBySAX extends DefaultHandler{
4		// 记录当前解析到的节点名
5		private String tagName; 
6		//主办法

7		public static void main(String[] argv) {
8			String uri = "src/book.xml";
9			try {
10				SAXParserFactory parserFactory = SAXParserFactory.newInstance();
11				ParserXmlBySAX myParser = new ParserXmlBySAX();
12				SAXParser parser = parserFactory.newSAXParser();
13				parser.parse(uri, myParser);
14			} catch (IOException ex) {
15				ex.printStackTrace();
16			} catch (SAXException ex) {
17				ex.printStackTrace();
18			} catch (ParserConfigurationException ex) {
19				ex.printStackTrace();
20			} catch (FactoryConfigurationError ex) {
21				ex.printStackTrace();
22			}		
23		}

    在main办法 的第8行里,我们歌词 我们歌词 我们歌词 我们歌词 歌词 指定了待解析xml文档的路径和文件名,在第10行里,我们歌词 我们歌词 我们歌词 我们歌词 歌词 创建了SAXParserFactory你你这个 类型的SAX解析工厂对象。在第12行,我们歌词 我们歌词 我们歌词 我们歌词 歌词 通过SAX解析工厂对象,创建了SAXParser你你这个 类型的解析类。在第13行,通过了parse办法 启动了解析。

    在上文里我们歌词 我们歌词 我们歌词 我们歌词 歌词 就以前知道,在SAX的办法 里,是通过调用各种回调函数来完成解析的,很多很多 在代码里,我们歌词 我们歌词 我们歌词 我们歌词 歌词 还得自定义各个回调函数,代码如下。    

// 出理

到文档结尾时,直接输出,不做任何动作
25		public void endDocument() throws SAXException {
26			System.out.println("endDocument");
27		}
28		// 出理

到结束了了了英文标签时,把记录当前标签名的tagName设置成null
29		public void endElement(String uri, String localName, String qName) throws SAXException {
400			tagName = null;
31		}
32		// 结束了了了英文出理

文档时,直接输出,不做任何动作
33		public void startDocument() throws SAXException {
34			System.out.println("startDocument");		
35		}
36		// 出理

结束了了了英文标签
37		public void startElement(String uri, String localName, String name,Attributes attributes) throws SAXException {	
38			if ("book".equals(name)) { //解析book标签的属性 
39	            for (int i = 0; i < attributes.getLength(); i++) {
40	                System.out.println("attribute name is:" + attributes.getLocalName(i)  + "  attribute value:" + attributes.getValue(i)); 
41	            }            
42	        }
43	        //把当前标签的名字记录到tagName你你这个

变量里  
44			tagName = name; 
45		}
46	    //通过你你这个

办法

解析book的一个多子元素的值
47		public void characters(char[] ch, int start, int length)  
48	            throws SAXException {  
49	        if(this.tagName!=null){  
400	            String val=new String(ch,start,length);            
51	            //以前是name,price或memo,则输出它们的值
52	            if("name".equals(tagName))
53	            { System.out.println("name is:" + val);  }
54	            if("price".equals(tagName))
55	            { System.out.println("price is:" + val); }
56	            if("memo".equals(tagName))
57	            { System.out.println("memo is:" + val);  }
58	        }  
59	    }
400	}

    我们歌词 我们歌词 我们歌词 我们歌词 歌词 用tagName来保存当前的标签名,是为了解析book元素的name,price和memo你你这个 个多子元素。

    <name>FrameWork</name>

    比如当解析到name你你这个 结束了了了英文标签时,在第44行里,startElement会把tagname值设置成name,当解析到FramWork时,以前它涵盖在一个多标签之间,很多很多 会被触发第47行的characters办法 ,在其中的第52行的if判断里,以前得知当前的标签名是name,很多很多 会输出FrameWork你你这个 name元素的值,当解析到</name>你你这个 结束了了了英文标签时,会触发第29行的endElement办法 ,在其中的400行里,会把tagName值清空。

    这段代码的输出结果如下,其中第1行和第10行分别是在结束了了了英文解析和完成解析时输出的。

    第2行针对id属性的输出是在startElement办法 的第40行里被打印的,第3到第5行针对5个book子元素的输出是在characters办法 里被打印的。

    第2到第5行是针对第一个多book元素的输出,而第6到第9行是针对第一个多book。    

1	startDocument
2	attribute name is:id  attribute value:01
3	name is:Java
4	price is:15
5	memo is:good book
6	attribute name is:id  attribute value:02
7	name is:FrameWork
8	price is:20
9	memo is:new book
10	endDocument

4 DOM和SAX两种生活解析办法 的应用场景

    在基于DOM的办法 里,以前我们歌词 我们歌词 我们歌词 我们歌词 歌词 会把整个xml文档以DOM树的办法 装载到内存里,很多很多 还不能边解析边修改,而是还能再次解析以前被解析过的内容。

    而在SAX的办法 里,以前我们歌词 我们歌词 我们歌词 我们歌词 歌词 是以基于回调函数的办法 来解析,很多很多 不须不能 把整个文档载入到内存,原来能节省内存资源。

    很多很多 说,取舍 DOM 还是 SAX,这取决于如下一个多个因素。

    第一,以前我们歌词 我们歌词 我们歌词 我们歌词 歌词 在解析时还打算更新xml里的数据,非要 建议使用DOM办法 。

    第二,以前待解析的文件过大,把它删改装载到内存时原来会 影响到内存性能,非要 建议使用SAX的办法 。

    第三,以前我们歌词 我们歌词 我们歌词 我们歌词 歌词 对解析的速率单位有一定的要求,非要 建议使用SAX办法 ,以前它比DOM办法 要快些。