Digester

本文介绍了一种使用Apache Commons Digester解析XML文件的方法。通过三种不同的配置方式,演示了如何将XML数据映射到Java对象中,包括属性方式、子标签方式及callMethod-callParam方式。

看AjaxChat的时候看到Digester。自己也写了个程序测试一下。
student.xml:

<?xml version="1.0" encoding="UTF-8"?>
<teacher name="张三丰" course="java">
	<student name="王八" age="20" id="1" />
	<student name="张飞" age="22" id="2" />
	<student name="李世民" age="21" id="3" />
	<student name="李陵" age="22" id="4" />
	<student name="高工" age="23" id="5" />
	<student name="黄夺" age="24" id="6" />
	<student name="马球" age="25" id="7" />
	<student name="琚要" age="26" id="8" />
</teacher>

 

teacher.xml:

<?xml version="1.0" encoding="UTF-8"?>
<teachers>
<teacher name="张三丰" course="java">
	<student>
		<name>王八</name>
		<age>20</age>
		<id>1</id>
	</student>
	<student>
		<name>张飞</name>
		<age>22</age>
		<id>1</id>
	</student>
	<student>
		<name>李世民</name>
		<age>21</age>
		<id>3</id>
	</student>
	<student>
		<name>李陵</name>
		<age>22</age>
		<id>4</id>
	</student>
	<student>
		<name>高工</name>
		<age>23</age>
		<id>5</id>
	</student>
	<student>
		<name>黄夺</name>
		<age>24</age>
		<id>6</id>
	</student>
	<student>
		<name>马球</name>
		<age>25</age>
		<id>7</id>
	</student>
	<student>
		<name>琚要</name>
		<age>26</age>
		<id>8</id>
	</student>
</teacher>
<teacher name="李小龙" course="net">
	<student>
		<name>王八2</name>
		<age>20</age>
		<id>1</id>
	</student>
	<student>
		<name>张飞2</name>
		<age>22</age>
		<id>1</id>
	</student>
	<student>
		<name>李世民2</name>
		<age>21</age>
		<id>3</id>
	</student>
	<student>
		<name>李陵2</name>
		<age>22</age>
		<id>4</id>
	</student>
	<student>
		<name>高工2</name>
		<age>23</age>
		<id>5</id>
	</student>
	<student>
		<name>黄夺2</name>
		<age>24</age>
		<id>6</id>
	</student>
	<student>
		<name>马球2</name>
		<age>25</age>
		<id>7</id>
	</student>
	<student>
		<name>琚要2</name>
		<age>26</age>
		<id>8</id>
	</student>
</teacher>
</teachers>

 

package gjs.domain;

public class Student {
	private int id;
	private String name;
	private int age;
        //......
}

package gjs.domain;

import java.util.ArrayList;
import java.util.List;

public class Teacher {
	private String name;
	private String course;
	private List<Student> students=new ArrayList<Student>();

	public void addStudent(String name,String age, String id){
		Student s=new Student();
		s.setAge(Integer.valueOf(age));		
		s.setId(Integer.valueOf(id));
		s.setName(name);
		this.students.add(s);
	}

	public void addStudent(Student student){
		this.students.add(student);
	}	
        //......
}

package gjs.domain;

import java.util.ArrayList;
import java.util.List;

public class TeacherList {
	private List<Teacher> teachers=new ArrayList<Teacher>();
	public void addTeachers(Teacher teacher){
		this.teachers.add(teacher);
	}
	public List<Teacher> getTeachers() {
		return teachers;
	}

	public void setTeachers(List<Teacher> teachers) {
		this.teachers = teachers;
	}
}

package gjs.test;

import java.io.File;
import java.io.IOException;
import gjs.domain.Student;
import gjs.domain.Teacher;
import gjs.domain.TeacherList;
import org.apache.commons.digester.Digester;
import org.junit.Test;
import org.xml.sax.SAXException;
import static org.junit.Assert.*;
public class DigesterTest {
	
	/**
	 * 属性方式
	 */
	@Test public void testOne(){
		Digester digester=new Digester();
		//设置不进行合法性验证
		digester.setValidating(false);
		//当遇到<teacher>时创建一个Teacher对象,放入栈顶
		digester.addObjectCreate("teacher", Teacher.class);
		digester.addSetProperties("teacher");
		//当遇到<teacher>的子元素<student>时创建一个Student对象,放入栈顶
		digester.addObjectCreate("teacher/student", Student.class);
		//设置<student>的属性值,根据属性值调用相应的set方法
		digester.addSetProperties("teacher/student");
		//当再次遇到<student>时创建一个Student对象,放入栈顶,同时调用栈次顶的addStudent方法
		digester.addSetNext("teacher/student", "addStudent", "gjs.domain.Student");
		try {
			Teacher teacher = (Teacher)digester.parse(new File("src/student.xml"));
			assertEquals(8, teacher.getStudents().size());
		} catch (IOException e) {
			e.printStackTrace();
		} catch (SAXException e) {
			e.printStackTrace();
		}		
	}

	/**
	 * 子标签方式(设置Property方式一)
	 */
	@Test public void testTwo(){
		Digester digester=new Digester();
		digester.setValidating(false);
		//设置栈顶
		digester.push(new TeacherList());
		digester.addObjectCreate("teachers/teacher", Teacher.class);
		digester.addSetProperties("teachers/teacher");
		digester.addObjectCreate("teachers/teacher/student", Student.class);
		//子标签方式设置属性方法之一,第三个参数是第二个参数所指方法的参数个数
		digester.addCallMethod("teachers/teacher/student/name", "setName",1);
		digester.addCallMethod("teachers/teacher/student/age", "setAge",1);
		digester.addCallMethod("teachers/teacher/student/id", "setId",1);
		digester.addSetNext("teachers/teacher/student", "addStudent", "gjs.domain.Student");
		digester.addSetNext("teachers/teacher", "addTeachers", "gjs.domain.Teacher");
		try {
			TeacherList teacher = (TeacherList)digester.parse(new File("src/teacher.xml"));
			assertEquals(2, teacher.getTeachers().size());
			assertEquals("java", teacher.getTeachers().get(0).getCourse());
			assertEquals(8, teacher.getTeachers().get(0).getStudents().size());
		} catch (IOException e) {
			e.printStackTrace();
		} catch (SAXException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 子标签方式(设置Property方式二)
	 */
	@Test public void testThree(){
		Digester digester=new Digester();
		digester.setValidating(false);
		//设置栈顶
		digester.push(new TeacherList());
		digester.addObjectCreate("teachers/teacher", Teacher.class);
		digester.addSetProperties("teachers/teacher");
		digester.addObjectCreate("teachers/teacher/student", Student.class);
		//子标签方式设置属性方法之二
		digester.addBeanPropertySetter("teachers/teacher/student/name");
		digester.addBeanPropertySetter("teachers/teacher/student/age");
		digester.addBeanPropertySetter("teachers/teacher/student/id");
		digester.addSetNext("teachers/teacher/student", "addStudent", "gjs.domain.Student");
		digester.addSetNext("teachers/teacher", "addTeachers", "gjs.domain.Teacher");
		try {
			
			TeacherList teacher = (TeacherList)digester.parse(new File("src/teacher.xml"));
			assertEquals(2, teacher.getTeachers().size());
			assertEquals("java", teacher.getTeachers().get(0).getCourse());
			assertEquals(8, teacher.getTeachers().get(0).getStudents().size());
		} catch (IOException e) {
			e.printStackTrace();
		} catch (SAXException e) {
			e.printStackTrace();
		}
	}
	/**
	 * 子标签方式 (callMethod callParam方式)
	 */
	@Test public void testFour(){
		Digester digester=new Digester();
		digester.setValidating(false);
		digester.push(new TeacherList());
		digester.addObjectCreate("teachers/teacher", "gjs.domain.Teacher");
		digester.addSetProperties("teachers/teacher");
		//当<student>时调用栈顶元素(Teacher)的addStudents却并不执行,等待addCallParam设置参数,3为参数个数,这里传入的参数是字符串。
		digester.addCallMethod("teachers/teacher/student", "addStudent" ,3);
		digester.addCallParam("teachers/teacher/student/name", 0);
		digester.addCallParam("teachers/teacher/student/age", 1);
		//这句之后即</student>才调用addStudents方法,并且如果再次遇到<student>重复。
		digester.addCallParam("teachers/teacher/student/id", 2);		
		digester.addSetNext("teachers/teacher", "addTeachers", "gjs.domain.Teacher");
		try {
			TeacherList teacher=(TeacherList)digester.parse(new File("src/teacher.xml"));
			assertEquals(2, teacher.getTeachers().size());
			assertEquals("java", teacher.getTeachers().get(0).getCourse());
			assertEquals(8, teacher.getTeachers().get(0).getStudents().size());
			assertEquals("李世民2", teacher.getTeachers().get(1).getStudents().get(2).getName());
		} catch (IOException e) {
			e.printStackTrace();
		} catch (SAXException e) {
			e.printStackTrace();
		}
	}
}

 

基于数据驱动的 Koopman 算子的递归神经网络模型线性化,用于纳米定位系统的预测控制研究(Matlab代码实现)内容概要:本文围绕“基于数据驱动的Koopman算子的递归神经网络模型线性化”展开,旨在研究纳米定位系统的预测控制问题,并提供完整的Matlab代码实现。文章结合数据驱动方法与Koopman算子理论,利用递归神经网络(RNN)对非线性系统进行建模与线性化处理,从而提升纳米级定位系统的精度与动态响应性能。该方法通过提取系统隐含动态特征,构建近似线性模型,便于后续模型预测控制(MPC)的设计与优化,适用于高精度自动化控制场景。文中还展示了相关实验验证与仿真结果,证明了该方法的有效性和先进性。; 适合人群:具备一定控制理论基础和Matlab编程能力,从事精密控制、智能制造、自动化或相关领域研究的研究生、科研人员及工程技术人员。; 使用场景及目标:①应用于纳米级精密定位系统(如原子力显微镜、半导体制造设备)中的高性能控制设计;②为非线性系统建模与线性化提供一种结合深度学习与现代控制理论的新思路;③帮助读者掌握Koopman算子、RNN建模与模型预测控制的综合应用。; 阅读建议:建议读者结合提供的Matlab代码逐段理解算法实现流程,重点关注数据预处理、RNN结构设计、Koopman观测矩阵构建及MPC控制器集成等关键环节,并可通过更换实际系统数据进行迁移验证,深化对方法泛化能力的理解。
<think>我们正在讨论Apache Commons Digester库,特别是关于规则(rules)的配置和使用方法。根据引用内容,Digester库通过规则将XML元素与Java对象的操作关联起来。以下将详细说明Digester规则的核心概念、配置方法及使用步骤。 ### 一、Digester规则的核心概念 1. **模式(Pattern)** 模式是XML元素的路径表达式,用于匹配XML文档中的特定元素。例如,`catalog/book`匹配`<catalog>`下的`<book>`元素。 2. **规则(Rule)** 规则定义了当Digester遇到匹配的模式时执行的操作。每个规则都是`org.apache.commons.digester.Rule`的子类。常用规则包括: - `ObjectCreateRule`:创建Java对象 - `SetPropertiesRule`:设置对象属性(将XML属性映射到Java对象属性) - `BeanPropertySetterRule`:设置Bean属性(通过子元素文本内容) - `SetNextRule`:将当前对象添加到父对象中 - `CallMethodRule`:调用对象的方法 ### 二、规则配置方法 Digester规则可通过编程方式或XML配置文件(`digester-rules.xml`)定义。以下分别介绍两种方式: #### 方式1:编程方式配置规则 ```java Digester digester = new Digester(); digester.addObjectCreate("catalog", Catalog.class); // 匹配根元素创建Catalog对象 digester.addObjectCreate("catalog/book", Book.class); // 匹配book元素创建Book对象 digester.addSetProperties("catalog/book"); // 将book元素的属性映射到Book对象 digester.addBeanPropertySetter("catalog/book/title", "title"); // 将<title>文本设置为Book的title属性 digester.addSetNext("catalog/book", "addBook"); // 将Book对象添加到Catalog的addBook方法 // 解析XML Catalog catalog = (Catalog) digester.parse(new File("catalog.xml")); ``` #### 方式2:XML规则文件配置(`digester-rules.xml`) ```xml <digester-rules> <pattern value="catalog"> <object-create-rule classname="com.example.Catalog"/> <pattern value="book"> <object-create-rule classname="com.example.Book"/> <set-properties-rule/> <bean-property-setter-rule pattern="title" propertyname="title"/> <set-next-rule methodname="addBook"/> </pattern> </pattern> </digester-rules> ``` 加载规则文件: ```java Digester digester = DigesterLoader.createDigester( this.getClass().getResource("/digester-rules.xml") ); Catalog catalog = digester.parse(new File("catalog.xml")); ``` ### 三、使用步骤 1. **添加依赖** 确保包含以下库(引用[4]): ```xml <dependency> <groupId>commons-digester</groupId> <artifactId>commons-digester</artifactId> <version>2.1</version> </dependency> <!-- 同时需要commons-logging和commons-beanutils --> ``` 2. **定义Java对象** 创建与XML结构对应的Java类,例如`Catalog`和`Book`,并提供必要的属性和方法。 3. **配置规则** 选择编程方式或XML文件方式定义规则。 4. **解析XML** 调用`digester.parse()`方法解析XML,生成Java对象树。 ### 四、常见问题解决方案 #### 问题1:规则未触发 - **检查模式路径**:确保模式表达式与XML结构完全匹配(区分大小写)。 - **确认规则顺序**:规则应按XML文档的解析顺序添加(从根元素到子元素)。 #### 问题2:属性绑定失败 - **属性名匹配**:XML属性名必须与Java对象的setter方法名对应(不区分大小写,但需遵循驼峰命名转换)。例如,XML属性`pub-date`对应Java方法`setPubDate()`。 #### 问题3:嵌套对象处理 - 使用`SetNextRule`将子对象添加到父对象中: ```java digester.addSetNext("catalog/book", "addBook"); ``` 要求`Catalog`类有`addBook(Book book)`方法。 ### 五、高级技巧 1. **自定义规则** 继承`Rule`类实现特定逻辑: ```java public class UppercaseRule extends Rule { @Override public void body(String namespace, String name, String text) { String upper = text.toUpperCase(); getDigester().push(upper); // 将结果压入栈供后续规则使用 } } ``` 注册规则: ```java digester.addRule("catalog/book/title", new UppercaseRule()); ``` 2. **使用变量** Digester支持栈变量: ```java digester.push(new HashMap<String, Object>()); // 压入Map digester.addCallMethod("catalog/book", "putInMap", 2); // 调用Map的put方法 digester.addCallParam("catalog/book/title", 0); // 第一个参数为title文本 digester.addCallParam("catalog/book/author", 1); // 第二个参数为author文本 ``` --- §§ 相关问题 §§ 1. Digester规则与SAX解析器有何关系? 2. 如何处理XML命名空间(namespace)? 3. Digester能否解析大型XML文件(避免内存溢出)? 4. 如何通过注解配置Digester规则? [^1]: Apache Commons Digester官方文档 - Rule类说明 [^2]: Digester设计模式解析 [^3]: XML配置驱动的对象构建机制 [^4]: Maven仓库 - Digester依赖项</think>### Apache Commons Digester 规则配置与使用指南 Digester 是一个基于 SAX 的 XML 解析库,通过预定义规则将 XML 元素映射到 Java 对象操作。以下是核心配置方法和使用流程: --- ### 一、Digester 规则核心概念 #### 1. **模式(Pattern)** XML 元素的路径表达式,决定规则触发位置,例如: - `/root`:根元素 - `/root/user`:`<root>`下的`<user>`元素 - `*/item`:任意层级的`<item>`元素 [^3] #### 2. **规则(Rule)** 定义匹配模式时执行的操作,常用规则类型: | 规则类 | 作用 | 示例 | |--------|------|------| | `ObjectCreateRule` | 创建对象 | `new ObjectCreateRule("user", User.class)` | | `SetPropertiesRule` | 设置对象属性 | `new SetPropertiesRule()` | | `BeanPropertySetterRule` | 通过子元素设置属性 | `new BeanPropertySetterRule("name")` | | `SetNextRule` | 将对象添加到父对象 | `new SetNextRule("addUser")` | | `CallMethodRule` | 调用方法 | `new CallMethodRule("setRole", 1)` | --- ### 二、规则配置方法 #### 方式 1:编程式配置(推荐) ```java Digester digester = new Digester(); digester.addObjectCreate("users/user", User.class); // 创建User对象 digester.addSetProperties("users/user"); // 设置属性(如<user id="1">) digester.addBeanPropertySetter("users/user/name", "name"); // 设置name属性 digester.addSetNext("users/user", "addUser"); // 调用Users.addUser() ``` #### 方式 2:XML 规则文件(`digester-rules.xml`) ```xml <digester-rules> <pattern value="users/user"> <object-create-rule classname="com.example.User"/> <set-properties-rule/> <bean-property-setter-rule pattern="name" propertyname="name"/> <set-next-rule methodname="addUser"/> </pattern> </digester-rules> ``` 加载规则文件: ```java Digester digester = DigesterLoader.createDigester( getClass().getResource("/digester-rules.xml") ); ``` --- ### 三、完整使用流程 #### 步骤 1:添加依赖(Maven) ```xml <dependency> <groupId>commons-digester</groupId> <artifactId>commons-digester</artifactId> <version>2.1</version> </dependency> <!-- 需配合 commons-beanutils 和 commons-logging --> ``` #### 步骤 2:定义 Java 对象 ```java public class User { private String id; private String name; // getters/setters } public class Users { private List<User> userList = new ArrayList<>(); public void addUser(User user) { userList.add(user); } } ``` #### 步骤 3:解析 XML ```java Users users = new Users(); Digester digester = new Digester(); digester.push(users); // 设置根对象 // 添加规则 digester.addObjectCreate("users/user", User.class); digester.addSetProperties("users/user"); digester.addBeanPropertySetter("users/user/name", "name"); digester.addSetNext("users/user", "addUser"); // 解析XML文件 digester.parse(new File("data.xml")); ``` #### 示例 XML(data.xml) ```xml <users> <user id="101"> <name>Alice</name> </user> <user id="102"> <name>Bob</name> </user> </users> ``` --- ### 四、高级技巧 #### 1. 动态规则绑定 ```java digester.addRule("users/user", new Rule() { @Override public void begin(String namespace, String name, Attributes attributes) { User user = (User) digester.peek(); // 获取当前对象 user.setJoinDate(LocalDate.now()); // 动态操作 } }); ``` #### 2. 方法参数传递 ```java // 调用 user.setRole("admin"),参数来自role子元素 digester.addCallMethod("users/user/role", "setRole", 1); digester.addCallParam("users/user/role", 0); // 参数位置 ``` #### 3. 命名空间处理 ```xml <pattern value="ns:user" namespace="http://example.com"> <object-create-rule classname="com.example.User"/> </pattern> ``` --- ### 五、常见问题解决 #### 问题 1:规则未触发 **原因**:模式路径不匹配或 SAX 解析错误 **解决**: - 检查 XML 结构和模式路径 - 启用日志:`digester.setLogger(new SimpleLog());` #### 问题 2:属性绑定失败 **原因**:JavaBean 缺少 setter 方法或属性名不匹配 **解决**: - 确认属性名与 XML 元素/属性名一致 - 使用 `BeanPropertySetterRule` 显式指定属性名 #### 问题 3:内存泄漏 **原因**:未正确释放资源 **解决**: ```java finally { digester.clear(); // 清理内部状态 } ``` ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值