11.3 使用dom4j访问XML文档
前面已经提到,使用dom4j访问XML文档是非常简单的,它的处理方式与W3C的DOM处理很接近,而且更简单易用。
11.3.1 验证XML文档
dom4j也可以正常验证XML文档的有效性,包括使用DTD和使用Schema来进行验证。
如果程序员只需要使用DTD验证XML文档,则只需调用SAXReader的如下方法即可:
setValidation(boolean validation):启用DTD验证XML文档的有效性。该方法仅对DTD语义约束有效,对XML Schema语义约束没有任何作用。
提示
实际上完全可以在创建SAXReader时使用如下构造器:new SAXReader(true);通过该构造器所创建出来的SAXReader默认就已经打开了DTD验证功能。
dom4j完全支持使用XML Schema来验证XML文档的有效性,dom4j的SAXReader解析器提供了如下方法来启用验证:
如果XML文档中没有引入对应的XML Schema,则还需要告诉SAXReader应使用哪个Schema来验证XML文档的有效性,为此需要设置如下代码:
下面的程序示范了如何使用dom4j来验证XML文档的有效性:
程序清单:codes\11\11.3\src\lee\Dom4jValidate.java
①号代码处设置了验证XML文档所使用的Schema,如果要验证的XML文档中已经引入了Schema语义约束,则这段代码完全可以省略。
如果上面的程序验证的XML文档不是有效文档,将可看到图11.2所示结果。
图11.2 使用dom4j验证XML文档的有效性
11.3.2 使用dom4j解析XML文档
使用dom4j解析XML文档也非常简单,在将XML文档转换成dom4j树之后,程序就可使用一致的编程模型来处理XML文档了,我们可以使用“递归”方法来获取整份XML文档里包含的信息。
程序清单:codes\11\11.3\src\lee\Dom4jRead.java
上面的程序中允许使用两种解析器来解析XML文档,这两种解析器只是在底层处理上存在区别,这种区别对程序员而言完全透明。
提示
使用XPP3Reader作为解析器来解析XML文档时底层需要依赖XML Pull Parser 3.x,因此需要将dom4j项目lib目录下的xpp3-1.1.3.3.jar文件添加到系统类加载路径中。
使用上面的程序来解析如下XML文档:
程序清单:codes\11\11.3\book.xml
解析结果如图11.3所示:
图11.3 使用dom4j解析XML文档
11.3.3 使用访问者模式遍历XML文档
dom4j的Node接口中定义了一个accept(Visitor visitor)方法,由于该方法是在Node接口中定义的,因此dom4j树中的任何节点都可以调用该方法,调用该方法时传入的Visitor对象将负责处理该节点及其所有子节点的信息。
Visitor是dom4j提供的一个接口,该接口里包含如下几个方法:
visit(Attribute node):当Visitor对象访问属性节点时将回调该方法。
visit(CDATA node):当Visitor对象访问CDATA片段时将回调该方法。
visit(Comment node):当Visitor对象访问注释节点时将回调该方法。
visit(Document document):当Visitor对象访问文档根节点时将回调该方法。
visit(DocumentType documentType):当Visitor对象访问DTD内容时将回调该方法。
visit(Element node):当Visitor对象访问元素节点时将回调该方法。
visit(Entity node):当Visitor对象访问Entity节点时将回调该方法。
visit(Namespace namespace):当Visitor对象访问命名空间时将回调该方法。
visit(ProcessingInstruction node):当Visitor对象访问处理指令时将回调该方法。
visit(Text node):当Visitor对象访问文档内容时将回调该方法。
由于dom4j的任何节点都可调用accept(Visitor visitor)方法,因此可以非常方便地使用访问者模式读取XML文档的部分内容。如果希望访问整个XML文档的内容,直接调用Document节点的accept(Visitor visitor)方法即可。下面的程序示范了如何使用访问者模式来读取XML文档的元素、属性和处理指令。
程序清单:codes\11\11.3\src\lee\VisitorRead.java
上面的程序中提供了一个Visitor实现类,这个实现类并没有实现Visitor接口,而是继承了VisitorSupport类。这是因为VisitorSupport类已经实现了Visitor接口,并实现了该接口包含的所有抽象方法,为这些方法提供了空实现。
提示
Visitor接口和VisitorSupport类的关系就像事件监听器接口和事件适配器一样,VisitorSupport类实现了Visitor接口,并为每个方法提供了空实现。当开发者通过继承VisitorSupport来实现自己的Visitor时就可以只重写自己关心的方法,从而避免重写Visitor接口里的所有方法。
上面的Visitor里只实现了visit(Element node)、visit(Attribute node)和visit(ProcessingInstruction node)3个方法,这意味着该Visitor只处理XML文档里的元素、属性和处理指令。上面的程序依然处理前一节的XML文档,运行上面的程序可看到图11.4所示结果。
图11.4 使用访问者模式读取XML文档
注意
访问者模式依然有点类似于事件机制的解析方式。区别是:访问者模式里的Visitor对象既充当解析器,也充当事件监听器。当使用Visitor访问XML文档时,访问不同的节点元素时将自动触发Visitor里对应的方法。