目前XML解析的方法主要用兩種:
1、dom解析:(Document Object Model,即文檔對象模型)是W3C組織推薦的解析XML的一種方式。
使用dom解析XML文檔,該解析器會先把XML文檔加載到記憶體中,生成該XML文檔對應的document對象,然後把XML文檔中的各個标簽元素變成相應的Element對象,文本會變成Text對象,屬性會變成Attribute對象,并按這些标簽、文本、屬性在XML文檔中的關系儲存這些對象的關系。
缺點:消耗記憶體,是以使用dom解析XML文檔時不能解析太大的XML文檔,否則有可能會造成記憶體溢出。
優點:使用dom解析XML文檔可以很友善的執行增删改查操作(可以直接根據節點對應的對象進行操作)。
2、sax解析:Simple API for XML,不是官方标準,但它是XML社群事實上的标準,幾乎所有的XML解析器都支援它。
使用sax解析XML文檔,該解析器會從上往下讀,讀一行,解析一行;
優點:因為它解析XML文檔是采取讀一行,解析一行的方式,是以它不會對記憶體造成壓力。
缺點:不适合執行增删改查的操作(也是因為它解析XML文檔時采取的讀一行解析一行的方式,是以它不能往回操作),隻适合對XML文檔進行讀取操作。
======================================================================================================
補充:
XML解析開發包:Jaxp(sun)、Jdom、dom4j;
======================================================================================================
調整JVM記憶體大小:
當我們要解析的XML文檔記憶體比較大、而且要對該XML中的節點資料進行相關的操作時,使用這兩種解析方式顯然都會不友善,這時就需要調整JVM記憶體的大小了。
JVM預設的允許最大記憶體容量是64M(根據jdk的版本不同,預設的最大容量值不一樣,jdk5.0版本的是64MB,jdk7版本的是170MB)。
調整JVM記憶體大小的方法(相應的指令為:-Xmx記憶體大小值機關):
在Eclipse中的項目導航框中右擊相應的Java程式》》Run As》》Open Run Dialog...》》打開Run對話框》》選擇Arguments選項,在開視窗中有兩個輸入框,第一個是程式的參數輸入框,第二個是VM的參數輸入框,在第二個VM的參數輸入框中輸入Xmx200M》》點選右下角的Run按鈕,執行相應的Java程式,就不會報OutOfMemoryError的錯誤了。
======================================================================================================
XML解析開發包:
1、JAXP:JAXP開發包是J2SE的一部分,它由javax.xml、org.w3c.dom、org.xml.sax包及其子包組成。
在javax.xml.parsers包中,定義了幾個工廠類,程式員調用這些工廠類,可以得到XML文檔的dom或sax的解析器,進而實作對XML文檔的解析。
首先、建立工廠:
DocumentBuilderFactory factory = DocumentBuilderFactroy.newInstance();//因為DocumentBuilderFactory類是抽象類,不能new出它的對象隻能調用它的靜态方法擷取它的對象。
其次、得到dom解析器:
DocumentBuilder builder = factory.newDocumentBuilder();
然後、加載XML文檔,得到代表文檔的Document對象:
Document document = builder.parse("*.xml");
拿到代表XML文檔的document對象就可以操作XML文檔中的各個節點了。
======================================================================================================
補充:
dom解析下,XML文檔的每一個組成部分都會用一個對象表示,例如标簽用Element,屬性用Attribute,但不管什麼對象,都是Node的子類,是以在開發中可以把擷取到的任意節點都當作Node對待。
XML程式設計(CRUD)
create、read、update、delete
添加、查詢、更新、删除;
除了這兩種解析方法外,還有另外的解析方法。。。
======================================================================================================
在對XML文檔進行添加、修改和删除操作時,不僅要更新document對象還要更新XML文檔(把更新後的document對象重寫到XML文檔中)。
javax.xml.transform包中的Transformer類用于把代表XML文檔的Document對象轉換為某種格式後輸出,例如把XML文檔應用樣式表後轉換成一個HTML文檔。利用這個對象,當然也可以把Document對象又重新寫入到一個XML文檔中。源和目的地。可以通過:
javax.xml.transform.dom.DOMSource類來關聯要轉換的document對象,
用javax.xml.transform.stream.StreamResult對象來表示資料的目的地。
Transformer對象通過TransformerFactory獲得。
Transformer類通過transform方法完成轉換操作,該方法接收個
(工廠對象(TransformerFactory)》》》轉換器對象(Transformer)》》》轉換方法(transform(DOMSource 源,StreamResult 目的地);))
======================================================================================================
SAX解析:
SAX解析采用事件處理的方式解析XML檔案,利用SAX解析XML文檔,涉及兩個部分:解析器和事件處理器:
解析器可以使用JAXP的API建立,建立出SAX解析器後,就可以指定解析器去去解析某個XML文檔。
解析器采用SAX方式在解析某個XML文檔時,它隻要解析到XML文檔的一個指定部分,都會去調用事件處理器的一個方法,解析器在調用事件處理器的方法時,會把目前解析到的XML檔案内容作為方法的參數傳遞給事件處理器。
事件處理器由程式員編寫,程式員通過事件處理器中方法的參數,就可以很輕松的得到SAX解析器解析到的資料,進而可以決定如何對資料進行處理。
1、建立解析工廠;
SAXParserFactory fac = SAXParserFactory.newInstance();
2、擷取解析器;
SAXParser sp = fac.newSAXParser();
3、得到讀取器;
XMLReader re = sp.getXMLReader();
4、設定内容處理器;
re.setContentHandler(new ContentHandler(){ });
(或者:re.setContentHandler(new DefaultHandler());)
第一種方法是解析整個XML文檔,第二種方法可以隻解析某個标簽;
其實還有一種内容處理器,也是先繼承DefaultHandler類,然後把解析的内容封裝到bean對象中。
5、讀取XML文檔内容;
re.parse("*.xml");
======================================================================================================
XML解析開發包:
2、dom4j:
SAXReader saxReader = new SAXReader();
Document doc = saxReader.read(new File());
OutputFormat format = OutputFormat.createPrettyPrint();//該對象标明格式按漂亮的格式進行輸出;另外還有一個對象是按緊湊的格式進行輸出;
format.setEncoding("UTF-8");
XMLWriter xmlWriter = new XMLWriter(new FileOutputStream(),format);
xmlWriter.write(doc);//如果xmlWriter對象采用的流是位元組流,那麼該對象會先把doc對象按format對象給定的編碼格式轉換成位元組,然後把資料交給位元組流進行操作。
writer.close();//最後要關閉資源
======================================================================================================
XPath:
使用XPath可以快速定位到某個節點;
List list = document.selectNodes("//foo/bar");//擷取foo節點下的所有bar節點;
Node node = document.selectSingleNode("//foo/bar");//擷取foo節點下的第一個bar節點;
單斜杠是絕對路徑即從根節點開始;
雙斜杠是相對路徑即從所有目前節點開始;
星号“*”表示選擇所有由星号之前的路徑所定位的元素;
例如:
/aa/bb*/*/bbb表示選擇所有的有3個祖先元素的bbb元素;
//bb[@*]表示選擇有任意屬性的bb元素;
//bb[not(@*)]表示選擇沒有屬性的bb元素;
//bb[@id='b1']表示選擇含有屬性id='b1'的bb元素;