Castor功能与应用参考(二)- XML映射

索引
1.         示例需求
2.         Castor XML映射概念
2.1   概述
3.         映射文件定义详解
3.2.1          <class>节点的属性
3.2.2          <class>节点的子节点
3.4.1          < field >节点的属性
3.4.2          < field >节点的子节点
3.5.1          < bind-xml >节点的属性
3.5.2          < bind-xml >中使用嵌套类映射
3.5.3          Location属性简介
4.         映射文件使用举例
1.      示例需求
在运行下文中讲述的示例时,用户需要预先做一些准备工作。用户可以从 castor网站上获取最新1.1.2.1版本包括castor-1.1.2.1.zip和castor-1.1.2.1-examples.zip解压到本地目录,在Eclipse中构建一个Java项目。然后将解压目录中的castor-1.1.2.1.jar,lib目录下的commons-logging-1.1.jar,log4j-1.2.13.jar和xerces-J_1.4.0.jar添加到项目的类路径中。
2.      Castor XML映射概念
Castor XML 通过Mapping定义的方式简化了Java类和XML文档之间的绑定。尽管可以使用Castor默认的自省方式编组和解编Java对象,但是对于复杂的映射绑定,Mapping定义提供了更加细致的控制。同时,Mapping文件可以在一定程度上解耦合Java对象模型与XML文档,从而避免各自的变化给对方带来的影响。
2.1概述
Mpping文件本身也以XML文档格式定义。Mapping文档以Java对象模型为视角,用于描述Java对象如何映射为XML文档节点,Java对象中的字段属性如何映射为XML文档节点中的子节点或属性。
如上图所示,在Castor中,一个Java类映射为一个XML节点,Java类中的属性字段映射为XML节点下的子节点或者属性。描述上述映射的Mapping文件如下所示:
<?xml version="1.0"?>
<!DOCTYPE mapping PUBLIC "-//EXOLAB/Castor Mapping DTD Version 1.0//EN"
                                "http://castor.org/mapping.dtd">
< mapping >
       < description > Description of the mapping </ description >
       < map-to xml =" Person "/>
       < class name =" Person ">
              < field name =" name " type =" string ">
                     < bind-xml name =" name " node =" element "/>
              </ field >
              < field name =" birthday " type =" date ">
                     < bind-xml name =" birthday " node =" element "/>
              </ field >
       </ class >
</ mapping >
2.2编组过程
在Castor中,一个Java类必须映射为一个XML节点。当Castor编组一个Java对象的过程如下:首先,如果存在映射信息,从映射信息中确定该对象所对应的XML节点名称;如果不存在映射信息,则使用对象的类名作为XML节点名。然后,使用映射文件中字段 < field >的映射信息确定Java对象中的一个字段属性如何转换为XML文档中的如下几种存在:
  • 一个属性
  • 一个节点
  • 一个节点的文本
  • 忽略(在映射文件中可以设定不编组某一字段属性,Castor将忽略该字段)
Castor遍历整个Java对象,如果发现一个Class类型的属性,则查找Mapping文件中的 < class >节点定义。
如果在Mapping文件中找不到一个类的对应信息,默认情况下,Castor会分析这个类的元数据,采用一组默认的规则来定义要编组的字段属性所映射的XML文档元素。默认规则如下:
  • 所有原始数据类型,包括原始数据类型的对象封装类型(如Boolean,Short等)都编组为XML节点属性;
  • 所有其他对象类型都编组为文本或者节点;
2.3解编过程
在解编过程中,当Castor查找到一个XML文档节点时,Castor首先查找映射信息来决定如何解编XML文档为Java对象。如果不存在映射信息,Castor会使用XML节点的名称决定如何构建类(Class)实例,例如,如果节点的名称为”test-element”,在Mapping文件不存在时,Castor将构建一个名称为”TestElement”的类。然后,Castor根据映射文件中关于字段属性的映射信息处理该XML文档节点下的内容。
3.      映射文件定义详解
3.1Mapping文件的根节点
如上例XML Mapping 文件所示,Mapping 文件的根节点为 <mapping><mapping>节点的Xml Schema定义为:
< xsd:element name =" mapping ">
              < xsd:complexType >
                     < xsd:sequence >
                            < xsd:element name =" description " type =" xsd:string " minOccurs =" 0 "/>
                            < xsd:element ref =" include " minOccurs =" 0 " maxOccurs =" unbounded "/>
                            < xsd:element ref =" class " minOccurs =" 0 " maxOccurs =" unbounded "/>
                            < xsd:element ref =" key-generator " minOccurs =" 0 " maxOccurs =" unbounded "/>
                     </ xsd:sequence >
              </ xsd:complexType >
</ xsd:element >
 
< mapping > 节点下的节点包括:
  • 一个 < description > 节点,可选的,用于添加描述信息
  • 一个或多个 < include > 节点,用于引用其他的映射文件
  • 一个或多个 < class > 节点,用于描述每一个定义 Mapping Java
  • 一个或多个 < key-generator > 节点,该节点在 Castor JDO 中使用,后续文档将详细解释
Mapping 文件举例如下:
        <?xml version="1.0"?>
        <!DOCTYPE mapping PUBLIC "-//EXOLAB/Castor Mapping DTD Version 1.0//EN"
                                 "http://castor.org/mapping.dtd">
        <mapping>
                <description>Description of the mapping</description>
                <include href="other_mapping_file.xml"/>
                <class name="A">
                        .........
                </class>
                <class name="B">
                        .........
                </class>
        </mapping>
3.2<class>节点定义
< class > 节点的 Schema 定义如下:
< xsd:element name =" class ">
          < xsd:complexType >
                 < xsd:sequence >
                        < xsd:element name =" description " type =" xsd:string " minOccurs =" 0 "/>
                        < xsd:element ref =" cache-type " minOccurs =" 0 "/>
                        < xsd:element ref =" map-to " minOccurs =" 0 "/>
                        < xsd:element ref =" named-query " minOccurs =" 0 " maxOccurs =" unbounded "/>
                        < xsd:choice >
                               < xsd:element ref =" field " minOccurs =" 0 " maxOccurs =" unbounded "/>
                               < xsd:element ref =" container " minOccurs =" 0 " maxOccurs =" unbounded "/>
                        </ xsd:choice >
                 </ xsd:sequence >
                 < xsd:attribute name =" name " type =" xsd:ID " use =" required "/>
                 < xsd:attribute name =" extends " type =" xsd:IDREF " use =" optional "/>
                 < xsd:attribute name =" depends " type =" xsd:IDREF " use =" optional "/>
                 < xsd:attribute name =" identity " type =" xsd:NMTOKENS " use =" optional "/>
                 < xsd:attribute name =" access " use =" optional " default =" shared ">
                        < xsd:simpleType >
                               < xsd:restriction base =" xsd:string ">
                                      < xsd:enumeration value =" read-only "/>
                                      < xsd:enumeration value =" shared "/>
                                      < xsd:enumeration value =" exclusive "/>
                                      < xsd:enumeration value =" db-locked "/>
                               </ xsd:restriction >
                        </ xsd:simpleType >
                 </ xsd:attribute >
                 < xsd:attribute name =" key-generator " type =" xsd:string " use =" optional "/>
                 < xsd:attribute name =" auto-complete " type =" xsd:boolean " use =" optional " default =" false "/>
                 < xsd:attribute name =" verify-constructable " type =" xsd:boolean " use =" optional " default =" true "/>
          </ xsd:complexType >
   </ xsd:element >
< class > 节点包含了 Java 类与 XML 文档之间映射的所有信息。其中,详细描述了 Java 类中各个字段属性与 XML 文档元素的映射。
3.2.1       <class>节点的属性
Ø name: 映射的Java 类名称,使用类的全名,如”com.acme.MyClass” 。
Ø extends: 只有在该类扩展其他类时,使用该参数指定扩展的类。如果被扩展的类未在该Mapping 文件中指定,则不能使用该属性。
Ø depends: 在Castor JDO 中指明类之间的依赖关系,用于表示数据库表中关联表的概念。
Ø auto-complete:   如果该属性值为”true” ,则Castor 在处理该类时首先采用自省的方式决定该类的字段属性,然后使用Mapping 文件中对该字段属性的设定覆盖自省方式的操作。auto-complete 属性可以让Castor 的默认自省处理方式与Mapping 定义方式很好的结合,从而降低对包含很多字段的类进行复杂的设定操作。
Ø identity: 在Castor JDO 中使用,用于描述该类实例的主键字段,详细信息参考Castor JDO 部分。
Ø access: 在Castor JDO 中使用,详细信息参考Castor JDO 部分。
Ø key-generator: 在Castor JDO 中使用,详细信息参考Castor JDO 部分。
3.2.2       <class>节点的子节点
Ø description 可选的属性,用于对该类添加描述性信息
Ø cache-type: 只在Castor JDO 中使用,详细信息参考Castor JDO 部分。
Ø map-to: 可选属性,如果XML 中节点名称与类(Class) 名称不同,则使用该节点设定。默认的,Castor 会自动分析XML 节点名称和类名称之间的映射,如对于Java 类”XxxYyy” ,Castor 会自动映射为XML 节点”xxx-yyy” 。如果用户不希望Castor 自动生成该名称,则可以使用<map-to> 节点来指定XML 映射名称。注意:<map-to> 仅用于XML文档中的根节点。
Ø field 节点下包含 零个或多个<field>节点。每个<field>节点用于描述Java类中的一个字段属性。<class>
<class> 映射举例
下面的例子将Java 类MyClass 映射为XML 文档中的节点’<data>’:
package mypackage
public class MyClass {
       public int foo;
       public String getBar() { ... }
       public void setBar(String bar) { ... }
}
如果用户希望输出的XML文档格式如下:
  <data foo-like="12">
     <something>...</something>
 </data>
则用户需要以如下方式设定Mapping映射文件:
  <mapping>
     ...
     <class name="mypackage.MyClass">
        <map-to xml="data"/>
        <field name="foo" direct="true" ...>
           <bind-xml name="foo-like" node="attribute"/>
        </field>
        </field name="bar" ....>
           <bind-xml name="something" node="element"/>
        </field>
     </class>
     ...
 </mapping>
3.3<map-to>节点定义
<map-to> 节点的Schema 定义如下:
< xsd:element name =" map-to ">
              < xsd:complexType >
                     < xsd:attribute name =" table " type =" xsd:NMTOKEN " use =" optional "/>
                     < xsd:attribute name =" xml " type =" xsd:string " use =" optional "/>
                     < xsd:attribute name =" ns-uri " type =" xsd:string " use =" optional "/>
                     < xsd:attribute name =" ns-prefix " type =" xsd:NMTOKEN " use =" optional "/>
                     < xsd:attribute name =" element-definition " type =" xsd:boolean " use =" optional " default =" false "/>
                     < xsd:attribute name =" ldap-dn " type =" xsd:string " use =" optional "/>
                     < xsd:attribute name =" ldap-oc " type =" xsd:string " use =" optional "/>
              </ xsd:complexType >
       </ xsd:element >
<map-to> 节点用于指定给定Java 类与XML 文档节点的映射。<map-to> 节点只用于XML 文档根节点,如果该节点未在Mapping 文件中设定,则Castor 采用如下处理策略:
Ø 在编组过程中,通过Java 类名称命名XML 文档根节点名,如Java 类”XxxYyy” 映射为XML 节点”xxx-yyy”
Ø 在解编过程中,通过XML 文档根节点名称确定Java 类名称,如XML 节点”test-element” 映射为Java 类”TestElement”
用户可以在castor.properties 中指定Castor 在Java 类名称与XML 文档节点名之间的转换策略。 <map-to> 节点的属性包括:
Ø xml :类映射的XML节点名称Java
Ø ns-uri: XML 节点的名称空间URI
Ø ns-prefix: XML 节点的名称空间前缀
Ø element-definition: True if the descriptor as created from a schema definition that was of type element (as opposed to a <complexType> definition). This only is useful in the context of source code generation
Ø ldap-dn: 在Castor XML 中不使用该属性
Ø ldap-oc: 在Castor XML 中不使用该属性
3.4< field>节点定义
< field> 节点的 Schema 定义如下:
< xsd:element name =" field ">
              < xsd:complexType >
                     < xsd:sequence >
                            < xsd:element name =" description " type =" xsd:string " minOccurs =" 0 "/>
                            < xsd:element ref =" sql " minOccurs =" 0 "/>
                            < xsd:element ref =" bind-xml " minOccurs =" 0 "/>
                            < xsd:element ref =" ldap " minOccurs =" 0 "/>
                     </ xsd:sequence >
                     < xsd:attribute name =" name " type =" xsd:string " use =" required "/>
                     < xsd:attribute name =" type " type =" xsd:string " use =" optional "/>
                     < xsd:attribute name =" required " type =" xsd:boolean " use =" optional " default =" false "/>
                     < xsd:attribute name =" transient " type =" xsd:boolean " use =" optional " default =" false "/>
                     < xsd:attribute name =" direct " type =" xsd:boolean " use =" optional " default =" false "/>
                     < xsd:attribute name =" lazy " type =" xsd:boolean " use =" optional " default =" false "/>
                     < xsd:attribute name =" container " type =" xsd:boolean " use =" optional "/>
                     < xsd:attribute name =" get-method " type =" xsd:string " use =" optional "/>
                     < xsd:attribute name =" has-method " type =" xsd:string " use =" optional "/>
                     < xsd:attribute name =" set-method " type =" xsd:string " use =" optional "/>
                     < xsd:attribute name =" create-method " type =" xsd:string " use =" optional "/>
                     < xsd:attribute name =" handler " type =" xsd:string " use =" optional "/>
                     < xsd:attribute name =" collection " use =" optional ">
                            < xsd:simpleType >
                                   < xsd:restriction base =" xsd:string ">
                                          < xsd:enumeration value =" array "/>
                                          < xsd:enumeration value =" vector "/>
                                          < xsd:enumeration value =" arraylist "/>
                                          < xsd:enumeration value =" hashtable "/>
                                          < xsd:enumeration value =" collection "/>
                                          < xsd:enumeration value =" set "/>
                                          < xsd:enumeration value =" map "/>
                                          < xsd:enumeration value =" enumerate "/>
                                          < xsd:enumeration value =" sortedset "/>
                                          < xsd:enumeration value =" iterator "/>
                                   </ xsd:restriction >
                            </ xsd:simpleType >
                     </ xsd:attribute >
                     < xsd:attribute name =" comparator " type =" xsd:string " use =" optional "/>
                     < xsd:attribute name =" identity " type =" xsd:boolean " use =" optional " default =" false "/>
              </ xsd:complexType >
       </ xsd:element >
<field> 节点用于描述如何编组/ 解编Java 对象中的字段属性。Castor 可以从<field> 节点描述中的”name” 属性确定Java 字段的名称;可以从<field> 节点描述中的”type” 和”collection” 属性确定Java 字段的类型;可以从<field> 节点描述中的”direct” ,”get-method” 和”set-method” 属性确定Java 字段的访问方法。通过上述信息,Castor 能够操作Java 类中的字段属性。
Castor 通过以下两个规则来判定某一字段的类型签名:
  • 检查 <field>节点中的“类型”属性(”type””collection”
如果 <field> 节点中没有 ”collection” 属性, ”type” 属性指定的类型即为该字段的 Java 类型。 ”type” 属性值既可以是 Java 对象类型的全限定名 ( 包含包名称 ) ,也可以是 Castor 定义的一系列简称。 Castor 支持的类型简称列表如下:
简称
原始类型
Java类型
other
N
java.lang.Object
string
N
java.lang.String
integer
Y
java.lang.Integer
long
Y
java.lang.Long
boolean
Y
java.lang.Boolean
double
Y
java.lang.Double
float
Y
java.lang.Float
big-decimal
N
java.math.BigDecimal
byte
Y
java.lang.byte.Type
date
N
java.util.Date
short
Y
java.lang.short.Type
char
Y
java.lang.Character.Type
bytes
N
bytes[]
chars
N
char[]
strings
N
string[]
loacle
N
java.util.Locale
Castor 会自动将XML 文档中的节点内容自动转换为上述Java 对象类型。如果设定了”collection”属性,collection属性值遵从下面的对象对象列表:
简称
原始类型
Java 类型
array
<java 类型>[]
<java 类型>[]
arraylist
java.util.List
java.util.Arraylist
vector
java.util.Vector
java.util.Vector
hashtable
java.util.Hashtable
java.util.Hashtable
collection
java.util.Collection
java.util.Arraylist
set
java.util.Set
java.util.Hashset
map
java.util.Map
java.util.Hashmap
sortedset
java.util.SortedSet
java.util.TreeSet
Collection集合中的对象为Java类型。对于Hashtable和Map类型的对象,Castor同时存储其键和值。对于其映射,可以使用org.exolab.castor.mapping.MapItem类通过顶层(相对于嵌套类映射)类映射定义和嵌套类映射定义来描述。
  • 检查<field> 节点中的“签名”属性(”direct”,”set-method” 和”get-method”
如果 ”direct” 属性设定为true,则在Java类定义中,该字段必须具有如下的声明:
public <type> <name>;
如果 ”direct” 属性 设定为 false 或者该属性被忽略, Castor 会通过该属性的存取方法访问该属性。首先,若设定了 'get-method' 'set-method' Castor 会访问如下方法签名:
public <type> <get-method>();
         
public void <set-method>(<type> value);
若没有设定'get-method' 'set-method'属性,Castor会尝试访问如下签名方法:
public <type> get<capitalized-name>();
public void set<capitalized-name>(<type> value);
<capitalized-name>是指Castor检查<name>属性值,将其首字母转换为大写,其他字符保持不变。
  • collection 字段属性处理的例外情况
在默认情况下,’get-method’属性返回集合字段实例,’set-method’属性设定集合字段实例。特例情况如下表所示:
'get-method'
If a 'get-method' is provided for a collection field, Castor - in adition to the default behaviour described above - will deviate from the standard case for the following special prefixes:
public Iterator iterate...();
A 'get-method' starting with the prefix 'iterate' is treated as Iterator method for the given collection field.
public Enumeration enum...();
A 'get-method' starting with 'enum' is treated as Enumeration method for the given collection field.
'set-method'
If 'set-method' is provided for a collection field, Castor - in addition to the default behaviour described above - will accept an 'add' prefix and expect the following signature:
public void add...(<type> value);
This method is called for each collection element while unmarshalling.
 
3.4.1       <field>节点的属性
<field>节点可以包含将Java字段映射为XML元素,数据库表列名称等信息。<field>节点可配置的属性如下:
Ø  name: 该属性是必须的,即使在该映射类中没有该字段属性。如果配置了”direct”属性,”name”属性值必须是映射对象中的一个public字段(该字段必须是public,非static和非transient的类型)。如果没有”direct”和”get-/set-method”属性设定,“name”属性值对应的字段通过该值确定其访问方法(采用Java Bean规范)。
Ø  type: 该字段属性的Java类型。Castor使用该信息将XML信息转换为Java对象信息(如将字符串转换为整型),定义该字段访问方法的签名。如果设定了”collection”属性,该属性信息用于指定集合中对象的类型信息。
Ø  required: 在编组和解编过程中,该字段是否可选,默认值为false。
Ø  transient: 如果设定为”true”,该字段在处理过程中将被忽略。
Ø  direct: 如果为true,该字段在Java类定义中必须是public类型。
Ø  collection: 如果该字段存在多个,则Castor使用该属性的设定来处理他们。该类型用于定义对应Java类中集合的类型。
Ø  get-method: 可选配置,”name”属性对应Java类字段的访问方法,具体使用参考前文描述。
Ø  set-method: 可选配置,”name”属性对应Java类字段的访问方法,具体使用参考前文描述。
Ø  create-method: 工厂方法,用于构建FieldHandler实例。
3.4.2       <field>节点的子节点
在XML Mapping中,<field>节点的子节点仅包含一个<xml>节点,用于描述如何将该字段属性映射到XML文档元素。
Castor自0.9.5版本以后,支持将一个 < field>节点映射为该字段所属Java类构造函数的参数,这种机制通过”set-method”属性来实现。如果需要设定一个字段作为该类对象初始化时构造函数的一个参数,可以设定该字段在Mapping文件中 < field>节点的”set-method”属性为”1%”-“9%”。 ”1%”表示构造函数的第一个参数,依次类推。这种机制举例如下:
假定存在如下所示的Java类Foo,Foo类除了具有一个默认的构造函数外,还有一个具有参数的构造函数。
public class Foo {
    private int size = 20;
    public Foo() { }
    public Foo(int size) {
        this.size = size;
    }
    public int getSize() {
        return size;
    }
    public void setSize(int size) {
        this.size = size;
    }
}
如果用户希望在实例化Foo类时,调用Foo类具有参数的构造函数而不是默认无参构造函数,则通过设定如下的映射文件实现。
<?xml version="1.0"?>
<mapping>
 <class name="Foo">
     <field name="size" get-method="getSize" set-method="%1" type="int">
        <bind-xml node="attribute"/>
     </field>
 </class>
</mapping>
Mapping文件中的setMethod=”1%”的设定,会告诉Castor在实例化Foo类时,使用size属性字段作为构造Foo(int)的参数。
注意:如果设定了 ”set-method” 属性,则”get-method” 属性也必须设定
3.5<bind-xml>节点定义
<bind-xml> 节点的用于描述Java 字段如何在XML 文档中映射展现。在编组和解编过程中均要使用。
<bind-xml> 节点的Schema 定义如下:
< xsd:element name =" bind-xml ">
              < xsd:complexType >
                     < xsd:sequence >
                            < xsd:element ref =" class " minOccurs =" 0 "/>
                            < xsd:element name =" property " type =" propertyType " minOccurs =" 0 " maxOccurs =" unbounded "/>
                     </ xsd:sequence >
                     < xsd:attribute name =" name " type =" xsd:QName " use =" optional ">
                     </ xsd:attribute >
                     < xsd:attribute name =" type " type =" xsd:NMTOKEN " use =" optional "/>
                     < xsd:attribute name =" auto-naming " use =" optional ">
                            < xsd:simpleType >
                                   < xsd:restriction base =" xsd:string ">
                                          < xsd:enumeration value =" deriveByClass "/>
                                          < xsd:enumeration value =" deriveByField "/>
                                   </ xsd:restriction >
                            </ xsd:simpleType >
                     </ xsd:attribute >
                     < xsd:attribute name =" location " type =" xsd:string " use =" optional ">
                     </ xsd:attribute >
                     < xsd:attribute name =" matches " type =" xsd:string " use =" optional "/>
                     < xsd:attribute name =" reference " type =" xsd:boolean " use =" optional "/>
                     < xsd:attribute name =" node " use =" optional ">
                            < xsd:simpleType >
                                   < xsd:restriction base =" xsd:string ">
                                          < xsd:enumeration value =" attribute "/>
                                          < xsd:enumeration value =" element "/>
                                          < xsd:enumeration value =" namespace "/>
                                          < xsd:enumeration value =" text "/>
                                   </ xsd:restriction >
                            </ xsd:simpleType >
                     </ xsd:attribute >
                     < xsd:attribute name =" QName-prefix " type =" xsd:NMTOKEN " use =" optional "/>
                     < xsd:attribute name =" transient " type =" xsd:boolean " use =" optional "/>
              </ xsd:complexType >
       </ xsd:element >
3.5.1       <bind-xml>节点的属性
Ø  name: XML节点或属性的名称。注意:该属性值必须是QName,可以使用名称空间前缀来表明该节点或属性所属的特定名称空间,该前缀在编组过程中并不保留或使用,只是用来保持文档的格式良好。
Ø  auto-naming: 如果未设定name属性,auto-naming属性用于提示是否Castor自动为该字段构建相应的名称。通常情况下,使用<field>节点中的name属性值作为XML元素的名称。
Ø  type: 该节点在XML文档中的 Schema类型,Castor编组框架使用该属性确定对XML节点的处理方式。如”QName”。
Ø  location: 允许用户设定XML文档中 “间接路经”上的节点作为该Java字段属性的映射(如该字段所属类的XML节点映射为“AAA”,该节点的名称为“TTT”,但不是“AAA节点的子节点”,而是“AAA”节点的子节点“BBB”节点的子节点,则可以使用location属性映射为XML文档中的“AAA/BBB/TTT”。详细信息参看下述 Loaction 属性简介”
Ø  QName-prefix: 如果该字段对应XML文档节点中的一个QName值,则可以使用该属性设定其前缀。详细信息参考“Castor源代码自动生成章节”。
Ø  reference: 在解编该字段时,指明该字段是否看作一个对象引用。
Ø  matches: 允许覆盖节点名称的匹配规则。该属性值是一个标准的正则表达式,用于替代”name”属性。如果值为”*”,则可以匹配任何XML节点名称,但是仅当不存在其他字段与XML节点名称匹配时,使用该匹配。
Ø  node: 表明该字段映射成为XML文档中的属性,节点还是文本元素。默认情况下,原始类型的字段映射成XML属性,其他的映射成为XML节点。
Ø  transient: 如果其值设定为true,则视该节点为临时的,不做处理。默认继承<field>节点中transient属性值。
3.5.2       <bind-xml>中使用嵌套的类映射
Castor 自0.9.5.3 版本开始,<bind-xml> 节点支持嵌套的类映射定义。该功能在某个类映射信息需要在多个地方指定时非常方便,如映射Hashtable/HashMap/Map 等集合类时的情况。具体使用参考下面的例子:
嵌套类举例
<bind-xml ...>
   <class name="org.exolab.castor.mapping.MapItem">
      <field name="key" type="java.lang.String">
        <bind-xml name="id"/>
      </field>
      <field name="value" type="com.acme.Foo"/>
   </class>
</bind-xml>
3.5.3       location属性简介
<bind-xml> 节点中的location 属性允许用户将字段映射为XML 文档中的内嵌节点或者在映射节点封装一个节点。封装节点只出现在XML 文档结构中,与Mapping 文件定义的Java 对象没有直接映射关系。下面仍以Foo 类为例,
  public class Foo {
     private Bar bar = null;
     public Foo();
 
     public getBar() {
        return bar;
     }
     public void setBar(Bar bar) {
        this.bar = bar;
     }
 }
我们希望将该类映射成为下面所示的XML 文档(注:’abc’ 节点并不存在于Foo 或者Bar 类的定义中)
<?xml version="1.0"?>
<foo>;
   <abc>
      <bar>...</bar>
   </abc>
</foo>
为实现上述映射,我们以如下方式定义Mapping 文件
<?xml version="1.0"?>
   ...
   <class name="Foo">
      <field name="bar" type="Bar">
         <bind-xml name="bar" location="abc"/>
      </field>
  </class>
   ...
</mapping>
需要注意的是,“location ”属性的值指定的是封装的节点的名称,如果希望封装多层节点,则节点名称之间使用”/” 分隔,如下例所示:
<bind-xml name="bar" location="abc/xyz" />
此外,用户还需要注意的是,<bind-xml> 节点中的属性”name” 指定的xml 元素名称并不是“location ”属性中指定的封装节点的一部分。同时,封装节点的父节点总是其所封装字段所在类对象映射的节点。“location ”属性同样可以封装XML 属性元素,如下所示的映射定义:
<bind-xml name="bar" location="abc" node="attribute" />
生成的XML 文档为:
<?xml version="1.0"?>
<foo>
   <abc bar="..."/>;
</foo>
 
4.      映射文件使用举例
下面我们以一个完整的例子,说明如何使用Castor 的Mapping 映射文件实现Java 类与XML 文档之间的相互转换。
首先,我们定义一个名为”order.xml” 的数据文件,我们用这个XML 文件描述一个订单,该订单中包含这个订单的客户信息,以及客户在此订单中所订购的货物。一个订单中可以存在多个货物。
order.xml
<?xml version="1.0"?>
< Order reference =" 12343-AHSHE-314159 ">
  < Client >
   < Name > Jean Smith </ Name >
   < Address > 2000, Alameda de las Pulgas, San Mateo, CA 94403 </ Address >
  </ Client >
 
  < Item reference =" RF-0001 ">
   < Description > Stuffed Penguin </ Description >
   < Quantity > 10 </ Quantity >
   < UnitPrice > 8.95 </ UnitPrice >
  </ Item >
 
  < Item reference =" RF-0034 ">
   < Description > Chocolate </ Description >
   < Quantity > 5 </ Quantity >
   < UnitPrice > 28.50 </ UnitPrice >
  </ Item >
 
  < Item reference =" RF-3341 ">
    < Description > Cookie </ Description >
    < Quantity > 30 </ Quantity >
    < UnitPrice > 0.85 </ UnitPrice >
 </Item>
我们要为该订单定义三个Java类,分别描述该订单,订单的客户和货物。
Ø  MyOrder 代表该订单
Ø  ClientData 代表订单的客户
Ø  Item 代表订单中的一项货物
这三个Java类的代码如下所示:
MyOrder.java
import java.util.Vector;
import java.util.Enumeration;
 
public class MyOrder {
    private String _ref ;
    private ClientData _client;
    private Vector _items ;
    private float _total ;
 
    public void setReference(String ref) {
       _ref = ref;
    }
 
    public String getReference() {
       return _ref ;
    }
 
    public void setClientData(ClientData client) {
       _client = client;
    }
 
    public ClientData getClientData() {
       return _client;
    }
 
    public void setItemsList(Vector items) {
       _items = items;
    }
 
    public Vector getItemsList() {
       return _items ;
    }
 
    public void setTotal( float total) {
       _total = total;
    }
 
    public float getTotal() {
       return _total ;
    }
 
    // Do some processing on the data
    public float getTotalPrice() {
       float total = 0.0f;
       for (Enumeration e = _items .elements(); e.hasMoreElements();) {
           Item item = (Item) e.nextElement();
           total += item._quantity * item._unitPrice;
       }
       return total;
    }
}
 
ClientData.java
public class ClientData {
    private String _name ;
    private String _address ;
 
    public void setName(String name) {
       _name = name;
    }
 
    public String getName() {
       return _name ;
    }
 
    public void setAddress(String address) {
       _address = address;
    }
 
    public String getAddress() {
       return _address ;
    }
}
 
Item.java
public class Item {
    public String _reference ;
    public int _quantity ;
    public float _unitPrice ;
    public String _description ;
}
现在,我们有了预期的XML文档定义,也有了描述文档的Java类定义。下一步,我们定义XML文档与Java类之间的映射。在下面的mapping.xml文件中,我们定义了三个类MyOrder、ClientData和Item的映射。
mapping.xml
<?xml version="1.0"?>
<!DOCTYPE mapping PUBLIC "-//EXOLAB/Castor Mapping DTD Version 1.0//EN"
                        "http://castor.org/mapping.dtd">
< mapping >
       < class name =" MyOrder ">
              < map-to xml =" Order "/>
              < field name =" Reference " type =" java.lang.String ">
                     < bind-xml name =" reference " node =" attribute "/>
              </ field >
              < field name =" Total " type =" float ">
                     < bind-xml name =" total-price " node =" attribute "/>
              </ field >
              < field name =" ClientData " type =" ClientData ">
                     < bind-xml name =" Client "/>
              </ field >
              < field name =" ItemsList " type =" Item " collection =" vector ">
                     < bind-xml name =" Item "/>
              </ field >
       </ class >
       < class name =" ClientData ">
              < field name =" Name " type =" java.lang.String ">
                     < bind-xml name =" Name " node =" element "/>
              </ field >
              < field name =" Address " type =" java.lang.String ">
                     < bind-xml name =" Address " node =" element "/>
              </ field >
       </ class >
       < class name =" Item ">
              < field name =" _reference " type =" java.lang.String " direct =" true ">
                     < bind-xml name =" reference " node =" attribute "/>
              </ field >
              < field name =" _quantity " type =" integer " direct =" true ">
                     < bind-xml name =" Quantity " node =" element "/>
              </ field >
              < field name =" _unitPrice " type =" float " direct =" true ">
                     < bind-xml name =" UnitPrice " node =" element "/>
              </ field >
              < field name =" _description " type =" string " direct =" true ">
                     < bind-xml name =" Description " node =" element "/>
              </ field >
       </ class >
</ mapping >
         具备上述资源后,我们通过下面的Java代码测试Castor通过Mapping映射文件来实现XML文档与Java对象间的相互转换。
main.java
import org.exolab.castor.mapping.Mapping;
import org.exolab.castor.xml.Unmarshaller;
import org.exolab.castor.xml.Marshaller;
import java.io.FileReader;
import java.io.OutputStreamWriter;
import org.xml.sax.InputSource;
 
public class Main {
    public static void main(String args[]) {
       Mapping mapping = new Mapping();
       try {
           // 1. Mapping.xml 文件中加载映射信息
           mapping.loadMapping( "mapping.xml" );
 
           // 2. 解编 order.xml 文档,构造 java 对象
           Unmarshaller unmar = new Unmarshaller(mapping);
           MyOrder order = (MyOrder) unmar.unmarshal( new InputSource(
                  new FileReader( "order.xml" )));
 
           // 3. 调用 Java MyOrder 的对象实例方法,修改该对象实例
           float total = order.getTotalPrice();
           System. out .println( "Order total price = " + total);
           order.setTotal(total);
 
           // 4. 将修改后的对象实例重新编组为 XML 文档并输出到控制台
           Marshaller marshaller = new Marshaller( new OutputStreamWriter(
                  System. out ));
           marshaller.setMapping(mapping);
           marshaller.marshal(order);
 
       } catch (Exception e) {
           System. out .println(e);
           return ;
       }
    }
}
用户可以比较原来的order.xml文档与输出到控制台的XML文档数据的差别,从而体会Castor XML编组框架的功能。 
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值