java 中xml的使用

    XML 可擴展的標記語言
   XML 通用的數據格式標準
   在沒有XML標準時代
     1 數據可以任意格式存儲:二進制,文本格式
     2 數據的交換和分享出現麻煩
   XML 是一種通用的標準格式
     1 XML 數據格式標準
     2 可以用於文件的格式:XML 格式的文件稱爲XML 文件
     3 XML文件本身是文本文件,非常便於編輯和處理
        任何的文本編輯器都可以處理XML文件。

 

在解析xml之前要導入相應的jar包;

      XML 的語法結構:

     

<?xml version="1.0" encoding="UTF-8"?>
<!-- <?xml> 處理節點。處理指令, 建議在XML中第一行使用!處理節點之前不能用註釋! -->
<!-- 註釋節點 Comment Node  -->
<!-- 標記(標籤)tag:<標記名> 稱爲標記 
     標記有3種: <標記名>開始標記, </標記名>結束標記, <標記名/>稱爲自結束標記
     XML 中標記必須配對出現 有開始標記一定有結束標記
     <標記名/>自結束標記是 無內容的<標記名></標記名>簡寫形式
     <標記名/> == <標記名></標記名> -->
<!-- 元素(Element): 開始標記+內容+結束標記 的整體稱爲元素 
    如: <book>老夫子</book> 稱爲元素 
  元素的內容:
     可以文本節點
     可以是其他元素
     可以是文本和元素的混合體    
     可以是元素的嵌套   -->
<!-- 
  文本節點: 元素中出現的文本稱爲文本節點
 -->
<!-- 
 屬性:在元素的開始標記上可以定義元素的屬性
   屬性:屬性名=“屬性值” 
   屬性值必須使用引用
   屬性是無順序的。 -->
<!-- 
  格式良好的XML(良構)
  1 XML文檔只能有一個根元素。
  2 元素的嵌套要合理,不能交叉嵌套
   如下是錯誤的
    <book>
	<authors>
	</book>
	</authors>
  3 標記要配對
 -->
<!-- 
  因爲XML的標記和內容定義沒有約定,可以任意的擴展使用,稱爲可以擴展的標記語言!
 -->
<!-- 
  實體替換:XML的轉移字符, 當在文本節點中使用特殊符號時候,需要使用實體符號替換
  
  & = &
  < = <
  > = >
  空格=  
 -->
<!-- CDATA 段:用於聲明大段的文字,可以不進行實體替換 -->
<!-- XML 中的大小寫是敏感的。 -->
<books>
	<book id="b01" lang="cn">老夫子
		<authors>	
			<author><佚名></author>
			<author>V&A</author>
			<author><![CDATA[
				<p>測試</p>
			]]></author>
		</authors>
	</book>
	<book></book>
</books>




下面是java操作xml:

 /**
    * Java 中 XML 文件的處理
    *  1 直接使用文本流處理XML文件。
    *    使用BufferedReader讀取,使用PrintWriter寫出。
    *    缺點:無法識別XML語法,不能按照元素進行處理
    *    優點:快!
    *  2 使用XML API 處理XML文檔,W3C 提供了兩種標準的XML API 
    *    SAX:
    *    優點:支持XML的語法,只支持讀取操作,速度快, 佔用內存小
    *    缺點:不能寫XML,使用繁瑣
    *    DOM:支持XML語法,速度沒有SAX快,佔用內存大,支持讀寫操作
    *    
    *    DOM4j:是第三方提供的API,不是W3C的標準,底層封裝了 W3C DOM, 
    *       DOM4j API 簡潔方便(比W3C DOM 方便!)  
    */
	//@Test
	public void testSAXAPI(){
		//利用SAX API 讀取書籍的名字
		// 1 打開文件流 Class getResource;
		// 2 創建SAX 處理器(過濾器)
		// 3 創建SAX API 讀取XML文件,並且利用處理器過濾XML文件
		// 4 在SAX處理期間,就得到了數據
		
		InputStream in = getClass().getResourceAsStream("books.xml");
		
		DefaultHandler handler = new DefaultHandler(){
			boolean foundName = false;
			@Override
			public void startElement(String uri, String localName,
					String qName, Attributes attributes) throws SAXException {
				foundName = qName.equals("name");
				//讀取book元素的id屬性
				if (qName.equals("book")) {
					String id = attributes.getValue("id");
					System.out.println("Book ID:"+id); 
				}
			}
			@Override
			public void characters(char[] ch, int start, int length)
					throws SAXException {
				if (foundName) {
					String bookName = new String(ch, start, length);
					System.out.println(bookName); 
				}
			}
			@Override
			public void endElement(String uri, String localName, String qName)
					throws SAXException {
				foundName = false;
				if(qName.equals("books")){
					throw new SAXException("結束了");
				}
			}
		};
		//使用 SAXParser 使用handler掃描讀取XML文件,
		// SAXParser: 需要使用工廠模式創建SAXParser對象
		try {
			SAXParserFactory factory = SAXParserFactory.newInstance();
			SAXParser parser = factory.newSAXParser();
			
			parser.parse(in, handler);
			//parse 方法會從流in中讀取XML文檔,當遇到XML文檔的結構時候,執行handler中適當
			// 事件處理方法 startElement endElement 等。
			// 異常: IOException 文檔讀取時候發送IO錯誤
			//      SAXException 文檔不是格式良好,時候發送
			//        解析器拋出 SAX異常結束文件的讀取
			
		} catch (ParserConfigurationException e) {
			e.printStackTrace();
		} catch (SAXException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
	}
	
	/**
	 * DOM4j  API 演示
	 */
	@Test
	public void testReadDoc(){
		try {
			InputStream in = TestCase.class.getResourceAsStream("books.xml");
			SAXReader reader = new SAXReader();
			//DOM4j 提供SAXReader,可將流讀取爲XML Doc
			//如果流讀取失敗,XML 不是良好格式,將出現異常
			Document doc = reader.read(in);
			in.close();
			//顯示讀取結果
			// Dom4j 的幾乎所有API都有方法 asXML() 可以顯示XML文檔數據
			System.out.println(doc.asXML());
			//在doc中檢索 全部的書名
			// dom4j 提供了樹型結構的導航查詢API方法
			// getRootElement() 獲取文檔的根元素
			// Element 代表內存中一個元素節點對象
			Element root = doc.getRootElement();
			//elements() 方法,可以獲取一個元素的全部子元素節點
			// 重載的 elements(元素名) 獲取一個元素的全都指定名稱的子元素
			//List<Element> list = root.elements();
			List<Element> list = root.elements("book"); 
			for(Element e: list){
				//element(元素名) 獲取一個元素的指定名稱的子元素,如果重複,發回第一個子元素
				//Element n = e.element("name");
				//元素上一個方法 getText() 用於獲取當前元素中文本內容
				//String name = n.getText();
				//getTextTrim() 方法可以獲取文本,並且取出前後空白
				//name = n.getTextTrim();
				
				//dom4j 提供了更加便捷的API用於直接讀取子元素中的文本
				String name = e.elementTextTrim("name");
				System.out.println(name); 
				
				//dom4j 可以讀取元素的屬性
				String id = e.attributeValue("id");
				System.out.println("book id:"+id);  
				//讀取元素的全部屬性
				//List<Attribute> attributes = e.attributes();
			}
			//修改內存中的DOC對象
			Element lastBook = list.get(list.size()-1);
			//setText() 方法可以修改元素節點的文本內容
			lastBook.element("price").setText("80.00"); 
			System.out.println(doc.asXML()); 
			//添加新元素等
			// 1 爲根元素增加子元素book, addElement(元素名稱) 返回新元素對象。
			Element newBook = root.addElement("book");
			// 2 增加元素
			newBook.addAttribute("id", "B03");
			newBook.addAttribute("lang", "CN");
			// 2 book增加子name元素,並且爲name增加文本內容
			newBook.addElement("name").setText("紅樓夢");
			newBook.addElement("price").setText("88.90");
			Element authors = newBook.addElement("authors");
			authors.addElement("author").setText("曹雪芹"); 
			//...
			
			System.out.println(doc.asXML()); 
			//寫出Document 對象到文件, dom4j 提供的功能
			FileOutputStream out = new FileOutputStream("myBooks.xml");
			//設置輸出格式: createPrettyPrint()創建漂亮的打印格式 
			OutputFormat format = OutputFormat.createPrettyPrint();
			XMLWriter writer = new XMLWriter(out, format);
			
			writer.write(doc);//XML Docuemnt 編碼序列化到流
			writer.close();
			
 		} catch (DocumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
	}


 

/**
	 * XML 是數據格式,不僅僅是文件
	 *  
	 *              讀取                           寫出
	 *  字符流           無語法支持,繁瑣       無語法支持,快                  寫出大規模的XML,要注意編碼和語法結構
	 *  SAX      有語法支持,簡便        不能寫出                            適合大規模的XML讀取,佔用內存小
	 *  DOM4j    有語法支持,支持讀取   有語法支持,寫出           適合小規模XML讀寫,佔用內存大
 	 *  W3C DOM   可以讀                            可以寫                             API非常繁瑣,Java業界使用DOM4j替代之
 	 *  pull解析       有語法支持,簡便             不能寫                          適合大規模的XML讀取,佔用內存小
 	 *  
 	 *  pull解析: 特點是可以任意的暫停繼續, 完全可以代替 SAX 
	 */
	//@Test
	public void testXmlPull() throws Exception{
		InputStream in = new BufferedInputStream(new FileInputStream("myBooks.xml"));
		//XmlPullParser 是接口,事例需要使用工廠創建
		XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
		XmlPullParser pullParser = factory.newPullParser();
		
		//將被解析的流交給 pullParser, 不發送解析操作
		pullParser.setInput(new InputStreamReader(in, "utf-8"));
		
		//解析獲取全部的書名
		
		boolean found = false;
		Scanner scanner = new Scanner(System.in);
		//COMMENT 遇到了註釋
		//循環一直持續到 發生文件末尾事件爲止
		main:
		for(int event = pullParser.getEventType();
				event !=END_DOCUMENT; 
				event = pullParser.nextToken()){
			//event = START_DOCUMENT COMMENT START_TAG TEXT START_TAG TEXT
			switch (event) {
			case COMMENT:
				System.out.println(pullParser.getText());//抓取註釋的文本
				break ;
			case START_TAG:
				//從 XmlPullParser中拉取元素的開始標記名
				String name = pullParser.getName(); 
				if(name.equals("book")){
					String id = pullParser.getAttributeValue(0);
					System.out.println(id);
				}
				found = name.equals("name"); 
				break;
			case TEXT:
				if (found) {
					//拉取文本
					String text = pullParser.getText().trim();
					System.out.println(text);
				}
				break;
			case END_TAG:
				found = false;
			}
		}
		in.close();
				
		
	}
	
	/** 靜態導入 */
	//@Test
	public void testStaticImport(){
		double x = sin(PI);
		System.out.println(x); 
	}
	
	/**
	 * w3school.com.cn 中文  
	 * w3schools.com   英文
	 * xpath 是XML 的一種查詢語法
	 * myBooks.xml
	 * 抓取全部的 書名 節點的集合 
	 * String xpath = "/books/book/name"
	 * 在DOM對象上查找,就可以獲取全部滿足xpath的 Element對象
	 * dom4j 支持 xpath查找,在內存的Dom對象中查找 子節點
	 * 
	 * 1 xpath 的語法
	 * 2 dom4j API 支持xpath 查詢
	 *    1 支持根部絕對路徑查詢
	 *      doc.selectNodes(xpath)   返回一個集合,包含全部滿足條件的節點
	 *      doc.selectSingleNode(xpath) 返回第一個匹配的節點
	 *    2 支持相對路徑查詢,從某個元素節點開始執行查詢
	 *      如 Element book 節點
	 *         book.selectNodes(xpath) 
	 *         book.selectSingleNode(xpath)
	 */
	//@Test
	public void testXpath() throws Exception{
		//打開Dom4j DOM 對象
		SAXReader reader = new SAXReader();
		Document doc = reader.read(new File("myBooks.xml"));
		//selectNodes 是在DOM 上執行xpath查詢,將滿足條件的元素 都作爲返回值返回
		String xpath = "/books/book/name";
		List<Element> list = doc.selectNodes(xpath);
		//
		for (Element e : list) {
			System.out.println(e.asXML()); 
		}
	}
	public void testSelectSingleNode(String xpath) throws Exception{
		//打開Dom4j DOM 對象
		SAXReader reader = new SAXReader();
		Document doc = reader.read(new File("myBooks.xml"));
		Node node = doc.selectSingleNode(xpath);
		System.out.println(node.asXML());
	}
	public void testSelectNodes(String xpath) throws Exception{
		SAXReader reader = new SAXReader();
		Document doc = reader.read(new File("myBooks.xml"));
		List<Node> list = doc.selectNodes(xpath);
		for (Node node : list) {
			System.out.println(node.asXML()); 
		}
	}
	@Test
	public void testXPath() throws Exception{
		//testSelectSingleNode("/books"); 
		//testSelectNodes("/books/book");  
		//testSelectNodes("//.");  
		//XPATH 可以理解爲 一層一層的過濾
		// "//" 代表所有節點, //author 所有節點中名字爲author的節點。
		//testSelectNodes("//author");//查詢結果節點是Element類型
		
		//查詢所有節點中的 id屬性節點
		//testSelectNodes("//@id");//查詢結果節點是Attribute類型
		
		// DOM 節點的分類關係
		/* Node 節點
		 *  |-- Document 文檔節點
		 *  |     |-- 只能包含一個根元素
		 *  |-- Element  元素節點 
		 *  |    |-- 可以包含其他節點和文本
		 *  |-- Comment 註釋節點
		 *  |-- Text 文本節點
		 *  |-- Attribute 屬性節點
		 */
		//testSelectNodes("/books/book[1]");
		//testSelectNodes("/books/book[last()]"); 
		//testSelectNodes("/books/book[1]/name");
		//testSelectNodes("/books/book[last()]/name"); 
		//testSelectNodes("/books/book[1]/authors/author[1]"); 	
		//testSelectNodes("/books/book[1]/authors/athor[1]"); 	
		//book有id屬性被查詢出來
		//testSelectNodes("/books/book[@id]"); 	
		 
		//testSelectNodes("/books/book[@id and price>85 and position()=1]"); 
		
		testSelectNodes("//*[.>85]"); 
		//  /*/*  與   /books/book  區別
	}


 

發佈了50 篇原創文章 · 獲贊 1 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章