XML 指可擴展標記語言(EXtensible Markup Language),常用於簡化數據的存儲和共享。
-
xml用途
1.XML 把數據從 HTML 分離
如果您需要在 HTML 文檔中顯示動態數據,那麼每當數據改變時將花費大量的時間來編輯 HTML。
2.XML 簡化數據共享
在真實的世界中,計算機系統和數據使用不兼容的格式來存儲數據,XML 數據以純文本格式進行存儲,
因此提供了一種獨立於軟件和硬件的數據存儲方法。
3.XML 簡化數據傳輸
在互聯網上的不兼容系統之間交換數據;由於可以通過各種不兼容的應用程序來讀取數據,
以 XML 交換數據降低了這種複雜性。
4.XML 簡化平臺變更
升級到新的系統(硬件或軟件平臺),總是非常費時的。必須轉換大量的數據,不兼容的數據經常會丟失。
XML 數據以文本格式存儲。這使得 XML 在不損失數據的情況下,更容易擴展或升級到新的操作系統、
新的應用程序或新的瀏覽器。
-
XML的解析方式
1、DOM解析;
2、SAX解析;
3、JDOM解析;
4、DOM4J解析。
其中前兩種屬於基礎方法,是官方提供的平臺無關的解析方式;後兩種屬於擴展方法,
它們是在基礎的方法上擴展出來的,只適用於java平臺。
1、DOM解析
DOM(Document Object Model),也即文檔對象模型,DOM 是以層次結構組織的節點或信息片斷的集合。
這個層次結構允許開發人員在樹中尋找特定信息。分析該結構通常需要加載整個文檔和構造層次結構,
然後才能做任何工作。由於它是基於信息層次的,因而 DOM 被認爲是基於樹或基於對象的。
優點:
①、整個 Dom 樹都加載到內存中了,所以允許隨機讀取訪問數據。
②、允許隨機的對文檔結構進行增刪。
缺點:
①、整個 XML 文檔必須一次性解析完,耗時。
②、整個 Dom 樹都要加載到內存中,佔內存。
適用於:文檔較小,且需要修改文檔內容
public class XmlByDOM {
private static DocumentBuilderFactory bbf = null;
private static DocumentBuilder builder = null;
private static List<Userinfo> userinfos = new ArrayList<Userinfo>();
static {
bbf = DocumentBuilderFactory.newInstance();
try {
builder = bbf.newDocumentBuilder();
} catch (ParserConfigurationException e) {
e.printStackTrace();
}
}
private Logger logger = Logger.getLogger(this.getClass());
public static void main(String[] args) {
String path = XmlByDOM.class.getClassLoader().getResource("dom.xml").getPath();
System.out.println(path);
Userinfo userinfo = new Userinfo();
userinfo.setId("7");
userinfo.setEmail("[email protected]");
userinfo.setPhone("12365412301");
userinfo.setName("田七");
userinfo.setAddress("高新西區恆大");
//new XmlByDOM().addNode(userinfo);
new XmlByDOM().removeNode("7");
new XmlByDOM().getAll();
}
/**
* <p>
* 解析xml所有數據
* </p>
*/
protected void getAll() {
try {
InputStream inputStream = getInputStream();
Document document = builder.parse(inputStream);
logger.info("-----> xml " + document.getXmlVersion() + " >> " + document.getXmlEncoding());
//解析根元素
Element element = document.getDocumentElement();
String tagName = element.getTagName();
logger.info("-----> tagName " + tagName);
//解析userinfo節點
NodeList nodeList = element.getElementsByTagName("userinfo");
if (nodeList != null) {
for (int i = 0; i < nodeList.getLength(); i++) {
Element node = (Element) nodeList.item(i);
//獲取userinfo的id屬性
String id = node.getAttribute("id");
Element name = (Element) node.getElementsByTagName("name").item(0);
Element address = (Element) node.getElementsByTagName("address").item(0);
Element email = (Element) node.getElementsByTagName("email").item(0);
Element phone = (Element) node.getElementsByTagName("phone").item(0);
//獲取節點值
String nameNodeValue = name.getTextContent();
String addressNodeValue = address.getTextContent();
String emailNodeValue = email.getTextContent();
String phoneNodeValue = phone.getTextContent();
logger.info("-----> id " + id + " >> name " + nameNodeValue + " >> address " + addressNodeValue + " >> email " + emailNodeValue + " >> phone " + phoneNodeValue);
Userinfo userinfo = new Userinfo();
userinfo.setAddress(addressNodeValue);
userinfo.setName(nameNodeValue);
userinfo.setPhone(phoneNodeValue);
userinfo.setEmail(emailNodeValue);
userinfos.add(userinfo);
}
logger.info(userinfos);
}
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 根據節點id屬性獲取節點信息
* @param id
* @return
*/
protected Userinfo getById(String id){
try {
InputStream inputStream = getInputStream();
Document document = builder.parse(inputStream);
logger.info("-----> xml " + document.getXmlVersion() + " >> " + document.getXmlEncoding());
//解析根元素
Element element = document.getDocumentElement();
String tagName = element.getTagName();
logger.info("-----> tagName " + tagName);
//解析userinfo節點
NodeList nodeList = element.getElementsByTagName("userinfo");
if (nodeList != null) {
for (int i = 0; i < nodeList.getLength(); i++) {
Element node = (Element) nodeList.item(i);
//獲取userinfo的id屬性
String nodeId = node.getAttribute("id");
if(nodeId.equals(id)){
Element name = (Element) node.getElementsByTagName("name").item(0);
Element address = (Element) node.getElementsByTagName("address").item(0);
Element email = (Element) node.getElementsByTagName("email").item(0);
Element phone = (Element) node.getElementsByTagName("phone").item(0);
//獲取節點值
String nameNodeValue = name.getTextContent();
String addressNodeValue = address.getTextContent();
String emailNodeValue = email.getTextContent();
String phoneNodeValue = phone.getTextContent();
logger.info("-----> id " + id + " >> name " + nameNodeValue + " >> address " + addressNodeValue + " >> email " + emailNodeValue + " >> phone " + phoneNodeValue);
Userinfo userinfo = new Userinfo();
userinfo.setAddress(addressNodeValue);
userinfo.setName(nameNodeValue);
userinfo.setPhone(phoneNodeValue);
userinfo.setEmail(emailNodeValue);
logger.info(userinfo);
userinfos.add(userinfo);
return userinfo;
}
}
}
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
protected void removeNode(String id){
try {
InputStream inputStream = getInputStream();
Document document = builder.parse(inputStream);
logger.info("-----> xml " + document.getXmlVersion() + " >> " + document.getXmlEncoding());
//解析根元素
Element element = document.getDocumentElement();
String tagName = element.getTagName();
logger.info("-----> tagName " + tagName);
//解析userinfo節點
NodeList nodeList = element.getElementsByTagName("userinfo");
if (nodeList != null) {
for (int i = 0; i < nodeList.getLength(); i++) {
Element node = (Element) nodeList.item(i);
//獲取userinfo的id屬性
String nodeId = node.getAttribute("id");
if(nodeId.equals(id)){
element.removeChild(node);
// 同步
TransformerFactory.newInstance().newTransformer().transform(new DOMSource(document),
new StreamResult("src/main/resources/dom.xml"));
logger.info("-----> delete node success !");
}
}
}
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (TransformerConfigurationException e) {
e.printStackTrace();
} catch (TransformerException e) {
e.printStackTrace();
}
}
protected void addNode(Userinfo userinfo){
try {
InputStream inputStream = getInputStream();
Document document = builder.parse(inputStream);
logger.info("-----> xml " + document.getXmlVersion() + " >> " + document.getXmlEncoding());
//解析根元素
Element root = document.getDocumentElement();
//創建節點
Element element = document.createElement("userinfo");
element.setAttribute("id",userinfo.getId());
root.appendChild(element);
//創建節點屬性
Element name = document.createElement("name");
Element address = document.createElement("address");
Element email = document.createElement("email");
Element phone = document.createElement("phone");
name.setTextContent(userinfo.getName());
address.setTextContent(userinfo.getAddress());
email.setTextContent(userinfo.getEmail());
phone.setTextContent(userinfo.getPhone());
element.appendChild(name);
element.appendChild(address);
element.appendChild(email);
element.appendChild(phone);
//將xml樹寫入文件
TransformerFactory factory = TransformerFactory.newInstance();
Transformer transformer = factory.newTransformer();
URL url = this.getClass().getClassLoader().getResource("dom.xml");
File file = new File(url.getFile());
logger.info("-----> file name "+file.getName() +" >> size >>" +file.length());
//同步數據
transformer.transform(new DOMSource(document),new StreamResult("src/main/resources/dom.xml"));
logger.info("-----> add node success");
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (TransformerConfigurationException e) {
e.printStackTrace();
} catch (TransformerException e) {
e.printStackTrace();
}
}
protected void updateNode(Userinfo userinfo) throws IOException, SAXException, TransformerException {
InputStream inputStream = getInputStream();
Document document = builder.parse(inputStream);
logger.info("-----> xml " + document.getXmlVersion() + " >> " + document.getXmlEncoding());
//解析根元素
Element root = document.getDocumentElement();
//解析userinfo節點
NodeList nodeList = root.getElementsByTagName("userinfo");
if (nodeList != null) {
for (int i = 0; i < nodeList.getLength(); i++) {
Element node = (Element) nodeList.item(i);
//獲取userinfo的id屬性
String id = node.getAttribute("id");
if(id.equals(userinfo.getId())){
node.getElementsByTagName("name").item(0).setTextContent(userinfo.getName());
node.getElementsByTagName("address").item(0).setTextContent(userinfo.getAddress());
node.getElementsByTagName("email").item(0).setTextContent(userinfo.getEmail());
node.getElementsByTagName("phone").item(0).setTextContent(userinfo.getPhone());
//將xml樹寫入文件
TransformerFactory factory = TransformerFactory.newInstance();
Transformer transformer = factory.newTransformer();
URL url = this.getClass().getClassLoader().getResource("dom.xml");
File file = new File(url.getFile());
logger.info("-----> file name "+file.getName() +" >> size >>" +file.length());
transformer.transform(new DOMSource(document),new StreamResult("src/main/resources/dom.xml"));
}
}
}
}
private InputStream getInputStream() {
return this.getClass().getClassLoader().getResourceAsStream("dom.xml");
}
}
2、SAX解析
SAX的全稱是Simple APIs for XML,也即XML簡單應用程序接口。SAX處理的特點是基於事件流的。分析能夠立即開始,而不是等待所有的數據被處理。而且,由於應用程序只是在讀取數據時檢查數據,因此不需要將數據存儲在內存中。這對於大型文檔來說是個巨大的優點。事實上,應用程序甚至不必解析整個文檔;它可以在某個條件得到滿足時停止解析。sax分析器在對xml文檔進行分析時,觸發一系列的事件,應用程序通過事件處理函數實現對xml文檔的訪問,因爲事件觸發是有時序性的,所以sax分析器提供的是一種對xml文檔的順序訪問機制,對於已經分析過的部分,不能再重新倒回去處理。
優點:
①、訪問能夠立即進行,不需要等待所有數據被加載。
②、只在讀取數據時檢查數據,不需要保存在內存中
③、不需要將整個數據都加載到內存中,佔用內存少
④、允許註冊多個Handler,可以用來解析文檔內容,DTD約束等等。
缺點:
①、需要應用程序自己負責TAG的處理邏輯(例如維護父/子關係等),文檔越複雜程序就越複雜。
②、單向導航,無法定位文檔層次,很難同時訪問同一文檔的不同部分數據,不支持XPath。
③、不能隨機訪問 xml 文檔,不支持原地修改xml。
適用於:文檔較大,只需要讀取文檔數據。
public class XmlBySAX {
private static SAXTransformerFactory saxTransformerFactory = null;
private static List<Userinfo> userinfos = new ArrayList<Userinfo>();
static {
saxTransformerFactory = (SAXTransformerFactory) SAXTransformerFactory.newInstance();
}
private Logger logger = Logger.getLogger(this.getClass());
public static void main(String[] args) throws IOException, SAXException, TransformerConfigurationException, ParserConfigurationException {
new XmlBySAX().createXml("src/main/resources/sax.xml");
new XmlBySAX().new ParseSAX().analysisXml();
}
/**
* <p>創建xml</p>
*
* @param path
* @throws TransformerConfigurationException
* @throws FileNotFoundException
* @throws SAXException
*/
protected void createXml(String path) throws TransformerConfigurationException, FileNotFoundException, SAXException {
// 創建一個TransformerHandler實例
TransformerHandler handler = saxTransformerFactory.newTransformerHandler();
// 創建一個handler轉換器
Transformer transformer = handler.getTransformer();
// 換行
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
// 字符集
transformer.setOutputProperty(OutputKeys.ENCODING, "utf-8");
// 創建一個Result實例連接到XML文件
Result result = new StreamResult(path);
handler.setResult(result);
// 創建一個屬性實例, addAttribute(String uri, String localName, String qName, String type, String value)
AttributesImpl attr = new AttributesImpl();
// 打開doc對象
handler.startDocument();
logger.info("----->根節點開始");
// 創建根元素: handler.startElement(uri, 命名空間, 元素名, 屬性列表);//沒有則填null
handler.startElement(null, null, "root", attr);
logger.info("----->第一個子節點開始");
// 每次創建節點前,先清空屬性,放置一些屬性錯誤
attr.clear();
// 設置屬性
attr.addAttribute("", "", "id", "", "1");
//第一個子節點開始
handler.startElement("", "", "userinfo", attr);
attr.clear();
// 第一個子節點的第一個子節點people
handler.startElement("", "", "name", attr);
handler.characters("one name".toCharArray(), 0, "one name".length());
handler.endElement("", "", "name");
// 第一個子節點的第二個子節點people
attr.clear();
handler.startElement("", "", "address", attr);
handler.characters("one address".toCharArray(), 0, "one address".length());
handler.endElement("", "", "address");
handler.endElement("", "", "userinfo");
logger.info("----->第一個子節點結束");
logger.info("----->第二個子節點開始");
// 每次創建節點前,先清空屬性,放置一些屬性錯誤
attr.clear();
// 設置屬性
attr.addAttribute("", "", "id", "", "2");
//第一個子節點開始
handler.startElement("", "", "userinfo", attr);
attr.clear();
// 第一個子節點的第一個子節點people
handler.startElement("", "", "name", attr);
handler.characters("two name".toCharArray(), 0, "one name".length());
handler.endElement("", "", "name");
// 第一個子節點的第二個子節點people
attr.clear();
handler.startElement("", "", "address", attr);
handler.characters("two address".toCharArray(), 0, "one address".length());
handler.endElement("", "", "address");
handler.endElement("", "", "userinfo");
logger.info("----->第一個子節點結束");
//根節點結束
handler.endElement(null, null, "root");
logger.info("----->根節點結束");
// 關閉doc對象
handler.endDocument();
logger.info("sax success !!!");
}
class ParseSAX extends DefaultHandler {
//存放遍歷集合
private List<Userinfo> userinfos;
//構建Student對象
private Userinfo userinfo;
//用來存放每次遍歷後的元素名稱(節點名稱)
private String tagName;
public List<Userinfo> getUserinfos() {
return userinfos;
}
public void setUserinfos(List<Userinfo> userinfos) {
this.userinfos = userinfos;
}
protected void analysisXml() throws ParserConfigurationException, SAXException, IOException {
// 創建一個SAX解析工廠
SAXParserFactory factory = SAXParserFactory.newInstance();
// 創建一個SAX轉換工具
SAXParser saxParser = factory.newSAXParser();
//實例化 DefaultHandler對象
// 解析XML
ParseSAX parseSAX = new ParseSAX();
saxParser.parse(getInputStream(), parseSAX);
List<Userinfo> userinfos = parseSAX.getUserinfos();
for (Userinfo userinfo : userinfos) {
System.out.println("----->" + userinfo);
}
}
//解析根節點 初始化list集合
@Override
public void startDocument() throws SAXException {
userinfos = new ArrayList<Userinfo>();
}
//解析根節點下面的子節點開始
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
logger.info("<" + qName + ">");
if (qName.equals("userinfo")) {
userinfo = new Userinfo();
//獲取userinfo節點上的id屬性值
userinfo.setId(attributes.getValue(0));
}
this.tagName = qName;
}
//解析根節點下面的子節點結束
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
logger.info("</" + qName + ">");
if (qName.equals("userinfo")) {
this.userinfos.add(this.userinfo);
}
this.tagName = null;
}
//解析根節點結束
@Override
public void endDocument() throws SAXException {
}
//解析子節點下面的子節點屬性
@Override
public void characters(char ch[], int start, int length) throws SAXException {
String str = new String(ch, start, length);
if (!"\n".equals(str)) {
logger.info(str);
}
if (this.tagName != null) {
String date = new String(ch, start, length);
if (this.tagName.equals("name")) {
this.userinfo.setName(date);
} else if (this.tagName.equals("address")) {
this.userinfo.setAddress(date);
}
}
}
private InputStream getInputStream() {
return this.getClass().getClassLoader().getResourceAsStream("sax.xml");
}
}
3、JDOM(Java-based Document Object Model)
JDOM 是一種使用 XML 的獨特 Java 工具包,用於快速開發 XML 應用程序。它基於樹型結構,利用純JAVA的技術對XML文檔實現解析、生成、序列化以及多種操作。JDOM 直接爲JAVA編程服務。它利用更爲強有力的JAVA語言的諸多特性(方法重載、集合概念以及映射),把SAX和DOM的功能有效地結合起來。同時JDOM也是用Java語言讀、寫、操作XML的新API函數,在簡單和高效的前提下,這些API函數被最大限度的優化,以彌補DOM及SAX在實際應用當中的不足之處。在 JDOM 中,XML 元素就是 Element 的實例,XML 屬性就是 Attribute 的實例,XML 文檔本身就是 Document 的實例。因此創建一個新 JDOM 對象就如在 Java 語言中使用 new 操作符一樣容易。
優點:
①、使用具體類而不是接口,簡化了DOM的API。
②、大量使用了Java集合類,方便了Java開發人員。
缺點:
①、不能處理大於內存的文檔.
②、API 簡單,沒有較好的靈活性
需要導入額外包依賴
<dependency>
<groupId>org.jdom</groupId>
<artifactId>jdom</artifactId>
<version>2.0.2</version>
</dependency>
public class XmlByJDOM {
private Logger logger = Logger.getLogger(this.getClass());
public static void main(String[] args) throws IOException, JDOMException {
new XmlByJDOM().createJDOM("src/main/resources/jdom.xml");
new XmlByJDOM().analysisXml("src/main/resources/jdom.xml");
}
protected void analysisXml(String path) throws IOException, JDOMException {
// 創建一個SAXBuilder對象
SAXBuilder sab = new SAXBuilder();
// 調用Build方法,創建Document對象
Document doc = sab.build(new FileInputStream(path));
//獲取根節點
Element root = doc.getRootElement();
//獲取根下面的子節點
List<Element> elementList = root.getChildren();
//遍歷子節點
if (elementList != null && !elementList.isEmpty()) {
for (int i = 0; i < elementList.size(); i++) {
Element element = elementList.get(i);
//遍歷屬性
List<Attribute> attributes = element.getAttributes();
for (Attribute attribute : attributes) {
logger.info("節點屬性:" + attribute.getName() + ">>>" + attribute.getValue());
}
//遍歷子節點下面的節點屬性(名稱+值)
List<Element> subBook = element.getChildren();
for (Element subElement : subBook) {
logger.info("子節點屬性:" + subElement.getName() + ">>>" + subElement.getValue());
}
}
}
}
protected void createJDOM(String path) throws IOException {
// 創建一個根節點
Element rootElement = new Element("root");
Document doc = new Document(rootElement);
// 在根節點下創建第一個子節點
Element rootOneElement = new Element("person");
rootOneElement.setAttribute(new Attribute("attr", "root one"));
// 在第一個子節點下創建第一個子節點
Element childOneElement = new Element("people");
childOneElement.setAttribute(new Attribute("attr", "child one"));
childOneElement.setText("person child one");
// 在第一個子節點下創建第二個子節點
Element childTwoElement = new Element("people");
childTwoElement.setAttribute(new Attribute("attr", "child two"));
childTwoElement.setText("person child two");
// 在根節點下創建第二個子節點
Element rootTwoElement = new Element("person");
rootTwoElement.setAttribute(new Attribute("attr", "root two"));
// 在第一個子節點下創建第一個子節點
Element oneChildOneElement = new Element("people");
oneChildOneElement.setAttribute(new Attribute("attr", "child one"));
oneChildOneElement.setText("person child one");
// 在第一個子節點下創建第二個子節點
Element twoChildTwoElement = new Element("people");
twoChildTwoElement.setAttribute(new Attribute("attr", "child two"));
twoChildTwoElement.setText("person child two");
rootOneElement.addContent(childOneElement);
rootOneElement.addContent(childTwoElement);
rootTwoElement.addContent(oneChildOneElement);
rootTwoElement.addContent(twoChildTwoElement);
doc.getRootElement().addContent(rootOneElement);
doc.getRootElement().addContent(rootTwoElement);
// 創建xml輸出流操作類
XMLOutputter xmlOutput = new XMLOutputter();
// 設置xml格式化的屬性
Format f = Format.getRawFormat();
f.setIndent(" "); // 文本縮進
f.setTextMode(Format.TextMode.TRIM_FULL_WHITE);
xmlOutput.setFormat(f);
// 把xml文件輸出到指定的位置
xmlOutput.output(doc, new FileOutputStream(new File(path)));
}
}
4、DOM4J(Document Object Model for Java)
Dom4j是一個易用的、開源的庫,用於XML、XPath和XSLT。它應用於Java平臺,採用了Java集合框架並完全支持DOM、SAX和JAXP。在Java開發社區裏,DOM4J的使用最爲廣泛。JDOM的操作非常簡單,但是在處理大XML文件時性能表現不佳,解析10M文檔時就會內存溢出。而DOM4J是一個非常優秀的Java XML API,具有性能優異、功能強大和易於使用的特點,同時它也是一個開放源代碼的軟件,DOM4J使用大量的接口,這也是它被認爲比JDOM靈活的原因。如今我們可以看到越來越多的Java軟件都在使用DOM4J來讀寫XML。DOM4J的官方地址是“http://www.dom4j.org/”,由於在實際項目開發中,採用DOM4J的佔主流。
優點:
①、大量使用了Java集合類,方便Java開發人員,同時提供一些提高性能的替代方法。
②、支持XPath。查找節點特別快
③、靈活性高。
缺點:
①、大量的使用了接口,API複雜,理解難。
②、移植性差。
注:XPath是一門在 XML 文檔中查找信息的語言。
導入額外的maven依賴
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6.1</version>
</dependency>
public class XmlByDOM4J {
private static String path = "src/main/resources/dom4j.xml";
private Logger logger = Logger.getLogger(this.getClass());
public static void main(String[] args) throws Exception {
new XmlByDOM4J().add();
new XmlByDOM4J().update();
new XmlByDOM4J().delete();
new XmlByDOM4J().read();
}
protected void add() throws DocumentException, IOException {
SAXReader reader = new SAXReader();
Document document = reader.read(new File(path));
//獲取根節點並添加子節點
Element student = document.getRootElement().element("student");
student.addElement("schoolName").setText("南充");
OutputFormat format = OutputFormat.createPrettyPrint();
format.setEncoding("utf-8");
XMLWriter writer = new XMLWriter(new FileOutputStream(path), format);
writer.write(document);
writer.close();
}
public void update() throws Exception {
SAXReader reader = new SAXReader();
Document document = reader.read(new File(path));
Element student = (Element) document.getRootElement().elements("student").get(0);
student.element("schoolName").setText("湖南1");
OutputFormat format = OutputFormat.createPrettyPrint();
format.setEncoding("utf-8");
XMLWriter writer = new XMLWriter(new FileOutputStream(path), format);
writer.write(document);
writer.close();
}
public void delete() throws Exception {
SAXReader reader = new SAXReader();
Document document = reader.read(new File(path));
Element student = document.getRootElement().element("student");
Element schoolName = student.element("schoolName");
schoolName.getParent().remove(schoolName);
OutputFormat format = OutputFormat.createPrettyPrint();
format.setEncoding("utf-8");
XMLWriter writer = new XMLWriter(new FileOutputStream(path), format);
writer.write(document);
writer.close();
}
public void read() throws Exception {
SAXReader reader = new SAXReader();
Document document = reader.read(new File(path));
//得到根節點
Element root = document.getRootElement();
//遍歷已知<student><student>節點
//List<Element> students = root.elements("student");
//遍歷未知節點
List<Element> students = root.elements();
for (Element student : students) {
//未知屬性名情況下
List<Attribute> attributeList = student.attributes();
for (Attribute attr : attributeList) {
logger.info("未知屬性名 >>> " + attr.getName() + ": " + attr.getValue());
}
//已知屬性名情況下
logger.info("已知屬性名>>> " + student.attributeValue("attr"));
//未知子元素名
List<Element> elements = student.elements();
for (Element element : elements) {
logger.info("未知子元素名 >>> " + element.getName() + ": " + element.getText());
}
//已知子元素名
Element people = student.element("people");
//獲取<name><name>中間的值
String text = people.getText();
//獲取<name sex="xxx"><name>中間的sex值
String attr = people.attributeValue("attr");
logger.info(text + " 已知子元素名 >>> " + text + " : " + attr);
}
}
}
-
解析方式對比
DOM4J性能最好,連Sun的JAXM也在用DOM4J。目前許多開源項目中大量採用DOM4J,例如大名鼎鼎的Hibernate也用DOM4J來讀取XML配置文件。如果不考慮可移植性,那就採用DOM4J。
JDOM和DOM在性能測試時表現不佳,在測試10M文檔時內存溢出,但可移植。在小文檔情況下還值得考慮使用DOM和JDOM.雖然JDOM的開發者已經說明他們期望在正式發行版前專注性能問題,但是從性能觀點來看,它確實沒有值得推薦之處。另外,DOM仍是一個非常好的選擇。DOM實現廣泛應用於多種編程語言。它還是許多其它與XML相關的標準的基礎,因爲它正式獲得W3C推薦(與基於非標準的Java模型相對),所以在某些類型的項目中可能也需要它(如在JavaScript中使用DOM)。
SAX表現較好,這要依賴於它特定的解析方式-事件驅動。一個SAX檢測即將到來的XML流,但並沒有載入到內存(當然當XML流被讀入時,會有部分文檔暫時隱藏在內存中)。
總結:如果XML文檔較大且不考慮移植性問題建議採用DOM4J;如果XML文檔較小則建議採用JDOM;如果需要及時處理而不需要保存數據則考慮SAX。
參考:https://cloud.tencent.com/developer/article/1012671