2016-11-20 75 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