一:关于Xml
XML现在已经成为一种通用的数据交换格式,它的平台无关性,语言无关性,系统无关性,给数据集成与交互带来了极大的方便。
Xml基础知识
二:解析与生成XML文件的四种方式(DOM、SAX、JDOM和DOM4J)
XML在不同的语言里解析方式都是一样的,只不过实现的语法不同而已。
基本的解析方式有两种,一种叫SAX,另一种叫DOM。SAX是基于事件流的解析,DOM是基于XML文档树结构的解析。
假设XML的内容和结构如下:
<?xml version="1.0" encoding="utf-8"?>
<books>
<book >
<id>1001</id>
<name>Thinking In Java</name>
<price>80.00</price>
</book>
<book >
<id>1002</id>
<name>Core Java</name>
<price>90.00</price>
</book>
<book >
<id>1003</id>
<name>Hello, Andriod</name>
<price>100.00</price>
</book>
</books>
首先定义一个操作XML文档的接口XmlDocument,它定义了XML文档建立与解析的接口:
package com.zm.kingsoft.xml.Parser;
/**
* @author zm
* 定义XML文档建立与解析的接口
*/
public interface XmlDocument {
/**
* 解析XML文档
* @param fileName 解析的文件名称
* (文档位于assets文件夹下)
*/
void parserXml(String fileName);
/**
* 建立XML文档
* @param fileName 生成的文件名称
* (文档位于data/data/package name/files/)
*/
void createXml(String fileName);
}
1.DOM(Document Object Model)
DOM是用与平台和语言无关的方式表示XML文档的官方W3C标准。
解析器通过读入整个文档,构建一个驻留内存的树结构,然后代码就可以使用Dom接口来操作这个树结构。
优点:整个文档树在内存中,便于操作;支持删除、修改、重新排列等多种功能;
缺点:将整个文档调入内存,消耗资源大;
/**
* @author zm
* Dom方式解析与生成XML文档
*/
public class Dom implements XmlDocument {
private Context mContext;
private List<Book> books;
public Dom(Context context) {
super();
mContext = context;
books = new ArrayList<>();
}
@Override
public void parserXml(String fileName) {
books = new ArrayList<>();
try {
InputStream inputStream = mContext.getAssets().open(fileName);
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse(inputStream);//解析输入流,实例化document对象
inputStream.close();
Element root = document.getDocumentElement();
NodeList items = root.getElementsByTagName("book");
for(int i = 0;i<items.getLength();i++){
Book book = new Book();
Node item = items.item(i);
NodeList properties = item.getChildNodes();
for(int j = 0;j<properties.getLength();j++){
Node property = properties.item(j);
String nodeName = property.getNodeName();
switch (nodeName) {
case "id":
book.setId(property.getFirstChild().getNodeValue());
break;
case "name":
book.setName(property.getFirstChild().getNodeValue());
break;
case "price":
book.setPrice(property.getFirstChild().getNodeValue());
break;
}
}
books.add(book);
}
System.out.println(books.toString());
} catch (IOException | SAXException | ParserConfigurationException e) {
e.printStackTrace();
}
}
@Override
public void createXml(String fileName){
Document document = null;
//添加节点,实例化document
try {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
document = builder.newDocument();
Element root = document.createElement("books");
for(Book book:books){
Element bookElement = document.createElement("Book");
Element idElement = document.createElement("id");
idElement.setTextContent(book.getId());
bookElement.appendChild(idElement);
Element nameElement = document.createElement("name");
nameElement.setTextContent(book.getName());
bookElement.appendChild(nameElement);
Element priceElement = document.createElement("price");
priceElement.setTextContent(book.getPrice());
bookElement.appendChild(priceElement);
root.appendChild(bookElement);
}
document.appendChild(root);
} catch (ParserConfigurationException e) {
e.printStackTrace();
}
//XML输出
try {
TransformerFactory factory = TransformerFactory.newInstance();
Transformer transformer = factory.newTransformer();
transformer.setOutputProperty(OutputKeys.ENCODING,"UTF-8");
transformer.setOutputProperty(OutputKeys.INDENT,"yes");
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
DOMSource source = new DOMSource(document);//文档来源
StringWriter writer = new StringWriter();
Result result = new StreamResult(writer);//目标结果
transformer.transform(source, result);
FileOutputStream fos = mContext.openFileOutput(fileName, Context.MODE_PRIVATE);
fos.write(writer.toString().getBytes("UTF-8"));
fos.close();
} catch (IOException | TransformerException e) {
e.printStackTrace();
}
}
}
2.SAX(Simple API for XML)
SAX解析器采用了基于事件的模型。
当解析器发现元素开始、元素结束、文本、文档的开始或结束时,会回调相应的方法。
优点:不用事先调入整个文档,占用资源少;
缺点:需要应用程序自己负责TAG的处理逻辑(例如维护父/子关系等),文档越复杂程序就越复杂。
/**
* @author zm
* Sax方式解析与生成XML文档
*/
public class Sax implements XmlDocument{
private Context mContext;
private List<Book> books;
public Sax(Context context) {
super();
mContext = context;
books = new ArrayList<>();
}
@Override
public void parserXml(String fileName) {
MySaxHandler handler = new MySaxHandler();
try {
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser parser = factory.newSAXParser();
InputStream inputStream = mContext.getAssets().open(fileName);
parser.parse(inputStream,handler);
inputStream.close();
} catch (ParserConfigurationException | IOException | SAXException e) {
e.printStackTrace();
}
books = handler.getCollection();
System.out.println(books.toString());
}
@Override
public void createXml(String fileName) {
try {
SAXTransformerFactory factory = (SAXTransformerFactory) TransformerFactory.newInstance();
TransformerHandler handler= factory.newTransformerHandler();
Transformer transformer = handler.getTransformer();
transformer.setOutputProperty(OutputKeys.ENCODING,"UTF-8");
transformer.setOutputProperty(OutputKeys.INDENT,"yes");
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
StringWriter writer = new StringWriter();
Result result = new StreamResult(writer);//目标结果
handler.setResult(result);
String uri = ""; //代表命名空间的URI 当URI无值时 须置为空字符串
String localName = ""; //命名空间的本地名称(不包含前缀) 当没有进行命名空间处理时 须置为空字符串
char[] ch; //节点内容
handler.startDocument();
handler.startElement(uri, localName, "books", null);
for(Book book:books){
handler.startElement(uri,localName,"book",null);
handler.startElement(uri,localName,"id",null);
ch = book.getId().toCharArray();
handler.characters(ch,0,ch.length);
handler.endElement(uri, localName, "id");
handler.startElement(uri, localName, "name", null);
ch = book.getName().toCharArray();
handler.characters(ch,0,ch.length);
handler.endElement(uri, localName, "name");
handler.startElement(uri, localName, "price", null);
ch = book.getPrice().toCharArray();
handler.characters(ch,0,ch.length);
handler.endElement(uri, localName, "price");
handler.endElement(uri,localName,"book");
}
handler.endElement(uri, localName, "books");
handler.endDocument();
FileOutputStream fileOutputStream = mContext.openFileOutput(fileName,Context.MODE_PRIVATE);
fileOutputStream.write( writer.toString().getBytes("UTF-8"));
fileOutputStream.close();
} catch (TransformerConfigurationException | SAXException | IOException e) {
e.printStackTrace();
}
}
class MySaxHandler extends DefaultHandler {
private List<Book> books;
private Book book;
private StringBuilder builder;
public List<Book> getCollection(){
return books;
}
@Override
public void startDocument() throws SAXException {
super.startDocument();
//初始化
books = new ArrayList<>();
builder = new StringBuilder();
}
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
super.startElement(uri, localName, qName, attributes);
//标签开始
if(localName.equals("book")){
book = new Book();
}
builder.setLength(0);
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
super.endElement(uri, localName, qName);
//标签结尾
switch (localName) {
case "id":
book.setId(builder.toString());
break;
case "name":
book.setName(builder.toString());
break;
case "price":
book.setPrice(builder.toString());
break;
case "book":
books.add(book);
break;
}
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
super.characters(ch, start, length);
//标签内容
builder.append(ch,start,length);
}
}
}
3.JDOM(Java-based Document Object Model)
相对于DOM与SAX ,JDOM极大地减少了代码量,并且更加适合java开发者使用。
JDOM自身不包含解析器,它通常使用SAX解析器来解析和验证输入XML文档。
/**
* @author zm
* Jdom方式解析与生成XML文档
*/
public class Jdom implements XmlDocument{
private Context mContext;
private List<Book> books;
public Jdom(Context context) {
super();
mContext = context;
books = new ArrayList<>();
}
@Override
public void parserXml(String fileName) {
try {
SAXBuilder builder = new SAXBuilder();
InputStream inputStream = mContext.getAssets().open(fileName);
Document document = builder.build(inputStream);
inputStream.close();
Element root = document.getRootElement();
List items = root.getChildren("book", null);
for (Object item1 : items) {
Book book = new Book();
Element item = (Element) item1;
for (Object o : item.getChildren()) {
Element property = (Element) o;
String nodeName = property.getName();
switch (nodeName) {
case "id":
book.setId(property.getText());
break;
case "name":
book.setName(property.getText());
break;
case "price":
book.setPrice(property.getText());
break;
}
}
books.add(book);
}
System.out.println(books.toString());
} catch (JDOMException | IOException e) {
e.printStackTrace();
}
}
@Override
public void createXml(String fileName) {
Element root = new Element("books");
for(Book book:books){
Element bookElement = new Element("Book");
Element idElement = new Element("id");
idElement.setText(book.getId());
bookElement.addContent(idElement);
Element nameElement = new Element("name");
nameElement.setText(book.getName());
bookElement.addContent(nameElement);
Element priceElement = new Element("price");
priceElement.setText(book.getPrice());
bookElement.addContent(priceElement);
root.addContent(bookElement);
}
Document document = new Document(root);
try {
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
transformer.setOutputProperty(OutputKeys.ENCODING,"UTF-8");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
StringWriter writer = new StringWriter();
Source source = new JDOMSource(document);//文档来源
Result result = new StreamResult(writer);//目标结果
transformer.transform(source, result);
FileOutputStream fos = mContext.openFileOutput(fileName,Context.MODE_PRIVATE);
fos.write(writer.toString().getBytes("UTF-8"));
fos.close();
} catch (TransformerException | IOException e) {
e.printStackTrace();
}
}
}
4.DOM4J(Document Object Model for Java)
DOM4J 是一个非常非常优秀的Java XML API,具有性能优异、功能强大和极端易用的特点。
/**
* @author zm
* Dom4j方式解析与生成XML文档
*/
public class Dom4j implements XmlDocument{
private Context mContext;
private List<Book> books;
public Dom4j(Context context) {
super();
mContext = context;
books = new ArrayList<>();
}
@Override
public void parserXml(String fileName) {
try {
SAXReader reader = new SAXReader();
InputStream inputStream = mContext.getAssets().open(fileName);
Document document = reader.read(inputStream);
inputStream.close();
Element root = document.getRootElement();
List items = root.elements("book");
for (Object book1 : items) {
Book book = new Book();
Element itemBook = (Element) book1;
for (Iterator j = itemBook.elementIterator(); j.hasNext(); ) {
Element property = (Element) j.next();
String propertyNodeName = property.getName();
switch (propertyNodeName) {
case "id":
book.setId(property.getText());
break;
case "name":
book.setName(property.getText());
break;
case "price":
book.setPrice(property.getText());
break;
}
}
books.add(book);
}
System.out.println(books.toString());
} catch (DocumentException | IOException e) {
e.printStackTrace();
}
}
@Override
public void createXml(String fileName) {
try {
Document document = DocumentHelper.createDocument();//创建根节点
Element root = document.addElement("books");
for(Book book:books){
Element bookElement = root.addElement("Book");
Element idElement = bookElement.addElement("id");
idElement.setText(book.getId());
Element nameElement = bookElement.addElement("name");
nameElement.setText(book.getName());
Element priceElement = bookElement.addElement("price");
priceElement.setText(book.getPrice());
}
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
transformer.setOutputProperty(OutputKeys.ENCODING,"UTF-8");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
StringWriter writer = new StringWriter();
Source source = new DocumentSource(document);//文档来源
Result result = new StreamResult(writer);//目标结果
transformer.transform(source, result);
FileOutputStream fos = mContext.openFileOutput(fileName,Context.MODE_PRIVATE);
fos.write(writer.toString().getBytes("UTF-8"));
fos.close();
} catch (TransformerException | IOException e) {
e.printStackTrace();
}
}
}
参考:
http://developer.51cto.com/art/200903/117512.htm
http://www.cnblogs.com/lanxuezaipiao/archive/2013/05/17/3082949.html
Jdom :http://blog.chinaunix.net/uid-20359864-id-1700205.html
Dom4j:http://blog.csdn.net/redarmy_chen/article/details/12969219