JAXB中怎么构建对父对象的链接

还是以在第一节介绍JAXB的schema为例:

Xml代码   收藏代码
  1. <?xml version="1.0" encoding="UTF-8"?>    
  2. <schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://www.liulutu.com/students/"    
  3.     targetNamespace="http://www.liulutu.com/students/">    
  4.     <element name="students">    
  5.         <complexType>    
  6.             <sequence>    
  7.                 <element name="student" type="tns:StudentType" maxOccurs="unbounded" />    
  8.             </sequence>    
  9.         </complexType>    
  10.     </element>    
  11.     <simpleType name="SexType">    
  12.         <restriction base="string">    
  13.             <enumeration value="Male"></enumeration>    
  14.             <enumeration value="Female"></enumeration>    
  15.         </restriction>    
  16.     </simpleType>    
  17.     
  18.     <complexType name="StudentType">    
  19.         <attribute name="sex" type="tns:SexType"></attribute>    
  20.         <attribute name="name" type="string"></attribute>    
  21.     </complexType>    
  22. </schema>    

 生成的类文件如下:

 

models

从Schema定义里可以看出,Students里包含有多个StudentType对象:

Java代码   收藏代码
  1. @XmlAccessorType(XmlAccessType.FIELD)  
  2. @XmlType(name = "", propOrder = {  
  3.     "student"  
  4. })  
  5. @XmlRootElement(name = "students")  
  6. public class Students {  
  7.   
  8.     @XmlElement(required = true)  
  9.     protected List<StudentType> student;  
  10.   
  11.     /** 
  12.      * Gets the value of the student property. 
  13.      *  
  14.      * <p> 
  15.      * This accessor method returns a reference to the live list, 
  16.      * not a snapshot. Therefore any modification you make to the 
  17.      * returned list will be present inside the JAXB object. 
  18.      * This is why there is not a <CODE>set</CODE> method for the student property. 
  19.      *  
  20.      * <p> 
  21.      * For example, to add a new item, do as follows: 
  22.      * <pre> 
  23.      *    getStudent().add(newItem); 
  24.      * </pre> 
  25.      *  
  26.      *  
  27.      * <p> 
  28.      * Objects of the following type(s) are allowed in the list 
  29.      * {@link StudentType } 
  30.      *  
  31.      *  
  32.      */  
  33.     public List<StudentType> getStudent() {  
  34.         if (student == null) {  
  35.             student = new ArrayList<StudentType>();  
  36.         }  
  37.         return this.student;  
  38.     }  
  39.   
  40. }  

 现在的问题是,从StudentType对象里,怎么能访问到它的父对象也就是上面的students对象呢?StudentType类如下:

Java代码   收藏代码
  1. @XmlAccessorType(XmlAccessType.FIELD)  
  2. @XmlType(name = "StudentType")  
  3. public class StudentType {  
  4.   
  5.     @XmlAttribute(name = "sex")  
  6.     protected SexType sex;  
  7.     @XmlAttribute(name = "name")  
  8.     protected String name;  
  9.     @XmlAttribute(name = "birthday")  
  10.     @XmlJavaTypeAdapter(Adapter1 .class)  
  11.     @XmlSchemaType(name = "date")  
  12.     protected Calendar birthday;  
  13.   
  14.     /** 
  15.      * Gets the value of the sex property. 
  16.      *  
  17.      * @return 
  18.      *     possible object is 
  19.      *     {@link SexType } 
  20.      *      
  21.      */  
  22.     public SexType getSex() {  
  23.         return sex;  
  24.     }  
  25.   
  26.     /** 
  27.      * Sets the value of the sex property. 
  28.      *  
  29.      * @param value 
  30.      *     allowed object is 
  31.      *     {@link SexType } 
  32.      *      
  33.      */  
  34.     public void setSex(SexType value) {  
  35.         this.sex = value;  
  36.     }  
  37.   
  38.     /** 
  39.      * Gets the value of the name property. 
  40.      *  
  41.      * @return 
  42.      *     possible object is 
  43.      *     {@link String } 
  44.      *      
  45.      */  
  46.     public String getName() {  
  47.         return name;  
  48.     }  
  49.   
  50.     /** 
  51.      * Sets the value of the name property. 
  52.      *  
  53.      * @param value 
  54.      *     allowed object is 
  55.      *     {@link String } 
  56.      *      
  57.      */  
  58.     public void setName(String value) {  
  59.         this.name = value;  
  60.     }  
  61.   
  62.     /** 
  63.      * Gets the value of the birthday property. 
  64.      *  
  65.      * @return 
  66.      *     possible object is 
  67.      *     {@link String } 
  68.      *      
  69.      */  
  70.     public Calendar getBirthday() {  
  71.         return birthday;  
  72.     }  
  73.   
  74.     /** 
  75.      * Sets the value of the birthday property. 
  76.      *  
  77.      * @param value 
  78.      *     allowed object is 
  79.      *     {@link String } 
  80.      *      
  81.      */  
  82.     public void setBirthday(Calendar value) {  
  83.         this.birthday = value;  
  84.     }  
  85.   
  86. }  

 从类定义可以看出,其中没有任何描述Students对象的信息。

解决方法:

首先,假设要解析的文件内容如下:

 

Xml代码   收藏代码
  1. <?xml version="1.0" encoding="UTF-8" standalone="yes"?>  
  2. <ns2:students xmlns:ns2="http://www.liulutu.com/students/">  
  3.     <student sex="Female" name="Bob" birthday="2003-11-27+08:00" />  
  4.     <student sex="Male" name="Lisa" birthday="2003-10-26+08:00" />  
  5. </ns2:students>  

 (如果手头没有文件,也可以用以上模型快速的生成一个,例如:)

Java代码   收藏代码
  1. StudentType studentType = new StudentType();  
  2. studentType.setBirthday(Calendar.getInstance());  
  3. studentType.setName("Bob");  
  4. studentType.setSex(SexType.FEMALE);  
  5.   
  6. Students students = new Students();  
  7. students.getStudent().add(studentType);  
  8.   
  9. JAXBContext context = JAXBContext.newInstance(Students.class);  
  10. Marshaller marshaller = context.createMarshaller();  
  11. marshaller.marshal(students, new File("a.xml"));   

方法一:使用public void afterUnmarshal(Unmarshaller u, Object parent) 方法

首先修改一下StudentType类,增加一个用来存取父对象的变量:

Java代码   收藏代码
  1. private Students parent;  
  2.   
  3. public Students getParent() {  
  4.     return parent;  
  5. }  

 因为模型是由JAXB直接读取和生成的,因此我们不能通过简单的setParent()来设置parent对象。

 

可以简单在生成的模型类中添加一个public void afterUnmarshal(Unmarshaller u, Object parent) 方法,这个方法在每次构建完模型后都会调用(甚至我们什么接口实现,类继承都不需要声明就会自动调用),其实的parent参数就是我们期望的父模型对象,因此可以直接把这个parent对象设置成我们期望的parent对象:

Java代码   收藏代码
  1. public void afterUnmarshal(Unmarshaller u, Object parent) {  
  2.     if (parent instanceof Students) {  
  3.         this.parent = (Students)parent;  
  4.     }  
  5. }  

 

可以检验一下:

Java代码   收藏代码
  1. JAXBContext context = JAXBContext.newInstance(Students.class);  
  2. Unmarshaller unmarshaller = context.createUnmarshaller();  
  3. Students students = (Students) unmarshaller.unmarshal(new File("a.xml"));  
  4. List<StudentType> student = students.getStudent();  
  5. for(StudentType st: student){  
  6.     System.out.println(st.getName());  
  7.     System.out.println(st.getParent());  
  8. }  

 方法二:使用Binder

方法一简单易用,但是缺点就是需要修改模型,这里介绍的方法就不需要修改模型,只是在读取的时候需要有点不一样:

首先我们用普遍的Dom方式读取文件内容:

Java代码   收藏代码
  1. DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();  
  2. factory.setNamespaceAware(true);  
  3. Document document = factory.newDocumentBuilder().parse(new File("a.xml"));  

 然后创建JAXBContext对象和Binder对象:

Java代码   收藏代码
  1. JAXBContext context = JAXBContext.newInstance(Students.class);  
  2. Binder<Node> binder = context.createBinder();  

 最后用Binder对象去解析模型的和链接父子关系:

Java代码   收藏代码
  1. Students students = (Students) binder.updateJAXB(document.getDocumentElement());  
  2. List<StudentType> student = students.getStudent();  
  3. for(StudentType st: student){  
  4.     System.out.println(st.getName());  
  5.     Node xmlNode = binder.getXMLNode(st);  
  6.     Object parent = binder.getJAXBNode(xmlNode.getParentNode());  
  7.     System.out.println(parent);  
  8. }  

 方法三 使用Unmarshall.Listener监听

除了以上两种方法,还可以使用监听的方式,在marshall的过程中构建父子关系,有点类似于方法一

Java代码   收藏代码
  1. JAXBContext context = JAXBContext.newInstance(Students.class);  
  2. Unmarshaller unmarshaller = context.createUnmarshaller();  
  3.   
  4. final Map<StudentType, Students> map = new HashMap<StudentType, Students>();  
  5. unmarshaller.setListener(new Listener() {  
  6.     public void afterUnmarshal(Object target, Object parent) {  
  7.         super.afterUnmarshal(target, parent);  
  8.         if(target instanceof StudentType && parent instanceof Students){  
  9.             map.put((StudentType)target, (Students) parent);  
  10.         }  
  11.           
  12.     }  
  13. });  
  14. Students students = (Students) unmarshaller.unmarshal(new File("a.xml"));  
  15. List<StudentType> student = students.getStudent();  
  16. for(StudentType st: student){  
  17.     System.out.println(st.getName());  
  18.     System.out.println(map.get(st));  
  19. }  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值