Posted on: 2013-11-26, Last modified: 2013-11-26, View: 3753
xml的解析技术包括了很多,其中dom4j,jdom,SAX等技术估计已经在大部分的人心中成为了耳熟能详的东西,但是如果
是关于xml与对象直接的转换技术,那么下面几种技术是不错的选择。
A.commons-digester
Digester本来仅仅是Jakarta Struts中的一个工具,用于处理struts-config.xml配置文件。显然,将XML文件转换成相应的Java对象是一项很通用的功能,这个工具理应具有更广泛的用途,所以很快它就在Jakarta Commons项目(用于提供可重用的Java组件库)中有了一席之地。
如今Digester随着Struts的发展以及其的公用性而被提到commons中独自立项,是apache的一个组件 apache commons-digester.jar,通过它可以很方便的从xml文件生成java对象.你不用再象以前通过jdom或者Xerces去读取一个document对象.(jdom和Xerces仍然有它们的用武之地及强大之处,在其它应用里你也少不了它们)
Digester简单原理
Digester由"事件"驱动,通过调用预定义的规则操作对象栈,将XML文件转换为Java对象。工作原理如下:
Digester底层采用SAX解析XML文件,所以很自然的,对象转换由"事件"驱动,即在识别出特定XML元素时(实际被细分为begin、body、end、finish四个时点),将执行特定的动作,比如创建特定的Java对象,或调用特定对象的方法等。此处的XML元素根据匹配模式(matching pattern)识别,而相关操作由规则(rule)定义。在转换过程中,Digester维持了一个对象栈,可以看作对象转换的工作台,用来存放转换中生成的、或是为转换临时创建的Java对象。对输入XML文件作了一趟完整的扫描后,对象栈的栈顶元素即为目标对象。由于Digester屏蔽了SAX解析的细节,使用者仅需关注转换操作本身,大大简化了转换操作。
理论知识介绍完成,列举一个实例。
common-digester所依赖的jar包:
common-Digester
common-BeanUtils
common-Collections
common-Logging
1.首先编写xml文件,文件内容如下:
<?xml version="1.0"?> <academy name="JAcademy"> <student name="JavaBoy" division="A"> <course> <id>C1</id> <name>JSP</name> </course> <course> <id>C2</id> <name>Servlets</name> </course> </student> <student name="JavaGirl" division="B"> <course> <id>C3</id> <name>EJB</name> </course> </student> <teacher name="JavaGuru"> <certification>SCJP</certification> <certification>SCWCD</certification> </teacher> <teacher name="JavaMaster"> <certification>OCP</certification> <certification>SCJP</certification> <certification>SCEA</certification> </teacher> </academy>
2.根据xml文件,编写Digester解析的规则文件。
<?xml version="1.0"?> <digester-rules> <pattern value="academy"> <object-create-rule classname="com.huawei.example.Academy" /> <set-properties-rule /> <pattern value="student"> <object-create-rule classname="com.huawei.example.Student" /> <set-properties-rule /> <pattern value="course"> <object-create-rule classname="com.huawei.example.Course" /> <bean-property-setter-rule pattern="id" /> <bean-property-setter-rule pattern="name" /> <set-next-rule methodname="addCourse" /> </pattern> <set-next-rule methodname="addStudent" /> </pattern> <pattern value="teacher"> <object-create-rule classname="com.huawei.example.Teacher" /> <set-properties-rule /> <call-method-rule pattern="certification" methodname="addCertification" paramcount="1" /> <call-param-rule pattern="certification" paramnumber="0" /> <set-next-rule methodname="addTeacher" /> </pattern> </pattern> </digester-rules>
规则文件相关说明:
1.ObjectCreateRule 当begin()方法被调用时, 此rule创建相应Java对象, 并将其push到Digester的对象栈上。当end()方法被调用时, 栈顶对象将被pop, Digester内所有对该对象的引用都将失效。
2.FactoryCreateRule 创建Java对象的另一种选择。当待创建的Java对象没有无参构造函数,或需要在创建时需要进行额外的设置时,需要用此rule。
B:属性设置
3.SetPropertiesRule 当begin()方法被调用时, Digester使用标准的Java反射API,将栈顶对象的属性设置为XML元素的同名属性值。
4.SetPropertyRule 当begin()方法被调用时, Digester调用栈顶对象某指定属性的设置方法,设置其值。
C:父子关系管理
5.SetNextRule 当end()方法被调用时, Digester将栈顶元素设置进次栈顶元素中(调用相应的设置方法)。
6.SetTopRule 当end()方法被调用时, Digester将次栈顶元素设置进栈顶元素中(调用相应的设置方法)。
D:任意方法调用
7.CallMethodRule 当end()方法被调用时, Digester将调用栈顶元素指定名称的方法。除了方法名外,此rule还需要配置参数数目,参数类型。参数值一般通过CallParamRule得到。
8.CallParamRule 此rule内嵌于CallParamRule中,按顺序(相对于0)定义了CallParamRule中参数值的来源,可选的来源包括当前XML元素的属性或内容。
E:其它
9.NodeCreateRule 将XML文件树的一部分转换为DOM节点,并push到Digester的对象栈上。
3.编写主体的测试类
public static void main(String[] args) throws IOException, SAXException, IllegalAccessException, InvocationTargetException, NoSuchMethodException { Digester digester = DigesterLoader.createDigester(TestDigester.class .getClassLoader().getResource("academyRules.xml")); Academy academy = (Academy) digester.parse(TestDigester.class .getClassLoader().getResourceAsStream("academy.xml")); Vector<Student> vStud = academy.getStudents(); Vector<Teacher> vTeach = academy.getTeachers(); for (int i = 0; i < vStud.size(); i++) { Student student =vStud.get(i); System.out.println("name : "+student.getName()); System.out.println("cources name :"+student.getCourses().get(0).getName()); } for (int i = 0; i < vTeach.size(); i++) { Teacher teacher =vTeach.get(i); System.out.println("Certifications : "+teacher.getCertifications()); } }
运行其结果如下:
cources name :JSP name : JavaGirl cources name :EJB Certifications : [SCJP, SCWCD] Certifications : [OCP, SCJP, SCEA]
这里只是对common-disgester进行了简单的介绍,如果想详细了解可以查看http://commons.apache.org/digester/
B. JAXB
关于jaxb这种技术,相信大家应该非常熟悉,学习过webservice的朋友应该有所了解。
jaxb是一项数据绑定技术,它将xml文件映射成一个个的java类,程序员通过操作这些类就可以对xml文件中的元素进行读取等操作,同样程序员也可以改变这些类的属性,最后映射到xml文件中,这样做可以把程序员的主要精力放在业务逻辑上,并且也更符合面向对象的思想,而无需像使用DOM4J等技术一样需要处理一个个的xml节点。
编写一个简单的实例
1.xml还是采用前面的,我们首先通过命令将xml文件生成xsd文件。
java -jar trang.jar academy.xml academy.xsd
2.下载jaxb相关的jar包,下载的详细地址如下:
3.如果命令将xsd文件生成对应的java实体类
xjc -p com.huawei.wuhen.academy academy.xsd -d src
命令这样所需的java类就生成了,以下为命令的详细说明:
xjc [–p java文件所在的包] [-xmlschema] [–d 保存java文件的目录]
-xmlschema xsd文件路径。
-d 指定了保存java文件的目录
-p 指定了生成的java文件所在的包
4.编写测试的相关类
private JAXBContext jaxb; // 这里要生成java实体类所对应的package名称 private final String PACKAGE_NAME = "com.huawei.wuhen.academy"; public Test() throws JAXBException { jaxb = JAXBContext.newInstance(PACKAGE_NAME); } // 将xml转换成对象 public Academy umarshall(String inputtFileName) throws JAXBException, FileNotFoundException { if (null == inputtFileName || inputtFileName.isEmpty()) { return null; } Unmarshaller unmarshaller = jaxb.createUnmarshaller(); return (Academy) unmarshaller.unmarshal(new FileInputStream( inputtFileName)); } // 将对象转换成xml public void marshall(Academy academy, String outputFileName) throws JAXBException, FileNotFoundException { Marshaller marshaller = jaxb.createMarshaller(); marshaller.marshal(academy, new FileOutputStream(outputFileName)); } public static void main(String[] args) throws JAXBException, FileNotFoundException { Test test = new Test(); Academy academy = test.umarshall("D:\\academy.xml"); System.out.println("name : " + academy.getStudent().get(0).getName()); test.marshall(academy, "F:\\academy.xml"); }
C.castor
castor可以用一个mapping.xml文件来描述转换后的Java对象的xml基本形态,类似于xStream的annotation,这点还是非常不错的。下面我们就来看看Castor是怎么样完成Java对象到XML之间的相互转换吧。
1.通过ant命令生成相关的java类,ant脚本如下:
<project name="castor" default="castor" basedir="."> <target name="init"> <property name="src.dir" value="src/" /> <property name="lib.dir" value="${basedir}/lib/" /> <property name="caster.file" value="academy.xsd" /> <property name="caster.package" value="com.huawei.wuhen.academy1" /> <property name="castor.dest" value="${src.dir}" /> <delete dir="${castor.dest}" /> </target> <target name="castor" depends="init"> <java classname="org.exolab.castor.builder.SourceGeneratorMain"> <arg value="-i" /> <arg value="${caster.file}" /> <arg value="-dest" /> <arg value="${castor.dest}" /> <arg value="-package" /> <arg value="${caster.package}" /> <arg value="-f" /> <arg value="true" /> <arg value="verbose" /> <arg value="true" /> <classpath> <fileset dir="${lib.dir}"> <include name="**/*.jar" /> </fileset> </classpath> </java> </target> </project>
相关jar下载地址如下:
http://www.castor.org/download.html
2.编写相关的测试类
// 将java对象转化成xml对象 public void marshall(Academy academy, String outputFileName) throws IOException, MarshalException, ValidationException { Writer writer = new FileWriter(new File(outputFileName)); Marshaller.marshal(academy, writer); } //将xml对象转化成java实体对象 public Academy unmarshall(Class<Academy> academy, String inputFileName) throws MarshalException, ValidationException, FileNotFoundException { if (null == inputFileName || inputFileName.isEmpty()) { return null; } Academy academy2 = (Academy) Unmarshaller.unmarshal(academy, new FileReader(new File(inputFileName))); return academy2; }
三种java与xml相互转换的技术,每种技术都具有自己的优点和缺点,我们可以根据项目的情况,合适的
选择相关技术,从而完成xml与java对象的转换。