扫一扫
分享文章到微信
扫一扫
关注官方公众号
至顶头条
作者:builder.com.cn 2007年2月5日
关键字:
列表D
public class LibraryRuleSet {
public static LibraryDetailsConfiguration getLibraryDetailsConfig (String libraryConfigFilePath) {
LibraryDetailsConfiguration libraryDetails = null;
try {
Digester digester = new Digester();
digester.setValidating(false);
// create an object of the given class,
//push it to top of Digester object stack
digester.addObjectCreate("library",LibraryDetailsConfiguration.class);
digester.addObjectCreate("library/movie", MovieDetailsConfiguration.class);
// call the setter method of the given bean property on the object
digester.addBeanPropertySetter("library/movie/title","title");
digester.addBeanPropertySetter("library/movie/rating","rating");
// pop the object on top of the stack
digester.addSetNext("library/movie","setMovie");
// begin parsing
File fileObj = new File(libraryConfigFilePath);
libraryDetails = (LibraryDetailsConfiguration) digester.parse(fileObj);
} catch(Exception e) {
System.out.println("Exception in parsing data file: " + e);
e.printStackTrace();
}
return libraryDetails;
}
}
这个类实际执行的工作包括:解析XML数据,并把这些数据映射到前面定义的Java对象中。首先,addObjectCreate()方法建立两个Configuration类实例;接下来,addBeanPropertySetter()方法告诉Digester调用哪个设置方法(setter method)将<title>和<rating>元素的字符数据附加到对象实例上;最后,parse()方法对文件进行解析和执行确定的行动。最终得到的结果是LibraryDetailsConfiguration类的一个适当配置的实例。现在,只需要写一个小存根,它将调用那个实例的printLibraryDetails()方法。(列表E)
列表E
public class TestDigester
{
public static void main(String args[]) {
LibraryDetailsConfiguration libraryDetails = LibraryRuleSet.getLibraryDetails("");
libraryDetails.printLibraryDetails();
}
}
Here's the output:
Minority Report -> 5Mission: Impossible III -> 3The Matrix -> 5
修改规则集
在Digester(任何基于SAX的API也一样)中,改变输出要求必须改变XML-Java对象映射,因此所使用的规则集也随之改变。为说明这一点,我们先建立一个稍微不同的XML文件,如列表F所示。
列表F
<?xml version='1.0'?>
<library>
<movie>
<title>The Matrix</title>
<cast>
<person>Keanu Reeves</person>
<person>Laurence Fishburne</person>
<person>Carrie-Anne Moss</person>
</cast>
<rating>5</rating>
</movie>
<movie>
<title>Mission: Impossible III</title>
<cast>
<person>Tom Cruise</person>
<person>Ving Rhames</person>
<person>Laurence Fishburne</person>
</cast>
<rating>3</rating>
</movie>
<movie>
<title>Minority Report</title>
<cast>
<person>Tom Cruise</person>
<person>Max von Sydow</person>
</cast>
<rating>5</rating>
</movie>
</library>
我们还假设你希望以不同的方法处理这些XML数据,这次以演员姓名为关键元素,并列举这名演员的所有电影。为达到这一目的,需要对MovieDetailsConfiguration类进行修改,现在我们需要一个数组来保存每部电影的演职员信息。(列表G)
列表G
public class MovieDetailsConfiguration{
private String title;
private ArrayList movieCastList;
private int rating;
public MovieDetailsConfiguration() {
movieCastList = new ArrayList();
}
public void setTitle(String title) {
this.title = title;
}
public String getTitle() {
return title;
}
public void setMovieCastList(ArrayList movieCastList) {
this.movieCastList = movieCastList;
}
public ArrayList getMovieCastList() {
return movieCastList;
}
public void addMovieCast(String castName) {
movieCastList.add(castName);
}
public void setRating(int rating) {
this.rating = rating;
}
public int getRating() {
return rating;
}
}
还有必要修改LibraryDetailsConfiguration类的setMovie()和printLibraryDetails()方法,如列表H所示。
列表H
public class LibraryDetailsConfiguration{
private HashMap movieDetailsMap;
// movieDetailsMap would store the title as key and
// MovieDetailsConfiguration object as value
public LibraryDetailsConfiguration() {
movieDetailsMap = new HashMap();
}
public void setMovieDetailsMap(HashMap movieDetailsMap) {
this.movieDetailsMap = movieDetailsMap;
}
public HashMap getMovieDetailsMap() {
return movieDetailsMap;
}
public void setMovie(MovieDetailsConfiguration movieDetails) {
ArrayList movieDetailList = null;
ArrayList movieCastList = movieDetails.getMovieCastList();
Iterator itMovieCast = movieCastList.iterator();
while (itMovieCast.hasNext()) {
String movieCastName = (String)itMovieCast.next();
if(movieDetailsMap.containsKey(movieCastName)) {
movieDetailList = (ArrayList)
movieDetailsMap.get(movieCastName);
} else {
movieDetailList = new ArrayList();
}
movieDetailList.add(movieDetails);
movieDetailsMap.put(movieCastName, movieDetailList);
}
}
public void printLibraryDetails() {
Collection movieCastColl = this.movieDetailsMap.keySet();
if (movieCastColl != null) {
Iterator itMovieCast = movieCastColl.iterator();
while(itMovieCast.hasNext()) {
String movieCastName =(String)itMovieCast.next();
System.out.println("ACTOR: " + movieCastName);
ArrayList movieDetailsList = (ArrayList)movieDetailsMap.get(movieCastName);
Iterator itMovieDetailsList = movieDetailsList.iterator();
while (itMovieDetailsList.hasNext()) {
MovieDetailsConfiguration movieDetails = (MovieDetailsConfiguration)itMovieDetailsList.next();
System.out.println("\t\tMOVIE TITLE: " + movieDetails.getTitle());
}
}
} else {
System.out.println("Movie details do not exist");
}
}
}
最后,还需要修改规则集,找到并定位演职员成员,把他们附加到演职员数组上。(列表I)
列表I
public class LibraryRuleSet {
public static LibraryDetailsConfiguration getLibraryDetailsConfig (String libraryConfigFilePath) {
LibraryDetailsConfiguration libraryDetails = null;
try {
Digester digester = new Digester();
digester.setValidating(false);
// create an object of the given class, push it to top of Digester object stack
digester.addObjectCreate("library",LibraryDetailsConfiguration.class);
digester.addObjectCreate("library/movie", MovieDetailsConfiguration.class);
// call the setter method of the given bean property on the object
digester.addBeanPropertySetter("library/movie/title","title");
digester.addBeanPropertySetter("library/movie/rating","rating");
// call the given method on the object, specify parameters
digester.addCallMethod("library/movie/cast/person", "addMovieCast",1);
digester.addCallParam("library/movie/cast/person",0);
// pop the object on top of the stack
digester.addSetNext("library/movie","setMovie");
// begin parsing
File fileObj = new File(libraryConfigFilePath);
libraryDetails = (LibraryDetailsConfiguration) digester.parse(fileObj);
} catch(Exception e) {
System.out.println("Exception in parsing movie data: " + e);
e.printStackTrace();
}
return libraryDetails;
}
}
以下是修改后的printLibraryDetails()方法输出结果:
ACTOR: Carrie-Anne Moss
MOVIE TITLE: The Matrix
ACTOR: Keanu Reeves
MOVIE TITLE: The Matrix
ACTOR: Laurence Fishburne
MOVIE TITLE: The Matrix
MOVIE TITLE: Mission: Impossible III
ACTOR: Ving Rhames
MOVIE TITLE: Mission: Impossible III
ACTOR: Tom Cruise
MOVIE TITLE: Mission: Impossible III
MOVIE TITLE: Minority Report
ACTOR: Max von Sydow
MOVIE TITLE: Minority Report
将规则集保存为XML
在前面的例子中,你看到用Java编写的Digester规则集。但是,Digester最大的优点在于,这并不是将XML元素映射到行动的唯一定义模式。而且,你还可以用XML指定规则集,这使得非Java开发人员也有可能利用Digester的强大功能。
为说明这个问题,我们首先删除在前面例子中定义的LibraryRuleSet类,再用以XML编写的规则集来代替它,如列表J所示。
列表J
<?xml version='1.0'?>
<digester-rules>
<pattern value="library">
<object-create-rule classname="sample.config.LibraryDetailsConfiguration"/>
</pattern>
<pattern value="library/movie">
<object-create-rule classname="sample.config.MovieDetailsConfiguration"/>
<bean-property-setter-rule pattern="title"/>
<call-method-rule pattern="cast/person" methodname="addMovieCast" paramcount="1" />
<call-param-rule pattern="cast/person" paramnumber="0"/>
<set-next-rule methodname="setMovie" />
</pattern>
</digester-rules>
把这个文件保存为movieRules.xml。
接下来,对存根进行修改,使它知道阅读这些XML规则集。(列表K)
列表K
public class TestDigester {
public static void main(String args[]) {
TestDigester digesterClient = new TestDigester();
digesterClient.digest();
}
public void digest() {
try {
//Create Digester using rules defined in movieRules.xml
Digester digester = DigesterLoader.createDigester(this.getClass().getClassLoader().getResource("movieRules.xml"));
//Parse movie.xml using the Digester to get an instance of Academy
LibraryDetailsConfiguration libraryConfig = (LibraryDetailsConfiguration) digester.parse(this.getClass().getClassLoader().getResourceAsStream("movie.xml"));
libraryConfig.printLibraryDetails();
} catch(Exception e) {
System.out.println("Exception while parsing the data file : " + e);
e.printStackTrace();
}
}
}
现在,试着运行上面的代码——输出结果应该与前面的例子相同。
如这些例子所说明的,Jakarta的Digester组件为解析一个XML文件提供一个基于规则的直观框架,对它进行编程比给标准的基于SAX的API编程要容易得多。使用基于XML的规则集进一步提高了可用性,允许非Java开发人员也能应用这个应用程序。自己试用一下吧——编码快乐!
责任编辑:德东
如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。
现场直击|2021世界人工智能大会
直击5G创新地带,就在2021MWC上海
5G已至 转型当时——服务提供商如何把握转型的绝佳时机
寻找自己的Flag
华为开发者大会2020(Cloud)- 科技行者