2017-06-22 1 views
0

J'ai la carte suivante qui contient soit des instances double ou entier en tant que valeur, les deux qui étendent la classe abstraite Numéro, annoté comme suit:JAXB Carte avec classe abstraite valeurs

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

Il est rangea en XML: Je dois également fournir le XSD pour ce type de XML, et c'est là que j'ai des problèmes. J'ai essayé de définir un complexType avec un choix, mais cela ne fonctionne pas parce que l'élément qui contient l'int, et l'élément qui contient le double ne peuvent pas avoir le même nom (ie ils ne peuvent pas être tous les deux nommés "value"), ce qui est exactement ce que fait le XML généré par JAXB.

travaillerait Le XSD suivant, mais je ne veux pas avoir des noms différents éléments (ou):

<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> 

Toutes les suggestions sur comment dois-je préciser que l'élément pourrait être un entier ou un double en mon document XSD?

Merci!

EDIT # 1

@svasa a suggéré d'utiliser l'approche suivante dans mon XSD, qui donnent le même nom à un élément dans un choix:

<?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> 

mais mon éditeur XSD se plaint de ce erreur:

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

que je pense signifie que les deux éléments sous la doivent avoir des noms différents chacun, ils peuvent les deux ne sont pas nommés "valeur".

+0

Par 'les valeurs qui contiennent un int et celles qui contiennent un nombre ne peuvent pas avoir le même nom 'voulez-vous dire le' key' ne peut pas avoir le même nom pour 'int' et' double' droit? – SomeDude

+0

Oui, par exemple key = SETTING_A value = 0.5d (un double) et key = SETTING_B value = 1000 (et int). – Guillem

Répondre

0

J'ai finalement opté pour refactorisation mon code de:

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

à:

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

Mes préférences classe a été renommé Réglage et stocke désormais un réglage unique avec des attributs:

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

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

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

Et lorsqu'il est rassemblé en XML, il produit les éléments qui ont soit doubleValue ou intValu e attributs (mais l'élément est nommé dans les deux cas):

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

Le XML généré est valable lorsque le XSD contient:

<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> 
+0

Comment cela résout-il le problème du 'name' étant même pour double et int? – SomeDude

+0

@svasa Dans la question initiale, je ne voulais pas avoir d'éléments XML avec des noms différents (ie et ) dans mon XSD. Dans ma propre réponse, j'ai choisi d'avoir un élément XML nommé qui a des attributs nommés doubleValue et intValue (ce qui est bien dans ce cas). – Guillem

0

Le xs:choice devrait vous permettre de spécifier entier ou double, et maxOccurs="1" ne prendra en charge qu'une seule valeur.

Mais si vous voulez que le key être unique, vous pouvez utiliser xsd: unique comme ci-dessous:

<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> 

Cette section:

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

ajoute un unique constraint qui spécifie vos key s devraient être unique.

+0

Cette solution me donne une erreur (voir question originale ** EDIT # 1 **), apparemment les éléments sous le ne peuvent pas avoir le même nom (c'est pourquoi je les avais nommés "double" et "int" dans le poste original). – Guillem