幸运快3网站地址_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行,又蕴含着五个元素,比如第一本书的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元素蕴含着五个元素,本来 第三层是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")){
300	        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元素有五个子节点,分别是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();
3000	        } 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 {
300					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 {
300			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){  
3000	            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	    }
300	}

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

    <name>FrameWork</name>

    比如当解析到name同类于于 开始英文了了标签时,在第44行里,startElement会把tagname值设置成name,当解析到FramWork时,就让 它蕴含在有三个白 多标签之间,本来 会被触发第47行的characters土土办法,在其中的第52行的if判断里,就让 得知当前的标签名是name,本来 会输出FrameWork同类于于 name元素的值,当解析到</name>同类于于 开始英文了标签时,会触发第29行的endElement土土办法,在其中的300行里,会把tagName值清空。

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

    第2行针对id属性的输出是在startElement土土办法的第40行里被打印的,第3到第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土土办法要快些。