I am trying to parse a big XML file using Apache commons-digester3. I am interested in extract only certain data. The XML is quite complex and I would prefer not to build the whole structure but rather match the patterns I am interested in.
Say I have the following XML:
<?xml version="1.0"?>
<foo>
<level1>
<level2>
<bar>the bar</bar>
</level2>
</level1>
</foo>
And I have the following domain object that I want to parse into:
package my.pkg;
public class Foo {
private String bar;
// Note the name of the setter is not "setBar" but rather "setTheBar"
public void setTheBar(String bar) {
this.bar = bar;
}
}
And now I have the XML rules I am having problems to get them right:
<digester-rules>
<pattern value="foo">
<object-create-rule classname="my.pkg.Foo"/>
<pattern value="level1/level2/bar">
<!--What do I need to pout on here the get "the bar" value injected into my Foo instance-->
</pattern>
</pattern>
</digester-rules>
I tried all sorts of combinations of set-method-rule
, bean-property-setter-rule
, etc but all failed to give me what I wanted. What I want seems so basic I am sure the solution must be so obvious but I cannot get it.
Thank you in advance for your help.
I think a call-method-rule with "usingElementBodyAsArgument='true'" should work for you:
<digester-rules>
<pattern value='foo'>
<object-create-rule classname='my.pkg.Foo'/>
<pattern value='level1/level2/bar'>
<call-method-rule methodname='setTheBar'
usingElementBodyAsArgument='true'/>
</pattern>
</pattern>
</digester-rules>
However, I'd always note that XML rules are fairly limited - they can do all the basic stuff but miss quite a lot of more advanced functionality (custom rules etc.), and if you use digester regularly you may well find yourself moving from XML rules to programmatic rules at some point. Personally, I always use the programmatic rules now, as I know I can always do everything I need.
The programmatic equivalent of the XML rules above would be:
RulesModule rules = new AbstractRulesModule() {
@Override
public void configure() {
forPattern("foo")
.createObject().ofType(Foo.class);
forPattern("foo/level1/level2/bar")
.callMethod("setTheBar")
.withParamCount(1)
.usingElementBodyAsArgument();
}
};
DigesterLoader loader = DigesterLoader.newLoader(rules);
Digester digester = loader.newDigester();
Foo foo = (Foo)digester.parse(...);
Hope this helps.