2012-04-14 70 views
5

更新 - 見編輯在底部JAXB Annotations - 如何使XmlIDRef元素的列表具有id值作爲屬性而不是元素正文文本?

IDREFS/keyrefs似乎JAXB註釋是可能的,但裁判最終被元素的文本。

我想參考是一個元素的屬性。

例如,假設此對象模型:

@XmlType 
public class Employee { 
    @XmlID 
    @XmlAttribute 
    String name; 
    @XmlAttribute 
    int years; 
    @XmlAttribute 
    String foo; 
} 

@XmlType 
public class Office { 
    @XmlAttribute 
    String name; 
    @XmlElementWrapper 
    @XmlElement(name = "employee") 
    List<Employee> employees; 
} 

@XmlRootElement 
public class Company { 
    @XmlElementWrapper 
    @XmlElement(name = "office") 
    List<Office> offices; 
    @XmlElementWrapper 
    @XmlElement(name = "employee") 
    List<Employee> employees; 
} 

我想外部化的XML格式來結束這樣看:

<company> 
    <offices> 
     <office name="nyc"> 
      <employees> 
       <!--*** id ref to employee name ***--> 
       <employee ref="alice"/> 
       <employee ref="bob"/> 
      </employees> 
     </office> 
     <office name="sf"> 
      <employees> 
       <employee ref="connie"/> 
       <employee ref="daphne"/> 
      </employees> 
     </office> 
    </offices> 
    <employees> 
     <!-- *** name is the id *** --> 
     <employee name="alice" years="3" foo="bar"/> 
     <employee name="bob" years="3" foo="bar"/> 
     <employee name="connie" years="3" foo="bar"/> 
     <employee name="daphne" years="3" foo="bar"/> 
    </employees> 
</company> 

相反,我能做的最好的就是這個(與上面在java代碼中列出的註釋):

<company> 
    <offices> 
     <office name="nyc"> 
      <employees> 
       <employee>alice</employee> 
       <employee>bob</employee> 
      </employees> 
     </office> 
     <office name="sf"> 
      <employees> 
       <employee>connie</employee> 
       <employee>daphne</employee> 
      </employees> 
     </office> 
    </offices> 
    <employees> 
     <employee name="alice" years="3" foo="bar"/> 
     <employee name="bob" years="3" foo="bar"/> 
     <employee name="connie" years="3" foo="bar"/> 
     <employee name="daphne" years="3" foo="bar"/> 
    </employees> 
</company> 

有沒有辦法我可以強制idref價值是員工的一種屬性,而不是元素正文文本?我知道我可以用XML Schema來做到這一點,但是我想盡可能地堅持註釋。

謝謝。

編輯 Torious下面的解決方案几乎可行,但在某些情況下它不起作用。

如果「辦公室」元素之前(在xml文件中)辦公室引用的「員工」元素出現,解組失敗。未找到員工引用,並且EmployeeRef包裝器具有空員工對象。如果「僱員」是第一個,它就可以工作。

這不會是太大問題,但元帥方法會首先放置「辦公室」,以便試圖解組剛剛編組的問題失敗。

編輯2評論在Torious'答案解決排序問題。

回答

4

的解決方案是使用一種XmlAdapter這在一個新的類型,EmployeeRef,其中規定了如何將XML ID參考的實例包裝了一個Employee

@XmlType 
public class Office { 

    @XmlAttribute 
    String name; 

    @XmlElementWrapper 
    @XmlElement(name="employee") 
    @XmlJavaTypeAdapter(EmployeeAdapter.class) // (un)wraps Employee 
    List<Employee> employees; 
} 

@XmlType 
public class EmployeeRef { 

    @XmlIDREF 
    @XmlAttribute(name="ref") 
    Employee employee; 

    public EmployeeRef() { 
    } 

    public EmployeeRef(Employee employee) { 
     this.employee = employee; 
    } 
} 

public class EmployeeAdapter extends XmlAdapter<EmployeeRef, Employee> { 

    @Override 
    public EmployeeRef marshal(Employee employee) throws Exception { 
     return new EmployeeRef(employee); 
    } 

    @Override 
    public Employee unmarshal(EmployeeRef ref) throws Exception { 
     return ref.employee; 
    } 
} 

好運。

+0

是的,這個伎倆。謝謝。 – marathon 2012-04-15 16:50:31

+0

好的,這在某些(大多數)情況下不起作用。請參閱上面的編輯 – marathon 2012-05-14 00:47:14

+1

用@XmlType(propOrder = {「employees」,「offices」})註釋'Company'類以在編組時強制所需的順序。 – Torious 2012-05-14 02:03:08

2

注:我是EclipseLink JAXB (MOXy)鉛和JAXB (JSR-222)專家小組的成員。

下面是通過利用@XmlPath註釋如何使用MOXy完成此操作的示例。由於bug,您將需要從2012年5月17日開始使用EclipseLink 2.4.0夜間標籤。此修補程序也已添加到EclipseLink 2.3.3(2012年5月18日開始)流中。您可以從以下位置下載夜間標籤:

辦公室

employees屬性,您可以結合使用@XmlIDREF註釋與@XmlPath註釋,以獲得所需的映射。 @XmlIDREF告訴JAXB實現寫出一個外鍵而不是該對象。

package forum10150263; 

import java.util.List; 
import javax.xml.bind.annotation.*; 
import org.eclipse.persistence.oxm.annotations.XmlPath; 

@XmlType 
public class Office { 
    @XmlAttribute 
    String name; 

    @XmlPath("employees/employee/@ref") 
    @XmlIDREF 
    List<Employee> employees; 
} 

僱員

的對應物@XmlIDREF@XmlID@XmlID用於指定對象的主鍵。

package forum10150263; 

import javax.xml.bind.annotation.*; 

@XmlType 
public class Employee { 
    @XmlID 
    @XmlAttribute 
    String name; 

    @XmlAttribute 
    int years; 

    @XmlAttribute 
    String foo; 
} 

公司

經由@XmlIDREF機構引用的每一個對象還需要由包含關係來引用。在這個例子中,這是由employees屬性完成的。

package forum10150263; 

import java.util.List; 
import javax.xml.bind.annotation.*; 

@XmlRootElement 
public class Company { 
    @XmlElementWrapper 
    @XmlElement(name = "office") 
    List<Office> offices; 

    @XmlElementWrapper 
    @XmlElement(name = "employee") 
    List<Employee> employees; 
} 

jaxb.properties

要指定莫西爲您的JAXB提供者,你需要添加一個在同一個包中的以下項領域模型命名爲jaxb.properties文件(見Specifying EclipseLink MOXy as Your JAXB Provider

javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory 

演示

標準JAXB API用於解編/編組XML。

package forum10150263; 

import java.io.File; 
import javax.xml.bind.*; 

public class Demo { 

    public static void main(String[] args) throws Exception { 
     JAXBContext jc = JAXBContext.newInstance(Company.class); 

     Unmarshaller unmarshaller = jc.createUnmarshaller(); 
     File xml = new File("src/forum10150263/input.xml"); 
     Company company = (Company) unmarshaller.unmarshal(xml); 

     Marshaller marshaller = jc.createMarshaller(); 
     marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); 
     marshaller.marshal(company, System.out); 
    } 

} 

input.xml中/輸出

<?xml version="1.0" encoding="UTF-8"?> 
<company> 
    <offices> 
     <office name="nyc"> 
     <employees> 
      <employee ref="alice"/> 
      <employee ref="bob"/> 
     </employees> 
     </office> 
     <office name="sf"> 
     <employees> 
      <employee ref="connie"/> 
      <employee ref="daphne"/> 
     </employees> 
     </office> 
    </offices> 
    <employees> 
     <employee name="alice" years="3" foo="bar"/> 
     <employee name="bob" years="3" foo="bar"/> 
     <employee name="connie" years="3" foo="bar"/> 
     <employee name="daphne" years="3" foo="bar"/> 
    </employees> 
</company> 

更多信息

相關問題