Dom4j 學(xué)習(xí)筆記
The dom4j Project Homepage: http://www.dom4j.org
Loading XML Data
以下代碼從File中或一個(gè)URL中讀取一個(gè)XML文件,并產(chǎn)生一個(gè)Document對象。一個(gè)Document對象表示了內(nèi)存中的一棵XML樹,可以在這個(gè)XML樹中進(jìn)行遍歷、查詢、修改等操作。
import java.io.*;
import java.net.*;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.io.SAXReader;
public class XMLLoader {
???
??? private Document doc = null;
???
??? public void parseWithSAX(File file)
??? throws MalformedURLException, DocumentException {
??????? SAXReader xmlReader = new SAXReader();
??????? this.doc = xmlReader.read(file);
??????? return;
??? }
???
??? public void parseWithSAX(URL url)
??? throws MalformedURLException, DocumentException {
??????? SAXReader xmlReader = new SAXReader();
??????? this.doc = xmlReader.read(url);
??????? return;
??? }
}
???????
QName and Namespace
QName對象表示了一個(gè)XML元素或?qū)傩缘膓ualified name,即一個(gè)namespace和一個(gè)local name的二元組。
Namespace對象表示了QName二元組中的namespace部分,它由prefix和URI兩部分組成。
/******************** SAMPLE XML FILE *************************
? <heavyz:Sample
??? xmlns:heavyz="??? <heavyz:HelloWorld/>
? </heavyz:Sample>
? *************************************************************/
?
public void printRootQNameInfo(Document doc) {
??? Element root = doc.getRootElement();
??? QName qname = root.getQName();
??? System.out.println("local name????? : " + qname.getName());
??? System.out.println("namespace prefix: " + qname.getNamespacePrefix());
??? System.out.println("namespace URI?? : " + qname.getNamespaceURI());
??? System.out.println("qualified name? : " + qname.getQualifiedName());
??? return;
}
/************************* OUTPUT *****************************
? localname?????? : Sample
? namespace prefix: heavyz
? namespace URI?? : http://www.heavyzheng.com/schema/sample.xsd
? qualified name? : heavyz:Sample
? *************************************************************/
???????
可以調(diào)用Namespace(String prefix, String uri)構(gòu)造方法構(gòu)造一個(gè)新的Namespace對象;也可以調(diào)用Namespace.get(String prefix, String uri)靜態(tài)方法獲得一個(gè)新的Namespace對象。
可以調(diào)用QName(String name)構(gòu)造方法構(gòu)造一個(gè)沒有namespace的qualified name;或者調(diào)用QName(String name, Namespace namespace)構(gòu)造方法構(gòu)造一個(gè)有namespace的qualified name。
Navigating Through an XML Tree
對Document對象調(diào)用getRootElement()方法可以返回代表根節(jié)點(diǎn)的Element對象。擁有了一個(gè)Element對象后,可以對該對象調(diào)用elementIterator()方法獲得它的子節(jié)點(diǎn)的Element對象們的一個(gè)iterator。使用(Element)iterator.next()方法遍歷一個(gè)iterator并把每個(gè)取出的元素轉(zhuǎn)化為Element類型。
通過遞歸的方法,以下代碼可以根據(jù)Document對象打印出完整的XML樹。
public void printXMLTree(Document doc) {
??? Element root = doc.getRootElement();
??? printElement(root,0);
??? return;
}
???
private void printElement(Element element, int level) {
??? // print indent
??? for (int i=0; i<level; i++) {
??????? System.out.print(" ");
??? }
??? System.out.println(element.getQualifiedName());
??? Iterator iter = element.elementIterator();
??? while (iter.hasNext()) {
??????? Element sub = (Element)iter.next();
??????? printElement(sub,level+2);
??? }
??? return;
}
???????
Getting Information from an Element
可以通過Element類提供的方法訪問一個(gè)XML元素中含有的信息: Method Comment
getQName() 元素的QName對象
getNamespace() 元素所屬的Namespace對象
getNamespacePrefix() 元素所屬的Namespace對象的prefix
getNamespaceURI() 元素所屬的Namespace對象的URI
getName() 元素的local name
getQualifiedName() 元素的qualified name
getText() 元素所含有的text內(nèi)容,如果內(nèi)容為空則返回一個(gè)空字符串而不是null
getTextTrim() 元素所含有的text內(nèi)容,其中連續(xù)的空格被轉(zhuǎn)化為單個(gè)空格,該方法不會(huì)返回null
attributeIterator() 元素屬性的iterator,其中每個(gè)元素都是Attribute對象
attributeValue() 元素的某個(gè)指定屬性所含的值
elementIterator() 元素的子元素的iterator,其中每個(gè)元素都是Element對象
element() 元素的某個(gè)指定(qualified name或者local name)的子元素
elementText() 元素的某個(gè)指定(qualified name或者local name)的子元素中的text信息
getParent 元素的父元素
getPath() 元素的XPath表達(dá)式,其中父元素的qualified name和子元素的qualified name之間使用"/"分隔
isTextOnly() 是否該元素只含有text或是空元素
isRootElement() 是否該元素是XML樹的根節(jié)點(diǎn)
要取出Element對象中某個(gè)屬性的信息,可以調(diào)用attributeIterator()方法獲得一個(gè)Attribute對象的iterator,然后再遍歷它。也可以直接調(diào)用attributeValue()方法獲得指定屬性的值。該方法接受四種類型的參數(shù):
attributeValue(QName qname):通過指定qualified name獲得屬性值,如果無法找到指定的屬性,則返回null。
attributeValue(QName qname, String defaultValue):通過指定qualified name獲得屬性值,如果無法找到指定的屬性,則返回defaultValue。
attributeValue(String name):通過指定local name獲得屬性值,而忽略屬性的namespace,如果無法找到指定的屬性,則返回null。
attributeValue(String name, String defaultValue):通過指定local name獲得屬性值,而忽略屬性的namespace,如果無法找到指定的屬性,則返回defaultValue。
對于一個(gè)Attribute對象,可以使用它的以下方法訪問其中的信息: Method Comment
getQName() 屬性的QName對象
getNamespace() 屬性所屬的Namespace對象
getNamespacePrefix() 屬性所屬的Namespace對象的prefix
getNamespaceURI() 屬性所屬的Namespace對象的URI
getName() 屬性的local name
getQualifiedName() 屬性的qualified name
getValue() 屬性的值
Writing an XML Tree to OutputStream
Dom4j通過XMLWriter將由Document對象表示的XML樹寫入一個(gè)文件,并使用OutputFormat格式對象指定寫入的風(fēng)格和編碼方法。調(diào)用OutputFormat.createPrettyPrint()方法可以獲得一個(gè)默認(rèn)的pretty print風(fēng)格的格式對象。對OutputFormat對象調(diào)用setEncoding()方法可以指定XML文件的編碼方法。
public void writeTo(OutputStream out, String encoding)
throws UnsupportedEncodingException, IOException {
??? OutputFormat format = OutputFormat.createPrettyPrint();
??? format.setEncoding("gb2312");
??? XMLWriter writer = new XMLWriter(System.out,format);
??? writer.write(doc);
??? writer.flush();
??? return;
}
???????
Creating an XML Tree
使用DocumentFactory對象創(chuàng)建一個(gè)空的Document對象。DocumentFactory對象由DocumentFactory.getInstance()靜態(tài)方法產(chǎn)生。對Document對象調(diào)用addElement()方法將創(chuàng)建XML根節(jié)點(diǎn),并將該節(jié)點(diǎn)返回。也可以手工創(chuàng)建一個(gè)Element對象并調(diào)用Document.setRootElement()方法把它設(shè)置為根節(jié)點(diǎn)
import org.dom4j.DocumentFactory;
import org.dom4j.Document;
import org.dom4j.Element;
public class XMLSaver {
???
??? private DocumentFactory factory = null;
??? private Document doc = null;
??? private Element root = null;
???
??? public XMLSaver() {
??????? factory = DocumentFactory.getInstance();
??????? doc = factory.createDocument();
??? }
???
??? public Element generateRoot(String name) {
??????? root = doc.addElement(name);
??????? return root;
??? }
???
??? public Element generateRoot(QName qname) {
??????? root = doc.addElement(qname);
??????? return root;
??? }
???
??? public Element generateRoot(Element element) {
??????? doc.setRootElement(element);
??????? root = element;
??????? return root;
??? }
}
???????
Adding Information into an Element
Element通過addElement()為自己增加一個(gè)子節(jié)點(diǎn)到當(dāng)前所有子節(jié)點(diǎn)的后面。該方法可以接受三種不同類型的參數(shù):(QName qname)、(String name)或者(String qualifiedName, String namespaceURI)。該方法返回增加的子節(jié)點(diǎn)的Element對象。
Element通過addAttribute()為自己增加屬性。該方法可以接受兩種不同類型的參數(shù):(QName qname, String value)或者(String name, String value)。該方法返回自身的Element對象。
Element通過addText()為自己增加文本內(nèi)容。該方法只接受String類型參數(shù),并返回自身的Element對象。
public void addAuthors(Element bookElement) {
??? Element author1 = bookElement.addElement("author");
??? author1.addAttribute("name","Toby");
??? author1.addAttribute("location","Germany");
??? author1.addText("Tobias Rademacher");
??? Element author2 = bookElement.addElement("author");
??? author2.addAttribute("name","James");
??? author2.addAttribute("name","UK");
??? author2.addText("James Strachan");
???
??? return;
}
???????
Deleting Elements and Attributes
要?jiǎng)h除XML樹上的一棵子樹,首先要找到該子樹的根節(jié)點(diǎn),然后對該節(jié)點(diǎn)調(diào)用detach()方法。注意:如果對根節(jié)點(diǎn)調(diào)用了detach()方法,將導(dǎo)致該XML樹不再完整(一個(gè)XML文件需要有且僅有一個(gè)根節(jié)點(diǎn))。
public void deleteSubtree(Element subtreeRoot) {
??? subtreeRoot.detach();
??? return;
}
???????
要清除Element下的所有子節(jié)點(diǎn)(包括Element和text),可以對該Element調(diào)用clearContent()方法。該方法不會(huì)清除Element的屬性。
要清除Element下的某個(gè)Attribute,首先要獲得該Attribute對象,然后把它作為參數(shù)調(diào)用Element的remove()方法。
Updating an Attribute
要更新一個(gè)屬性的內(nèi)容,首先要獲得該Attribute對象,然后可以調(diào)用setNamespace()方法更新它所屬的namespace;調(diào)用setValue()方法更新它的屬性值。
Updating an Element's Text
可以對一個(gè)Element對象調(diào)用isTextOnly()方法判斷它是否只含有text或者是空節(jié)點(diǎn)。對Element對象調(diào)用addText()方法將把一個(gè)字符串附加到Element中,但不會(huì)修改它原來擁有的text或者子節(jié)點(diǎn)。如果Element是isTextOnly(),要修改原來含有的text,可以先調(diào)用clearContent(),再調(diào)用addText()并把新值傳入。
public void updateText(Element element, String newText) {
??? if (element.isTextOnly()) {
??????? element.clearContent();
??????? element.addText(newText);
??? }
??? return;
}