利用commons-digester解析xml

jakarta的commons中的digester是非常优秀的xml解析工具,这个工具提供了从
xml->javabean的映射。相较于传统的w3c、sax方式解析xml文档,digester的层次更高,适合更懒得家伙。
下面这个例子简单,就是一个简单的存储数据,xml文件由schema文件约束,映射到对应的javabean当中,当然功能还不是很完善,作用也不够通用。
schema文件如下:

<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema"
	targetNamespace="http://www.example.org/final"
	xmlns:tns="http://www.example.org/final"
	elementFormDefault="qualified">

	<element name="doc">
		<complexType>
			<sequence>
				<element name="prvs" type="tns:prvs-type" />
				<element name="usrs" type="tns:usrs-type" />
			</sequence>
		</complexType>
	</element>

	<complexType name="prvs-type">
		<sequence>
			<element name="prv" minOccurs="0" maxOccurs="unbounded"
				type="tns:prv-type" />
		</sequence>
	</complexType>

	<complexType name="usrs-type">
		<sequence>
			<element name="usr" minOccurs="0" maxOccurs="unbounded"
				type="tns:usr-type" />
		</sequence>
	</complexType>

	<complexType name="prv-type">
		<sequence>
			<element name="name" type="string" />
			<element name="descr" type="string" />
		</sequence>
		<attribute name="prv_id" type="integer" use="required" />
	</complexType>

	<complexType name="usr-type">
		<sequence>
			<element name="name" type="string" />
			<element name="pwd" type="string" />
			<element name="prvs">
				<complexType>
					<sequence>
						<element name="prv_id" type="integer"
							minOccurs="0" maxOccurs="unbounded" />
					</sequence>
				</complexType>
			</element>
		</sequence>
		<attribute name="usr_id" type="integer" use="required" />
	</complexType>
</schema>

 对应2个具体的javabean:
一个是user类,代码如下:

package com.cxz.xmldb;

import java.util.HashSet;
import java.util.Set;
import java.util.Collections;

public class User {
	private int usr_id;

	private String name;

	private String pwd;

	private Set<Integer> prvs_id = Collections
			.synchronizedSet(new HashSet<Integer>());

	private Set<Privilege> prvs = Collections
			.synchronizedSet(new HashSet<Privilege>());

	public String getPwd() {
		return pwd;
	}

	public void setPwd(String pwd) {
		this.pwd = pwd;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getUsr_id() {
		return usr_id;
	}

	public void setUsr_id(int usr_id) {
		this.usr_id = usr_id;
	}

	public void addPrv(Privilege priv) throws DuplicateException {
		if (!prvs.add(priv))
			throw new DuplicateException(
					"The privilege had been duplicated created.");
	}

	public void rmvPrv(Privilege priv) {
		prvs.remove(priv);
	}

	public void addPrvId(Integer priv) throws DuplicateException {
		if (!prvs_id.add(priv))
			throw new DuplicateException(
					"The privilegeId had been duplicated created.");
	}

	public void rmvPrvId(Integer priv) {
		prvs_id.remove(priv);
	}

	public Set<Privilege> getPrvs() {
		return prvs;
	}

	public void setPrvs(Set<Privilege> prvs) {
		this.prvs = prvs;
	}

	public Set<Integer> getPrvs_id() {
		return prvs_id;
	}

	public void setPrvs_id(Set<Integer> prvs_id) {
		this.prvs_id = prvs_id;
	}

	@Override
	public int hashCode() {
		final int PRIME = 31;
		int result = 1;
		result = PRIME * result + usr_id;
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		final User other = (User) obj;
		if (usr_id != other.usr_id)
			return false;
		return true;
	}

}

 

 
另一个类是privilege类:

package com.cxz.xmldb;

public class Privilege {
	private int prv_id;

	private String name;

	private String descr;

	public String getDescr() {
		return descr;
	}

	public void setDescr(String descr) {
		this.descr = descr;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getPrv_id() {
		return prv_id;
	}

	public void setPrv_id(int prv_id) {
		this.prv_id = prv_id;
	}

	@Override
	public int hashCode() {
		final int PRIME = 31;
		int result = 1;
		result = PRIME * result + prv_id;
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		final Privilege other = (Privilege) obj;
		if (prv_id != other.prv_id)
			return false;
		return true;
	}
}

 下面这个是xml数据文件,包括了具体的关系:

<?xml version="1.0" encoding="UTF-8"?>
<doc xmlns="http://www.example.org/final"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.example.org/final doc.xsd ">
	<prvs>
		<prv prv_id="0">
			<name>read</name>
			<descr>read the file</descr>
		</prv>
		<prv prv_id="1">
			<name>write</name>
			<descr>write the file</descr>
		</prv>
		<prv prv_id="2">
			<name>execute</name>
			<descr>execute the file</descr>
		</prv>
	</prvs>
	<usrs>
		<usr usr_id="2003710201">
			<name>cxz</name>
			<pwd>19841230</pwd>
			<prvs>
				<prv_id>0</prv_id>
				<prv_id>1</prv_id>
				<prv_id>2</prv_id>
			</prvs>
		</usr>
		<usr usr_id="2003710202">
			<name>wm</name>
			<pwd>19841230</pwd>
			<prvs>
				<prv_id>0</prv_id>
				<prv_id>1</prv_id>
			</prvs>
		</usr>
		<usr usr_id="2003710203">
			<name>wjt</name>
			<pwd>19841230</pwd>
			<prvs>
				<prv_id>1</prv_id>
				<prv_id>2</prv_id>
			</prvs>
		</usr>
	</usrs>
<!--
	<ulist>
		yxiong = role,role2...
		ben = role2
	</ulist>
	
	<pri>
		role = a.jsp,b.action,....
	</pri>
 -->		
</doc>

 这个类代表了整个文档

package com.cxz.xmldb;

import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

public class Document {
	private Set<Privilege> prvs = Collections
			.synchronizedSet(new HashSet<Privilege>());

	private Set<User> usrs = Collections.synchronizedSet(new HashSet<User>());

	public Document() {
	}

	public void addPrivilege(Privilege p) throws DuplicateException {
		if (!prvs.add(p))
			throw new DuplicateException("Duplicated Priv");
	}

	public void removePrivilege(Privilege p) {
		prvs.remove(p);
	}

	public void addUser(User u) throws DuplicateException {
		if (!usrs.add(u))
			throw new DuplicateException("Duplicated Usr");
	}

	public void removeUser(User u) {
		usrs.remove(u);
	}

	public void fetch() throws DuplicateException, Exception {
		for (User usr : usrs) {
			for(Integer prvId : usr.getPrvs_id()){
				usr.addPrv(this.getOnePriv(prvId.intValue()));
			}
		}
	}
	
	private Privilege getOnePriv(int prvId) throws Exception{
		for(Privilege priv: prvs){
			if(priv.getPrv_id() == prvId)
				return priv;
		}
		throw new Exception("I didn't find the privilege entity.");
	}
}

 最后就是一个装配类,这个才是整个项目的重头:安装rule,从而建立映射关系。从而达到xml->javabean的映射。一个user对应多个privilege,类似于hibernate的映射:应该有一个容器,装载了所有的这个user实例所对应的privilege对象,当然,我采用的方法类似hibernate也是先装载一个id主,然后调用Document.fetch()进行填充,把id转化为具体的实例。

package com.cxz.xmldb;

import java.io.IOException;

import org.apache.commons.digester.CallMethodRule;
import org.apache.commons.digester.CallParamRule;
import org.apache.commons.digester.Digester;
import org.apache.commons.digester.ObjectCreateRule;
import org.apache.commons.digester.Rule;
import org.apache.commons.digester.SetNextRule;
import org.apache.commons.digester.SetPropertiesRule;
import org.xml.sax.SAXException;

public class SimpleDigester {

	/**
	 * @param args
	 * @throws Exception 
	 * @throws DuplicateException 
	 */
	public static void main(String[] args) throws DuplicateException, Exception {
		Digester digester = new Digester();

		Rule docCreate = new ObjectCreateRule("com.cxz.xmldb.Document");
		digester.addRule("doc", docCreate);

		Rule prvCreate = new ObjectCreateRule("com.cxz.xmldb.Privilege");
		digester.addRule("doc/prvs/prv", prvCreate);

		Rule usrCreate = new ObjectCreateRule("com.cxz.xmldb.User");
		digester.addRule("doc/usrs/usr", usrCreate);

		Rule propertiesSet = new SetPropertiesRule();
		digester.addRule("doc/prvs/prv", propertiesSet);
		digester.addRule("doc/usrs/usr", propertiesSet);

		digester.addRule("doc/prvs/prv", new SetNextRule("addPrivilege"));
		digester.addRule("doc/usrs/usr", new SetNextRule("addUser"));

		// digester.addRule("doc/prvs/prv", new CallMethodRule("setDescr", 1,
		// new Class[] { String.class }));
		// digester.addRule("doc/prvs/prv/descr", paramRule);
		//		
		// digester.addRule("doc/prvs/prv", new CallMethodRule("setName", 1,
		// new Class[] { String.class }));
		// digester.addRule("doc/prvs/prv/name", paramRule);

		digester.addRule("doc/prvs/prv/name", new CallMethodRule("setName", 0,
				new Class[] { String.class }));

		digester.addRule("doc/prvs/prv/descr", new CallMethodRule("setDescr",
				0, new Class[] { String.class }));

		digester.addRule("doc/usrs/usr/name", new CallMethodRule("setName", 0,
				new Class[] { String.class }));

		digester.addRule("doc/usrs/usr/pwd", new CallMethodRule("setPwd", 0,
				new Class[] { String.class }));

		digester.addRule("doc/usrs/usr/prvs/prv_id", new CallMethodRule(
				"addPrvId", 0, new Class[] { Integer.class }));

		Document doc = (Document) digester.parse(SimpleDigester.class
				.getClassLoader().getResource("doc.xml"));
		
		doc.fetch();

	}

}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值