commons-digester解析xml

http://commons.apache.org/proper/commons-digester/guide/binder.html


You configure the Digester by implementing RulesModule. You pass DigesterLoader a module, the DigesterLoader passes your module a RulesBinder, and your module uses the binder to configure patterns/rules bindings. A binding most commonly consist of a mapping between a pattern and one or more Rule. For example:

class EmployeeModule
    implements RulesModule
{

    protected void configure( RulesBinder rulesBinder )
    {
        rulesBinder.forPattern( "employee" ).createObject().ofType( Employee.class );
        rulesBinder.forPattern( "employee/firstName" ).setBeanProperty();
        rulesBinder.forPattern( "employee/lastName" ).setBeanProperty();

        rulesBinder.forPattern( "employee/address" )
            .createObject().ofType( Address.class )
            .then()
            .setNext( "addAddress" );
        rulesBinder.forPattern( "employee/address/type" ).setBeanProperty();
        rulesBinder.forPattern( "employee/address/city" ).setBeanProperty();
        rulesBinder.forPattern( "employee/address/state" ).setBeanProperty();
    }

}

DRY (Don't Repeat Yourself): Repeating "rulesBinder" over and over for each binding can get a little tedious. The Digester package provides a module support class named AbstractRulesModule which implicitly gives you access to RulesBinder's methods. For example, we could extend AbstractRulesModule and rewrite the above binding as:

class EmployeeModule
    extends AbstractRulesModule
{

    @Override
    protected void configure()
    {
        forPattern( "employee" ).createObject().ofType( Employee.class );
        forPattern( "employee/firstName" ).setBeanProperty();
        forPattern( "employee/lastName" ).setBeanProperty();

        forPattern( "employee/address" )
            .createObject().ofType( Address.class )
            .then()
            .setNext( "addAddress" );
        forPattern( "employee/address/type" ).setBeanProperty();
        forPattern( "employee/address/city" ).setBeanProperty();
        forPattern( "employee/address/state" ).setBeanProperty();
    }

}

http://commons.apache.org/proper/commons-digester/guide/plugins.html


An Example

Let's start off with an example.

Given the following digester rules in the main "parsing" application:

        Digester digester = new Digester();
        PluginRules rc = new PluginRules();
        digester.setRules( rc );

        digester.addObjectCreate( "pipeline", Pipeline.class );

        digester.addCallMethod( "pipeline/source", "setSource", 1 );
        digester.addCallParam( "pipeline/source", 0, "file" );

        PluginCreateRule pcr = new PluginCreateRule( Transform.class );
        digester.addRule( "pipeline/transform", pcr );
        digester.addSetNext( "pipeline/transform", "setTransform" );

        digester.addCallMethod("pipeline/destination", "setDest", 1);
        digester.addCallParam("pipeline/destination", 0, "file");

        digester.parse( filename );

the following input can be processed:

    <pipeline>
      <source file="input.txt"/>
      <transform plugin-class="SubstituteTransform">
        <from>changeme</from>
        <to>changed</to>
      </transform>
      <destination file="output.txt"/>
    </pipeline>


http://commons.apache.org/proper/commons-digester/guide/core.html

Processing Rules

The previous section documented how you identify when you wish to have certain actions take place. The purpose of processing rules is to define what should happen when the patterns are matched.

Formally, a processing rule is a Java class that subclasses the org.apache.commons.digester3.Rule interface. Each Rule implements one or more of the following event methods that are called at well-defined times when the matching patterns corresponding to this rule trigger it:

  • begin() - Called when the beginning of the matched XML element is encountered. A data structure containing all of the attributes corresponding to this element are passed as well.
  • body() - Called when nested content (that is not itself XML elements) of the matched element is encountered. Any leading or trailing whitespace will have been removed as part of the parsing process.
  • end() - Called when the ending of the matched XML element is encountered. If nested XML elements that matched other processing rules was included in the body of this element, the appropriate processing rules for the matched rules will have already been completed before this method is called.
  • finish() - Called when the parse has been completed, to give each rule a chance to clean up any temporary data they might have created and cached.

As you are configuring your digester, you can call the addRule() method to register a specific element matching pattern, along with an instance of a Rule class that will have its event handling methods called at the appropriate times, as described above. This mechanism allows you to create Rule implementation classes dynamically, to implement any desired application specific functionality.

In addition, a set of processing rule implementation classes are provided, which deal with many common programming scenarios. These classes include the following:

  • ObjectCreateRule - When the begin() method is called, this rule instantiates a new instance of a specified Java class, and pushes it on the stack. The class name to be used is defaulted according to a parameter passed to this rule's constructor, but can optionally be overridden by a classname passed via the specified attribute to the XML element being processed. When the end() method is called, the top object on the stack (presumably, the one we added in the begin() method) will be popped, and any reference to it (within the Digester) will be discarded.
  • FactoryCreateRule - A variation of ObjectCreateRule that is useful when the Java class with which you wish to create an object instance does not have a no-arguments constructor, or where you wish to perform other setup processing before the object is handed over to the Digester.
  • SetPropertiesRule - When the begin() method is called, the digester uses the standard Java Reflection API to identify any JavaBeans property setter methods (on the object at the top of the digester's stack) who have property names that match the attributes specified on this XML element, and then call them individually, passing the corresponding attribute values. These natural mappings can be overridden. This allows (for example) a class attribute to be mapped correctly. It is recommended that this feature should not be overused - in most cases, it's better to use the standard BeanInfo mechanism. A very common idiom is to define an object create rule, followed by a set properties rule, with the same element matching pattern. This causes the creation of a new Java object, followed by "configuration" of that object's properties based on the attributes of the same XML element that created this object.
  • SetPropertyRule - When the begin() method is called, the digester calls a specified property setter (where the property itself is named by an attribute) with a specified value (where the value is named by another attribute), on the object at the top of the digester's stack. This is useful when your XML file conforms to a particular DTD, and you wish to configure a particular property that does not have a corresponding attribute in the DTD.
  • SetNextRule - When the end() method is called, the digester analyzes the next-to-top element on the stack, looking for a property setter method for a specified property. It then calls this method, passing the object at the top of the stack as an argument. This rule is commonly used to establish one-to-many relationships between the two objects, with the method name commonly being something like "addChild".
  • SetTopRule - When the end() method is called, the digester analyzes the top element on the stack, looking for a property setter method for a specified property. It then calls this method, passing the next-to-top object on the stack as an argument. This rule would be used as an alternative to a SetNextRule, with a typical method name "setParent", if the API supported by your object classes prefers this approach.
  • CallMethodRule - This rule sets up a method call to a named method of the top object on the digester's stack, which will actually take place when the end() method is called. You configure this rule by specifying the name of the method to be called, the number of arguments it takes, and (optionally) the Java class name(s) defining the type(s) of the method's arguments. The actual parameter values, if any, will typically be accumulated from the body content of nested elements within the element that triggered this rule, using the CallParamRule discussed next.
  • CallParamRule - This rule identifies the source of a particular numbered (zero-relative) parameter for a CallMethodRule within which we are nested. You can specify that the parameter value be taken from a particular named attribute, or from the nested body content of this element.
  • NodeCreateRule - A specialized rule that converts part of the tree into a DOM Node and then pushes it onto the stack.

You can create instances of the standard Rule classes and register them by calling digester.addRule(), as described above. However, because their usage is so common, shorthand registration methods are defined for each of the standard rules, directly on the Digester class. For example, the following code sequence:

    Rule rule = new SetNextRule( digester, "addChild",
                                 "com.mycompany.mypackage.MyChildClass" );
    digester.addRule( "a/b/c", rule );

can be replaced by:

    digester.addSetNext( "a/b/c", "addChild",
                         "com.mycompany.mypackage.MyChildClass" );

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值