The xmlrules package provides for XML-based definition of
rules for Digester. This improves maintainability of Java code,
as rules are now defined in XML and read into Digester at run-time.
This is a brief overview of the digester-rules-in-XML feature. Briefly,
this feature lets you define Digester rules in XML, instead of
creating and initializing the Rules objects programmatically, which can become
tedious. In addition, it allows for including of one XML rules file within
another, inclusion of programmatically created rule sets within an XML file
(via reflection), and recursively nested matching pattern specifications.
Overview of digester-rules.dtd
A DTD, named digester-rules.dtd has been defined to help in the
understanding of how the loader operates.
The DTD is distributed in the commons-digester.jar. It can be found at
org/apache/commons/digester/xmlrules/digester-rules.dtd. It is not available
for download from the Apache website since users are best advised to use a copy stored
on their local system.
Digester input documents wishing to cite this DTD should include the
following DOCTYPE declaration:
<!DOCTYPE digester-rules PUBLIC
"-//Jakarta Apache //DTD digester-rules XML V1.0//EN"
"digester-rules.dtd">
Rule elements:
The DTD defines an element type corresponding to each predefined Digester
rule. Each rule element type includes attributes for values needed to
initialize the rule, and an optional pattern attribute
specifying the pattern to associate with the rule.
The DigesterLoader adds the rules to the digester in the order in
which they occur in the XML.
The use of each rule element type should be self-explanatory, if you compare
them to the API documentation for the Digester rules classes.
Defining matching patterns:
The matching pattern is a simple, xpath-like string which the
Digester uses to determine which elements to apply each rule to.
See the Digesterdocumentation for
more details.
There are two methods for associating patterns to rules in the XML file. One
is for each rule element to directly define its pattern in a
pattern attribute. An example would like something like:
In the above example, an ObjectCreateRule is created and
associated with the pattern "*/foo"; then a SetPropertiesRule is
created and associated with the pattern "*/foo".
The other method is to nest rules elements inside a
<pattern> element. In this way, the same pattern can be
defined for a group of rules. The following example has the same effect as the
previous example:
In the above example, an ObjectCreateRule and a
SetPropertiesRule are associated with the matching pattern
"*/foo/bar".
The use of pattern elements and the use of the pattern attribute inside rules
elements can be freely mixed. The next example has the same effect as the
previous example:
Including rules XML files within other rules XML files:
The <include> element lets you include one rules file within
another. With respect to pattern concatenation, the DigesterLoader
behaves as if the include file was 'macro-expanded'. Example:
Note that the pattern for the 'bar' rule has been prepended with the 'root/foo'
pattern. If rule2.xml was parsed by itself, it would yield a Digester
initialized with this pattern/rule:
bar -> ObjectCreateRule(Bar)
Including programmatically-created rules:
Sometimes rules cannot be easily defined via XML. Rule sets that are created
programmatically can still be included within a digester-rules XML file. This
is done by using an <include> element with a
class attribute, containing the name of a class that implements
org.apache.commons.digester.xmlrules.DigesterRulesSource.
This interface defines one method, getRules(Digester), which
creates rules and adds them to the supplied Digester. The pattern concatenation
works exactly as if the rules had been included from an XML file. Example:
FromXmlRuleSet is a RuleSet implementation that
initializes its Digester from rules defined in an XML file. The
path to the XML file is passed to constructor.
Alternatively, the convenience class DigesterLoader defines a
static method,
Digester createDigester(String rulesXml) throws DigesterLoaderException".
When passing the name of the file that contains your digester rules, this
method returns a Digester instance initialized with the rules.
To add your own rules, you need to:
Update the DTD You should add an element type for your rule. The
element should have an attribute corresponding to each of the rule's
initialization parameters.
Define an ObjectCreationFactory
Extend DigesterRuleParser DigesterRuleParser
is a RuleSet for parsing a rules XML file. You should extend this,
and override the addRuleInstances() method to add the rules for
parsing your new element. Look in DigesterRuleParser.java to see how its done.
The
xmlrulespackage provides for XML-based definition of rules forDigester. This improves maintainability of Java code, as rules are now defined in XML and read intoDigesterat run-time.[DTD Overview]
[Rule Elements]
[Matching Patterns]
[Including rules files in other rules files]
[Including programmatically-created rules]
[Creating a digester from XML]
Introduction
This is a brief overview of the digester-rules-in-XML feature. Briefly, this feature lets you define Digester rules in XML, instead of creating and initializing the Rules objects programmatically, which can become tedious. In addition, it allows for including of one XML rules file within another, inclusion of programmatically created rule sets within an XML file (via reflection), and recursively nested matching pattern specifications.
Overview of digester-rules.dtd
A DTD, named
digester-rules.dtdhas been defined to help in the understanding of how the loader operates.The DTD is distributed in the
commons-digester.jar. It can be found atorg/apache/commons/digester/xmlrules/digester-rules.dtd. It is not available for download from the Apache website since users are best advised to use a copy stored on their local system.Digester input documents wishing to cite this DTD should include the following DOCTYPE declaration:
Rule elements:
The DTD defines an element type corresponding to each predefined Digester rule. Each rule element type includes attributes for values needed to initialize the rule, and an optional
patternattribute specifying the pattern to associate with the rule.The
DigesterLoaderadds the rules to the digester in the order in which they occur in the XML.The use of each rule element type should be self-explanatory, if you compare them to the API documentation for the
Digesterrules classes.Defining matching patterns:
The matching pattern is a simple, xpath-like string which the
Digesteruses to determine which elements to apply each rule to. See theDigesterdocumentation for more details.There are two methods for associating patterns to rules in the XML file. One is for each rule element to directly define its pattern in a
patternattribute. An example would like something like:<digester-rules> <object-create-rule pattern="*/foo" classname="Foo"/> <set-properties-rule pattern="*/foo"/> </digester-rules>In the above example, an
ObjectCreateRuleis created and associated with the pattern "*/foo"; then aSetPropertiesRuleis created and associated with the pattern "*/foo".The other method is to nest rules elements inside a
<pattern>element. In this way, the same pattern can be defined for a group of rules. The following example has the same effect as the previous example:<digester-rules> <pattern value="*/foo"> <object-create-rule classname="Foo"/> <set-properties-rule/> </pattern> </digester-rules>Pattern elements can be recursively nested. If patterns are nested, the pattern string is formed by concatenating all the patterns together. Example:
<digester-rules> <pattern value="*/foo"> <pattern value="bar"> <object-create-rule classname="Foobar"/> <set-properties-rule/> </pattern> </pattern> </digester-rules>In the above example, an
ObjectCreateRuleand aSetPropertiesRuleare associated with the matching pattern "*/foo/bar".The use of pattern elements and the use of the pattern attribute inside rules elements can be freely mixed. The next example has the same effect as the previous example:
<digester-rules> <pattern value="*/foo"> <object-create-rule pattern="bar" classname="Foobar"/> <set-properties-rule pattern="bar"/> </pattern> </digester-rules>Including rules XML files within other rules XML files:
The
<include>element lets you include one rules file within another. With respect to pattern concatenation, theDigesterLoaderbehaves as if the include file was 'macro-expanded'. Example:File rules1.xml: <?xml version="1.0"?> <!DOCTYPE digester-rules SYSTEM "digester-rules.dtd"> <digester-rules> <pattern value="root/foo"> <object-create-rule classname="Foo"/> <include path="rules2.xml"/> </pattern> </digester-rules> File rules2.xml: <?xml version="1.0"?> <!DOCTYPE digester-rules SYSTEM "digester-rules.dtd"> <digester-rules> <pattern value="bar"> <object-create-rule classname="Bar"/> </pattern> </digester-rules>Parsing rule1.xml would result in a
Digesterinitialized with these pattern/rule pairs:root/foo -> ObjectCreateRule(Foo)
root/foo/bar -> ObjectCreateRule(Bar)
Note that the pattern for the 'bar' rule has been prepended with the 'root/foo' pattern. If rule2.xml was parsed by itself, it would yield a
Digesterinitialized with this pattern/rule:bar -> ObjectCreateRule(Bar)
Including programmatically-created rules:
Sometimes rules cannot be easily defined via XML. Rule sets that are created programmatically can still be included within a digester-rules XML file. This is done by using an
<include>element with aclassattribute, containing the name of a class that implementsorg.apache.commons.digester.xmlrules.DigesterRulesSource. This interface defines one method,getRules(Digester), which creates rules and adds them to the supplied Digester. The pattern concatenation works exactly as if the rules had been included from an XML file. Example:File rules3.xml: <?xml version="1.0"?> <!DOCTYPE digester-rules SYSTEM "digester-rules.dtd"> <digester-rules> <pattern value="root/foo"> <object-create-rule classname="Foo"/> <include class="BarRuleCreator"/> </pattern> </digester-rules>BarRuleCreator class definition:
public class BarRuleCreator implements DigesterRulesSource { public void getRules(Digester digester) { digester.addObjectCreate("bar", "Bar"); } }Parsing rules3.xml yields the same results as rules1.xml above:
root/foo -> ObjectCreateRule(Foo)
root/foo/bar -> ObjectCreateRule(Bar)
Creating a digester from XML:
FromXmlRuleSetis aRuleSetimplementation that initializes itsDigesterfrom rules defined in an XML file. The path to the XML file is passed to constructor.Alternatively, the convenience class DigesterLoader defines a static method,
Digester createDigester(String rulesXml) throws DigesterLoaderException". When passing the name of the file that contains your digester rules, this method returns aDigesterinstance initialized with the rules.To add your own rules, you need to:
You should add an element type for your rule. The element should have an attribute corresponding to each of the rule's initialization parameters.
ObjectCreationFactoryDigesterRuleParserDigesterRuleParseris aRuleSetfor parsing a rules XML file. You should extend this, and override theaddRuleInstances()method to add the rules for parsing your new element. Look in DigesterRuleParser.java to see how its done.