带有抽象类值的JAXB Map

时间:2017-06-22 14:59:30

标签: java xml xsd jaxb abstract-class

我有以下Map包含Double或Integer实例作为值,两者都扩展了抽象类Number,注释如下:

@XmlElement(name="settings")
private Map<String,Number> settings;

它被编组为XML:

<settings>
    <entry>
        <key>SETTING_A</key>
        <value xsi:type="xs:double">0.03</value>
    </entry>
    <entry>
        <key>SETTING_B</key>
        <value xsi:type="xs:int">1000</value>
    </entry>
</settings>

我还需要为这种类型的XML提供XSD,这是我遇到问题的地方。我试图用一个选项定义一个complexType,但不起作用,因为包含int的元素和包含double的元素不能具有相同的名称(即它们不能同时命名为“value” ),这正是JAXB生成的XML所做的。

以下XSD可以使用,但我不想使用不同的元素名称(或):

<xsd:complexType name="Entry">
    <xsd:sequence>
        <xsd:element name="key" type="NimrodSettingKey" minOccurs="1" maxOccurs="1"/>
        <xsd:choice>
           <xsd:element name="double" type="xsd:double" minOccurs="1" maxOccurs="1"/>
           <xsd:element name="int" type="xsd:integer" minOccurs="1" maxOccurs="1"/>
        </xsd:choice>
    </xsd:sequence>
</xsd:complexType>

有关如何在XSD文档中指定元素可以是int还是double的任何建议?

谢谢!

编辑#1

@svasa建议在我的XSD中使用以下方法,它为选择中的元素赋予相同的名称:

<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsd:element name="Settings"/>

<xsd:complexType name="Settings">
   <xsd:sequence>
      <xsd:element name="key" type="xsd:string" minOccurs="1" maxOccurs="1" />
        <xsd:choice>
          <xsd:element name="value" xs:type="xsi:double" minOccurs="1" maxOccurs="1" />
          <xsd:element name="value" xs:type="xsi:integer" minOccurs="1" maxOccurs="1" />
        </xsd:choice>
    </xsd:sequence>
</xsd:complexType>
</xsd:schema>

但是我的XSD编辑抱怨这个错误:

complex type 'Settings' violates the unique particle attribution rule in its components 'value' and 'value'

我认为这意味着每个下面的两个元素必须有不同的名称,它们不能都被命名为“value”。

2 个答案:

答案 0 :(得分:0)

我终于选择了重构我的代码:

@XmlElement(name="settings")
private Map<String,Number> settings

为:

@XmlElementWrapper(name="settings")
@XmlElement(name="setting")
private List<Setting> settings;

我的设置类已重命名为“设置”,现在存储一个具有属性的设置:

@XmlAttribute(name="name")
private String name;

@XmlAttribute(name="intValue")
private Integer intValue;

@XmlAttribute(name="doubleValue")
private Double doubleValue;

当编组为XML时,它会生成具有doubleValue或intValue属性的元素(但在这两种情况下都会命名该元素):

<settings>
   <setting name="SETTING_A" doubleValue="1.0E-5"/>
   <setting name="SETTING_B" intValue="1000"/>
   ...
</settings>

当XSD包含:

时,生成的XML有效
<xsd:complexType name="Settings">
    <xsd:sequence>
        <xsd:element name="setting" type="Setting" minOccurs="0" maxOccurs="unbounded"/>
    </xsd:sequence>
</xsd:complexType>

<xsd:complexType name="Setting">
    <xsd:attribute name="name" type="xsd:string"/>
    <xsd:attribute name="doubleValue" type="xsd:double"/>
    <xsd:attribute name="intValue" type="xsd:int"/>
</xsd:complexType>

答案 1 :(得分:0)

xs:choice应该可以指定整数或双精度,maxOccurs="1"只会处理一个值。

但是如果你希望key是唯一的,你可以使用xsd:unique,如下所示:

<xsd:element name="settings">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element maxOccurs="unbounded" name="entry">
          <xsd:complexType>
            <xsd:sequence>
              <xsd:element name="key" type="NimrodSettingKey" minOccurs="1" maxOccurs="1" />
              <xsd:choice>
                <xsd:element name="value" xsi:type="xsd:double" minOccurs="1" maxOccurs="1" />
                <xsd:element name="value" xsi:type="xsd:integer" minOccurs="1" maxOccurs="1" />
              </xsd:choice>
            </xsd:sequence>
          </xsd:complexType>
        </xsd:element>
      </xsd:sequence>
    </xsd:complexType>
    <xsd:unique name="keyU">
         <xsd:selector xpath=".//key" />
         <xsd:field xpath="." />
    </xsd:unique>
  </xsd:element>

本节:

<xsd:unique name="keyU">
      <xsd:selector xpath=".//key" />
      <xsd:field xpath="." />
</xsd:unique>

添加unique constraint,指明您的key应该是唯一的。