1. XML语法解析方式
XML解析方法是理论知识,不止在java里是这样,换到其他语言下也是一样的。目前有三种:
A. DOM(Document Object Model): DOM方法一次把XML的所有内容读入内存,按照xml的内容里面的node,attribute等生成一个树状结构。这就是一个对象模型了,完了我们就可以对这个树状结构进行操作。DOM的特点是编程简单,明了;缺点是要一次性读入所有内容
B. SAX(Simple API for XML): SAX是一种基于事件的解析方式,通过回调函数嵌入自己的代码。在解析前要定义好回调函数,在SAX开始解析后,一旦产生事件就会调用回调函数,比如一旦发现一个子节点就调用一个回调函数。SAX不像DOM一样有清晰的父子,树结构关系,要在回调函数里自己维护node之间的关系。因为SAX不需要维护树,所以它不要一次读入所有XML,但是编程难度比DOM大。
C. StAX(Streaming API for XML ): StAX是一种新的XML解析方式,它更像SAX,也是基于事件的,也不需要一次读入所有内容。和SAX的不同在于,SAX的事件是push的,而StAX是pull的。SAX通过让解析器调用回调函数把事件推送出来,而StAX则有一个主动去pull事件的接口,当调用pull的接口时,解析器去读取下一部分xml并产生事件返回。StAX相对SAX的好处是可以主动控制解析过程,甚至提前中止解析。
2. XML语法解析器
上面说的都是理论,只是解析的方法,还是需要工具安装上面的方法来真正的去解析XML,这就是XML解析器。
常看到的语法解析器有两种,Xerces和Crimson。 前者最早是IBM开发的,后者是SUN开发的,现在都是开源的。Crimson的效率比Xerces差很多,所以其实现在基本都是用Xerces了。
3. JAXP(Java API for XML Processing)
SUN在做Java的时候喜欢预留接口,像JDBC,Script等等。 因为有很多XML语法解析器,大家的接口是不一样的。为了简化开发,也方便替换解析器实现,SUN定义了JAXP接口。通常XML语法解析器都会实现这些接口,这样就保证了在不改变代码的情况下更改解析器实现。 怎么替换一个解析器呢? JAXP的DocumentBuilderFactory和SAXParserFactory类都有一个newInstance方法,他们都是类似的内容,以SAX为例:
- return (DocumentBuilderFactory) FactoryFinder.find(
- /* The default property name according to the JAXP spec */
- "javax.xml.parsers.DocumentBuilderFactory",
- /* The fallback implementation class name */
- "com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl");
传入了两个参数,看注释,第一个是一个属性名字,第二个是一个类名字。 FactoryFinder.find实现的功能就是,先按照属性去java程序的参数里找,如果找到了参数就按参数里指定的类名去构造解析器,如果没有就按照第二个参数里指定的类名字去构造解析器。 所以只要在启动程序的时候加上参数 -Davax.xml.parsers.SAXParserFactory=指定的类名 就可以替换解析器了。
4. DOM接口
按照JAXP的接口,DOM解析出来的对象是一个org.w3c.dom.Document实例,人们发现w3c的接口非常难用, 所以就产生了封装org.w3c.dom.Document的想法,于是就出现了JDOM和DOM4J,他们都是一样的目的,只是接口不一样。 最终DOM4J比JDOM在效率上领先。
5. JAXB(Java Architecture for XML Binding)
关系数据库通过OR-mapping实现表内数据和java对象的转换,XML也有方式实现和java对象的转换,叫做oxm(Object XML Mapping).
JAXB就是一个oxm的规范,又是SUN制定的。和JAXP一样,它也是定义好一些接口让厂商去实现,同时还定义了一些功能规范。和JAXP一样,JAXB也定义了方法把实现的类名传进去,随着时代的发展,它比JAXP多了两种方式,所以共三种方式。
A. 在要mapping的java类的同一个包内加入一个文件 jaxb.properties,在文件里定义javax.xml.bind.context.factory属性指定类名。
B. 像JAXP一样,通过加启动参数 -Djavax.xml.bind.JAXBContext 来指定类名
C. 通过在META-INF/services/目录下加一个名为javax.xml.bind.JAXBContext 的文件,文件里指定实现类名。
因为代码量原因,我就不贴了,可以查看Context源码的find方法。其中第三种方式在java 1.6里被抽象出一个java的新功能,叫ServiceRegistry,可以去查看API文档了解详情。
关键字:JAVA XML DOM SAX StAX Xerces Crimson JAXP JDOM DOM4J JAXB