XML 解析
解析XML有两种基本方式:
1)DOM
2)SAX
DOM解析器把 XML文档转化为一个包含其内容的树,并可以对树进行遍历。用DOM解析模型的优点是编程容易,开发人员只需要调用建树的指令,然后利用 navigation APIs访问所需的树节点来完成任务。可以很容易的添加和修改树中的元素。然而由于使用DOM解析器的时候需要处理整个XML文档,所以对性能和内存的要求比较高,尤其是遇到很大的XML文件的时候。由于它的遍历能力,DOM解析器常用于XML文档需要频繁的改变的服务中。
SAX解析器采用了基于事件的模型,它在解析XML文档的时候可以触发一系列的事件,当发现给定的tag的时候,它可以激活一个回调方法,告诉该方法制定的标签已经找到。SAX对内存的要求通常会比较低,因为它让开发人员自己来决定所要处理的tag。特别是当开发人员只需要处理文档中所包含的部分数据时,SAX这种扩展能力得到了更好的体现。但用SAX解析器的时候编码
工作会比较困难,而且很难同时访问同一个文档中的多处不同数据。
通俗点讲,Dom 解析器是将xml文档整个读入内存中以便查找,而SAX解析器只是依次解析读到的tag数据,当找到想要的数据时便可停止解析,不用读取整个XML文档至内存。有很多开源项目提供了各种用于解析xml的包,其原因无非是在dom和sax的原理基础上做一些优化工作。
Java中比较常用的操作xml的开源包有 dom4j、JDOM、Crimson、Commons-Digester等等。。(后两者均为apache开源包)。
当然JAVA 里也自带了一些包用于解析、保存xml:javax.xml包、org.w3c.dom、org.xml.sax,更多具体的操作方法可以查看java api文档(这几个包都是内置的,官方API文档里就其详尽的包描述)
这里我们使用javax.xml,org.w3c.dom,给出如何创建Dom树、如何从.xml文件中生成Dom树,如何将Dom树保存到xml文件中。
生成一个Document空的文档对象:
org.w3c.dom.Document doc = javax.xml.parsers.DocumentBuilderFactory.newInstance().
newDocumentBuilder().newDocument();
可以这样理解和记忆:要建立一个Document对象(这是一个产品),那么先要有一个工厂DocumentBuilderFactory,由工厂“招聘 “一个制造者DocumentBuilder,然后由制造者来生产Document对象。
工厂DocumentBuilderFactory没有公有的构造方法,只能用newInstance()取得一个工厂。同样DocumentBuilder也没有公共构造方法。这里涉及到设计模式里的“工厂方法模式”和“单态模式”,这样做的意义我们以后将在“设计模式”一块给出。
从.xml文件中生成Document对象:
javax.xml.parsers.DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new File(“fileName”));
其中parse方法可以是多种参数,可参看java api文档。
取得根结点:
doc.getDocumentElement().childNodes().item(0);
可以看到对dom树操作就类似于在javascript里用dom api操作xml了,事实上,两者都是有w3c标准化组织提供的。
文件存放xml Document对象。
javax.xml.transform.Transformer tf =
javax.xml.transform.TransformerFactory.newInstance().newTransformer();
tf.transform(new javax.xml.transform.dom.DOMSource(doc),
new javax.xml.transform.stream.StreamResult(new FileOutputStream(fileName)));
下面是一些简单的包装过的方法:
/**
*将dom树对象 doc存入fileName提定的文件中
**/
public void saveToFile(Document doc, String fileName) throws TransformerFactoryConfigurationError, FileNotFoundException, TransformerException{
javax.xml.transform.Transformer trans = javax.xml.transform.TransformerFactory.newInstance().newTransformer();
trans.transform(new javax.xml.transform.dom.DOMSource(doc),
new javax.xml.transform.stream.StreamResult(new FileOutputStream(fileName)));
}
/**
*生成一个带根结点名为 rootName的Dom树对象。
**/
public Document createXMLDoc(String rootName) throws FileNotFoundException, SAXException, IOException, ParserConfigurationException{
Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
doc.appendChild(doc.createElement(rootName));
return doc;
}
/**
*由给定文件名的xml文件生成一个Dom 树。
*/
public Document createXMLFromFile(String fileName) throws SAXException, IOException,
ParserConfigurationException {
File xmlFile = new File(fileName);
if (!xmlFile.exists()) {
System.err.println("File " + fileName + "doesn't exist!");
System.exit(0);
}
return DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(
fileName);
}