Digester 详细介绍 : apache common digester ,这里描述一个常见问题的解决方案
问题:
Digester 作为 SAX 解析 xml 的实现,它的原理就是制定一些规则,在遍历每个节点时检查是否有匹配的规则,如果有就执行对应的操作 。
比如:
InputStream is = new FileInputStream(file);
Digester digester = new Digester();
digester.push(this);
digester.setValidating(false);
digester.addObjectCreate("level1", Level1.class);
digester.addBeanPropertySetter("level1/property","property");
digester.addSetNext("level1","register");
digester.parse(is);
这段代码即遇见level1标签就就新建 Level1 实例对象 L,并把 property 子标签的标签值付给 L 对象的 property 属性。这里就遇到了空格问题,如果property 子标签中前后有空白,可以实验得到 L对象的property属性是trim过后的值,如果想要保留空白呢?
分析:
由于 digester 的一个动作对应一个rule,则看一下 addBeanPropertySetter 的实现:
public void addBeanPropertySetter(String pattern,
String propertyName) {
addRule(pattern,new BeanPropertySetterRule(propertyName));
}
那么可以看一下 BeanPropertySetterRule 的实现 ,首先知道 rule 通过其 body 方法来得到标签内的字符串值,则可以看一下 body 方法 :
/**
* Process the body text of this element.
*
* @param namespace the namespace URI of the matching element, or an
* empty string if the parser is not namespace aware or the element has
* no namespace
* @param name the local name if the parser is namespace aware, or just
* the element name otherwise
* @param text The text of the body of this element
*/
public void body(String namespace, String name, String text)
throws Exception {
// log some debugging information
if (digester.log.isDebugEnabled()) {
digester.log.debug("[BeanPropertySetterRule]{" +
digester.match + "} Called with text '" + text + "'");
}
bodyText = text.trim()
}
可见,由 rule 获得 标签值是已经 trim 过的,当然就没有办法了么?
解决:
自定义rule
由于系统自带的所有rule都是继承自 rule ,而实现一些公共接口,而现在要求和 BeanPropertySetterRule 没什么区别,只不过要求 body 方法不要对值进行 trim,则可以自己写个rule :
public class BeanPropertySetterRuleWhiteSpace extends Rule {
//......省略
public void body(String namespace, String name, String text)
throws Exception {
//不要 trim
bodyText = text;
}
}
那么根据 addBeanPropertySetter 的调用,可以这样子写了 :
digester.addBeanPropertySetter("level1/property","property");
==
digester.addRule("level1/property",new BeanPropertySetterRuleWhiteSpace("property"));
则最终解析得到的 Level1 实例的 property 属性前后空格得以保存。