XML文件解析
作者:xcbeyond
瘋狂源自夢想,技術(shù)成就輝煌!微信公眾號:《程序猿技術(shù)大咖》號主,專注后端開發(fā)多年,擁有豐富的研發(fā)經(jīng)驗,樂于技術(shù)輸出、分享,現(xiàn)階段從事微服務架構(gòu)項目的研發(fā)工作,涉及架構(gòu)設計、技術(shù)選型、業(yè)務研發(fā)等工作。對于Java、微服務、數(shù)據(jù)庫、Docker有深入了解,并有大量的調(diào)優(yōu)經(jīng)驗。
XML解析:
在xml文件中由于更多的是描述信息的內(nèi)容,所以在得到一個xml文檔之后應該利用程序按照里面元素的定義名稱取出對應的內(nèi)容,這一過程就稱為xml解析。
解析xml文件的4種方式:
1.DOM
2.SAX
3.JDOM
4.DOM4J
文檔對象模型(DOM)
DOM---對象化的XML數(shù)據(jù)接口
它定義了XML文檔的邏輯結(jié)構(gòu),給出了一種訪問和處理XML文檔的方法。利用DOM,程序開發(fā)人員可以動態(tài)地創(chuàng)建文檔,遍歷文檔結(jié)構(gòu),添加、修改、刪除文檔內(nèi)容,改變文檔的顯示方式等等。
DOM樹
DOM這個層次的結(jié)構(gòu)是一棵根據(jù)XML文檔生成的節(jié)點樹。在這棵節(jié)點樹中,有一個根節(jié)點--Document節(jié)點,所有其他的節(jié)點都是根節(jié)點的后代節(jié)點。節(jié)點樹生成之后,就可以通過DOM接口訪問、修改、添加、刪除、創(chuàng)建樹中的節(jié)點和內(nèi)容。
讀入xml:
DocumentBuilderFactory factory =
DocumentBuilderFactory.newInstance();
// 獲取解析器
DocumentBuilder builder = factory.newDocumentBuilder();
// 解析xml文檔
Document doc = builder.parse(new File("src\\dom.xml"));
Element root = builder.getDocumentElement();//獲得根元素
寫回xml:
TransformerFactory tfactory=TransformerFactory.newInstance();
Transformer tformer = tfactory.newTransformer();
tformer.transform(new DOMSource(doc), new StreamResult(new FileOutputStream("src\\dom1.xml")));
得到文檔模型的根元素
Element root = doc.getDocumentElement();
元素Element的函數(shù):
String getTagName() -得到標簽的名字
String getAttribute(“unit”) -得到元素的unit屬性值
節(jié)點Node的函數(shù):
NodeList getChildNodes() - 得到子節(jié)點的集合
Node getFirstChild() - 得到第一個子節(jié)點
Node getLastChild() - 得到最后一個子節(jié)點
節(jié)點Node的函數(shù):
Node getNextSibling() - 得到下一個兄弟節(jié)點
Node getPreviousSibling() - 得到前一個兄弟結(jié)點
Node getParentNode() - 得到父節(jié)點
NamedNodeMap getAttributes() - 得到所有的屬性集合
String getNodeName() - 得到當前節(jié)點的名字
String getNodeValue() - 得到當前節(jié)點的值
NodeList的函數(shù)
int getLength() -得到集合長度
Node item(int index) - 得到集合中的一個元素
寫XML文檔函數(shù)
DocumentBuilder 的函數(shù):
Document doc = builder.newDocument(); -新建一個模型
Document 的函數(shù):
Element createElement(String name) – 建立一個元素
Text createTextNode(String data)-創(chuàng)建一個文本節(jié)點
Node的函數(shù):
Node appendChild(Node child) - 添加一個子節(jié)點
Element 的函數(shù):
void setAttribute(String name, String value) - 設置元素的一個屬性和屬性值
簡單應用程序接口(SAX)
SAX是一種事件驅(qū)動的接口,它的基本原理是由接口的用戶提供符合定義的處理器,XML分析時遇到特定的事件,就去調(diào)用處理器中特定事件的處理函數(shù)。
捕獲和響應各個事件
startDocument( ) 和 endDocument( ) 事件是在文檔的起始處和結(jié)束處被激發(fā)的
startElement( ) 和 endElement( ) 事件是在遇到起始標記和結(jié)束標記時被激發(fā)的
characters( ) 事件是在遇到字符數(shù)據(jù)時被激發(fā)的
使用 SAX 解析 XML 文檔的步驟如下:
創(chuàng)建 SAXParserFactory 的實例
創(chuàng)建 SAXParser 的實例
創(chuàng)建 SAXParserHandler 類
使用 parse() 方法解析 XML 文檔
SAXParserFactory spfactory = SAXParserFactory.newInstance();
// 生成SAX解析對象
SAXParser parser = spfactory.newSAXParser();
// 指定XML文件,進行XML解析
parser.parse(new File("src\\dom.xml"), new SaxReader());
Jdom
JDOM 使用標準的 Java 編碼模式,用以來彌補DOM及SAX在實際應用當中的不足之處。
這些不足之處主要在于SAX沒有文檔修改、隨機訪問以及輸出的功能,而對于DOM來說,在使用時來用起來不太方便。
在 JDOM 中,XML 元素就是 Element 的實例,XML 屬性就是 Attribute 的實例,XML 文檔本身就是 Document 的實例。
因為 JDOM 對象就是像 Document、Element 和 Attribute 這些類的直接實例,因此創(chuàng)建一個新 JDOM 對象就如在 Java 語言中使用 new 操作符一樣容易。而不使用復雜的工廠化模式,使對象操作更為方便。
Document類操作
Element root=new Element("GREETING");
Document doc=new Document(root);
root.setText("HelloJDOM!");
Attribute 類操作
Attribute rootAttri = new Attribute("comment","introduce myself");//創(chuàng)建名為 commnet,值為 introduce myself 的屬性。
rootElement.setAttribute(rootAttri);//將剛創(chuàng)建的屬性添加到根元素。
Element類操作
Element root=doc.getRootElement();//獲得根元素element
List allChildren=root.getChildren();//獲得所有子元素的一個list
List namedChildren=root.getChildren("name");//獲得指定名稱子元素的list
Element child=root.getChild(“name”);//獲得指定名稱的第一個子元素
allChildren.remove(3);//刪除第四個子元素
allChildren.removeAll(root.getChildren("jack"));//刪除叫“jack”的子元素
root.removeChildren("jack");//便捷寫法
allChildren.add(new Element("jane"));//加入
root.addContent(new Element(“jane”));//便捷寫法
Element nameElement = new Element("name");//創(chuàng)建 name 元素
nameElement.addContent("kingwong");//將kingwong作為content添加到name元素
rootElement.addContent(nameElement);//將name元素作為content添加到根元素 getAttributeValue("name") 返回指定屬性名字的值。如果沒有該屬性則返回null,有該屬性但是值為空,則返回空字符串。
getChildText("childname") 返回指定子節(jié)點的內(nèi)容文本值。
root.getChild("book").getChild("name").getText();
root.getChild("book").getChild("name").setText("dsgdghdgasg");
解析xml
使用Jdom解析xml要導入org.dom的jar包
1.實例化一個合適的解析器對象
SAXBuilder builder = new SAXBuilder();
2.構(gòu)建一個文檔對象doc
Document doc = builder.build(new File("src\\dom.xml"));
XML文檔輸出
XMLOutputter outputter=new XMLOutputter();
outputter.output(doc,new FileOutputStream("src\\dom.xml"));
Dom4j
Dom4j是一個Java的XML API,類似于jdom,用來讀寫XML文件的。它應用于Java平臺,采用了Java集合框架并完全支持DOM,SAX和JAXP。
1.讀取并解析XML文檔:
讀寫XML文檔主要依賴于org.dom4j.io包,其中提供DOMReader和SAXReader兩類不同方式,而調(diào)用方式是一樣的。這就是依靠接口的好處。 // 從文件讀取XML,輸入文件名,返回XML文檔
public Document read(String fileName) throws MalformedURLException, DocumentException {
SAXReader reader = new SAXReader();
Document document = reader.read(new File(fileName));
return document;
}
2、取得Root節(jié)點
public Element getRootElement(Document doc){
return doc.getRootElement();
}
3、遍歷XML樹
for ( Iterator i = root.elementIterator(); i.hasNext(); ) {// 枚舉所有子節(jié)點
Element element = (Element) i.next();}
for ( Iterator i = root.elementIterator(foo); i.hasNext();) {// 枚舉名稱為foo的節(jié)點
Element foo = (Element) i.next();} // 枚舉屬性
for ( Iterator i = root.attributeIterator(); i.hasNext(); ) {
Attribute attribute = (Attribute) i.next();}
遞歸也可以采用Iterator作為枚舉手段,但文檔中提供了另外的做法
public void treeWalk() {
treeWalk(getRootElement());
}
public void treeWalk(Element element) {
for (int i = 0, size = element.nodeCount(); i < size; i++) {
Node node = element.node(i);
if (node instanceof Element) {
treeWalk((Element) node);
} else { // do something....
}
}
}
獲取節(jié)點數(shù)量,包含自身。 這個方法所遍歷出來的對象是多種的,node,namespace,text等類型的。 if(element instanceof Element) 條件 element.nodeCount()==1 表示當前元素是子元素
4. 創(chuàng)建XML
public Document createDocument() {
Document document = DocumentHelper.createDocument();
Element root = document.addElement(root);
Element author1 =root.addElement(author).addAttribute(name, James)
.addAttribute(location, UK).addText(James Strachan);
Element author2 =root.addElement(author).addAttribute(name, Bob)
.addAttribute(location, US).addText(Bob McWhirter);
return document;
}
5字符串與XML的轉(zhuǎn)換
有時候經(jīng)常要用到字符串轉(zhuǎn)換為XML或反之
// XML轉(zhuǎn)字符串
Document document = ...;
String text = document.asXML();
// 字符串轉(zhuǎn)XML
String text = <name>James</name>
Document document = DocumentHelper.parseText(text);
6文件輸出
一個簡單的輸出方法是將一個Document或任何的Node通過write方法輸出
FileWriter out = new FileWriter( foo.xml );
document.write(out);
美化輸出或縮進格式,可以用XMLWriter類 public void write(Document document) throws IOException {
// 讀取文件
FileWriter fileWriter = new FileWriter("src\\dom2.xml");
//OutputFormat xmlFormat = OutputFormat.createPrettyPrint();// 縮減型格式
OutputFormat xmlFormat =OutputFormat.createCompactFormat();//緊湊型格式
//format.setTrimText(false);//設置text中是否要刪除其中多余的空格
xmlFormat.setEncoding("gb2312");// 設置編碼
// 創(chuàng)建寫文件方法
XMLWriter xmlWriter = new XMLWriter(fileWriter, xmlFormat);
// 寫入文件
xmlWriter.write(document);
// 關(guān)閉
xmlWriter.close();
}