2016-11-20 91 views
0

我正在處理一個配置XML文件,我希望它是動態的。JAXB繼承動態命名標籤

我有以下類別:

庫:

@XmlAccessorType(XmlAccessType.FIELD) 
@XmlRootElement(name = "repository") 
public class Repository 
     implements Serializable 
{ 

    @XmlElement(name = "custom-configuration") 
    private CustomConfiguration customConfiguration; 

    ... 
    // Constructor 

    // Getters and setters 
} 

CustomConfiguration:

@XmlAccessorType(XmlAccessType.FIELD) 
public class CustomConfiguration 
{ 
} 

FooBarConfiguration:

@XmlAccessorType(XmlAccessType.FIELD) 
@XmlRootElement(name = "foo-bar-configuration") 
public class FooBarConfiguration extends CustomConfiguration 
{ 

    @XmlAttribute 
    private String bucket; 

    @XmlAttribute 
    private String key; 


    public FooBarConfiguration() 
    { 
    } 

    public String getBucket() 
    { 
     return bucket; 
    } 

    public void setBucket(String bucket) 
    { 
     this.bucket = bucket; 
    } 

    public String getKey() 
    { 
     return key; 
    } 

    public void setKey(String key) 
    { 
     this.key = key; 
    } 

} 

這是我想擁有的一切:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<repository id="test-repository"> 
    <foo-bar-configuration bucket="test-bucket" key="test-key"/> 
    <group/> 
</repository> 

這就是我得到相反:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<repository id="test-repository"> 
    <customConfiguration xsi:type="fooBarConfiguration" bucket="test-bucket" key="test-key" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/> 
    <group/> 
</repository> 

任何想法如何實現這一目標?

回答

1

按照要求,這裏有一個真實世界的例子。

<xsd:element name="AbstractQueryExpression" 
       type="fes:AbstractQueryExpressionType" abstract="true"/> 

This is how it's used

一些基地類型的Schema declares and abstract element

<xsd:complexType name="GetPropertyValueType"> 
     <xsd:complexContent> 
     <xsd:extension base="wfs:BaseRequestType"> 
      <xsd:sequence> 
       <xsd:element ref="fes:AbstractQueryExpression"/> 
      </xsd:sequence> 
      <xsd:attribute name="valueReference" type="xsd:string" 
       use="required"/> 
      <xsd:attribute name="resolvePath" type="xsd:string"/> 
      <xsd:attributeGroup ref="wfs:StandardPresentationParameters"/> 
      <xsd:attributeGroup ref="wfs:StandardResolveParameters"/> 
     </xsd:extension> 
     </xsd:complexContent> 
    </xsd:complexType> 

導致下面的Java代碼:

@XmlElementRef(name = "AbstractQueryExpression", namespace = "http://www.opengis.net/fes/2.0", type = JAXBElement.class) 
protected JAXBElement<?> abstractQueryExpression; 

Another schema declares an element which may substitute the original element

<xsd:element name="StoredQuery" type="wfs:StoredQueryType" 
     substitutionGroup="fes:AbstractQueryExpression"/> 

ObjectFactory這看起來如下:

@XmlElementDecl(namespace = "http://www.opengis.net/wfs/2.0", name = "StoredQuery", substitutionHeadNamespace = "http://www.opengis.net/fes/2.0", substitutionHeadName = "AbstractQueryExpression") 
public JAXBElement<StoredQueryType> createStoredQuery(StoredQueryType value) { 
    return new JAXBElement<StoredQueryType>(_StoredQuery_QNAME, StoredQueryType.class, null, value); 
} 

此機制可用於實現 「擴展點」。您聲明並使用抽象/通用「替代頭」元素,並且在其他模式中,特定元素可以替代它。

希望這會有所幫助。

+0

問題是我沒有使用XSD。我有類可以擴展未知的CustomConfiguration。他們可能或不在類路徑中,所以我不能只寫一個容易的ObjectMapper(因爲我必須事先知道這些類的名字)。還有其他建議嗎? – carlspring

+0

@carlspring你不需要XSD,也不需要事先知道類。將'ObjectFactory'放在你的擴展類所在的位置。構建JAXB上下文時在運行時使用它。編譯時無需知道這些類。 – lexicore

+0

您是否認爲您可以快速瀏覽我的差異:https://github.com/strongbox/strongbox/pull/183/files並告訴我我做錯了什麼? (如果您想構建代碼,請點擊此處:https://github.com/strongbox/strongbox/wiki/Building-the-code)。這是我得到的錯誤:https://github.com/strongbox/strongbox/pull/183/commits/9bdc666c32e7ba04df2e1befe7655050c1652bc9。 – carlspring

1

您應該能夠使用@XmlElementRef通過元素名元帥,例如:

@XmlElementRef 
private CustomConfiguration customConfiguration; 

下面是布萊斯Doughan一個例子:http://blog.bdoughan.com/2010/11/jaxb-and-inheritance-using-substitution.html

的Javadoc:https://docs.oracle.com/javase/8/docs/api/javax/xml/bind/annotation/XmlElementRef.html

+0

這看起來像個好主意。問題是,這個想法是這個 - 這個領域是在這裏,以便自定義實現可以做。我不知道他們會是什麼。它們超出了我們應用的範圍。因此,我不知道該字段的名稱是什麼。這就是爲什麼我試圖讓這看起來很通用。這可能嗎? – carlspring

+1

@carlspring您可以執行'@XmlElementRef受保護的JAXBElement '。你的擴展模塊必須提供一個'ObjectFactory'和'@XmlElementDecl(substitutionHeadName =「custom-configuration」)''。這個patern被稱爲取代組。你基本上說你'FooBarConfiguration'可以代替'CustomConfiguration'。 – lexicore

+0

@lexicore:你介意爲這種情況打個簡單的例子嗎?特別是,工廠部分... – carlspring