技术开发 频道

使用Apache宝石Digester改善XML处理



五、Digester的标准规则

1. 创建规则(Creational)

对象创建规则(ObjectCreateRule):
    根据指定类和它的默认构造方法创建一个对象,并将其压栈。当这个结点处理完后,并这个对象弹出。这个类可以通过类对象或类的全名进实例化。
 
工厂创建规则(FactoryCreateRule):

    使用指定的工厂类创建一个对象,并将其压栈。这个类没有默认的构造方法的工厂类是非常有用的。这个工厂类必须实现org.apache.commons.digester.ObjectCreationFactory接口。

2. 属性设置规则(Property Setters)

SetPropertiesRule:
    使用指定的XML结点属性来设置栈的顶层bean的一个或多个属性。属性名通过String[]数组传递,如处理象<article page="30">的XML指令。

BeanPropertySetterRule:

    通过当前XML结点的字符串值设置栈顶对象的属性,如<page>30</page>。

SetPropertyRule:

    这个规则设置一个最顶层的对象的属性,需要有两个值,key和value。如<article key="page" value="10" />。

3. 父 / 子管理规则(Parent/Child Management)
SetNextRule:
    弹出最顶层的对象,并将它传递给这个对象下面的指定的方法。类似将子结点插入到父结点的下面。

SetTopRule:

    将栈的第二个对象传给顶层对象。这对于当子对象有一个setParent方法而不是其他方法时非常有用。

SetRootRule:

    调用栈底部对象的一个方法,并将顶层对象作为一个参数传入。
 
4. 调用任意方法
CallMethodRule:
    调用最顶层bean的指定的任意方法。这个方法可以有任意个参数。参数值通过CallParamRule给出。

CallParamRule:

    描述方法参数的值。参数值或者是XML结点的属性值,或是XML结点的字符串内容值。这个规则要求参数的位置必须由一个整数索引指定。
六、使用xmlrules包指定XML规则

    到现在为止,我们已经学习了如何在编译时指定模式和规则。这些方法更简单和直接,但感觉有点单一。在本节中,我们将介绍如何在运行时来组织和处理XML指令和数据。在这让我们先来修理一下编译时的行为。我们从代码中可以看出,在源代码中有很多固定的东西(这些东西是不可编程的),而这些都可以在运行时完成。

    不过不用担心,读取这些信息无须读者自己做,在Digester中提供了一个包:org.apache.commons.digester.xmlrules。这个包中的类可以从一个XML文档中读取并返回一个指定的配置信息。XML文档配置文件必须使用DTD,这是xmlrules包的一部分。

下面是一个在这们例子中使用的XML规则的配置文件rules.xml。在看这个文件之前,我将有几点说明。
   
    模式可以由两种不同的方式指定:一种是每一个XML结点属性描述一个规则,或使用<pattern>结点。这些被定义的模式对于所有的规则结点都是可用的。这两种方式可以混合使用,并且<pattern>结点可以嵌套。在这种情况下,被子结点定义的pattern被加到<pattern>结点之后。
    <alias>结点用来和<set-propeties-rule>一起使用来将XML结点的属性映射成Bean的属性。下面是rules.xml的代码:

<?xml version="1.0"?> <digester-rules> <object-create-rule pattern="catalog" classname="Catalog" /> <set-properties-rule pattern="catalog" > <alias attr-name="library" prop-name="library" /> </set-properties-rule> <pattern value="catalog/book"> <object-create-rule classname="Book" /> <call-method-rule pattern="author" methodname="setAuthor" paramcount="0" /> <call-method-rule pattern="title" methodname="setTitle" paramcount="0" /> <set-next-rule methodname="addBook" /> </pattern> <pattern value="catalog/magazine"> <object-create-rule classname="Magazine" /> <call-method-rule pattern="name" methodname="setName" paramcount="0" /> <pattern value="article"> <object-create-rule classname="Article" /> <set-properties-rule> <alias attr-name="page" prop-name="page" /> </set-properties-rule> <call-method-rule pattern="headline" methodname="setHeadline" paramcount="0" /> <set-next-rule methodname="addArticle" /> </pattern> <set-next-rule methodname="addMagazine" /> </pattern> </digester-rules>

    上面的xml已经将所有的模式和规则设置完成,而调用类就变得非常简单了。为了运行它。我们需要通过命令行指定catalog和rules.xml文件名。(要注意的是,DigesterLoader不能通过rules.xml文件名去读文件或使用org.xml.sax.InputSource,而需要一个URL)。代码如下:

import org.apache.commons.digester.*; import org.apache.commons.digester.xmlrules.*; import java.io.*; import java.util.*; public class XmlRulesDriver { public static void main( String[] args ) { try { File input = new File( args[0] ); File rules = new File( args[1] ); Digester digester = DigesterLoader.createDigester( rules.toURL() ); Catalog catalog = (Catalog)digester.parse( input ); System.out.println( catalog.toString() ); } catch( Exception exc ) { exc.printStackTrace(); } } }
七、结论

    到现在为止Digester的主要功能已经讲完了。当然,Digester的功能还远不止这些。Digester还可以处理XML命名空间,而且还可以根据指定的命名空间来设置规则。

    在本文中未详细描述如何开发定制规则,不过这个非常简单,只需要继承Rule类,并实现相应的方法即可。Digester类还提供了push()、peek()和pop()方法,这此方法可以为开发人员提供更大的弹性(可以自由地将对象从栈中弹出或压入)。   
0
相关文章