2017-10-18 19 views
0

La racine de mon problème est un XML donné avec des noms de nœuds variables. Le code XML est déjà utilisé et ne peut pas être modifié.JAXB change l'élément "nom" de l'annotation @XMLElements

J'ai créé un XSD pour le XML afin de générer les classes corrospondantes, puis de l'analyser via un DOMParser.

J'utilise le DOMParser parce que par JAXB il n'est pas analysable à cause des noms de variables mais les classes générées sont utiles.

Maintenant, j'ai juste besoin d'un identifiant pour la variable Nodes dans les classes. J'ai pensé qu'il serait préférable de simplement changer l'élément @XmlElement Annotations "name" et lui donner une valeur comme "?" pour identifier les noeuds variables, mais je n'ai aucune idée si et comment il peut être possible de le changer.

J'ai déjà créé un fichier d'épisode pour changer certains noms de classe et je pensais que cela pouvait être changé, mais je n'ai pas trouvé de solution pour cela.

Exemple XML:

<Settings> 
    <Window> 
     <Position Top="5" Left="5"/> 
    </Window> 
    <OpenData> 
     <variable> 
      <TableData> 
       <variable-column00 POS="1" Visible="true" SortDesc="true"/> 
       <variable-column01 POS="3" Visible="true" SortDesc="true"/> 
       <variable-column02 POS="2" Visible="true" SortDesc="true"/> 
      </TableData> 
     </variable> 
     <variable> 
      <UserSettings> 
       <variable-series1 Color="blue" Caption="Series blue" Visible="true" /> 
       <variable-series2 Color="yellow" Caption="Series yellow" Visible="true" /> 
       <variable-series3 Color="red" Caption="Series red" Visible="true" /> 
      </UserSettings> 
      <ChartConfig>configuration-json....</ChartConfig> 
     </variable> 
     <variable/> 
    </OpenData> 
    </Settings> 

Les nœuds variables seraient: noeuds avec le nom "variable", en commençant noeuds avec "colonne variable" et un certain nombre (sous-noeuds de table de données) et les noeuds commençant par « variable série » et un certain nombre (sous-noeuds de paramètres utilisateur)

le XSD pour ce serait:

<?xml version="1.0" encoding="UTF-8"?> 
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified"> 

    <xs:complexType name="Window"> 
    <xs:complexContent> 
     <xs:extension base="SettingsElement"> 
     <xs:sequence> 
      <xs:element name="Position" type="Position" minOccurs="0" maxOccurs="1"/> 
     </xs:sequence> 
     </xs:extension> 
    </xs:complexContent> 
    </xs:complexType> 

    <xs:complexType name="Position"> 
    <xs:complexContent> 
     <xs:extension base="SettingsElement"> 
     <xs:attribute name="Top" type="xs:int" /> 
     <xs:attribute name="Left" type="xs:int" /> 
     </xs:extension> 
    </xs:complexContent> 
    </xs:complexType> 

    <xs:complexType name="OpenData"> 
    <xs:complexContent> 
     <xs:extension base="SettingsElement"> 
     <xs:sequence> 
      <!-- this would be the "variable" Node --> 
      <xs:element name="View" type="View" minOccurs="0" maxOccurs="unbounded" /> 
     </xs:sequence> 
     </xs:extension> 
    </xs:complexContent> 
    </xs:complexType> 


    <xs:complexType name="View"> 
    <xs:complexContent> 
     <xs:extension base="SettingsElement"> 
     <xs:sequence> 
     <!-- normaly the order would be random, but because i use the DOMParser i don't need to pass that to JAXB --> 
     <xs:element name="TableData" type="TableData" minOccurs="0" maxOccurs="unbounded" /> 
     <xs:element name="UserSettings" type="UserSettings" minOccurs="0" maxOccurs="1" /> 
     <xs:element name="ChartConfig" type="xs:string" minOccurs="0" maxOccurs="1" /> 
     </xs:sequence> 
     </xs:extension> 
    </xs:complexContent> 
    </xs:complexType> 

    <xs:complexType name="UserSettings"> 
    <xs:complexContent> 
     <xs:extension base="SettingsElement"> 
     <xs:sequence> 
     <!-- the next Variable Node name beginning with "variable-series" and then a number --> 
     <xs:element name="SeriesDefinition" type="SeriesDefinition" minOccurs="0" maxOccurs="unbounded" /> 
     </xs:sequence> 
     </xs:extension> 
    </xs:complexContent> 
    </xs:complexType> 

    <xs:complexType name="SeriesDefinition"> 
    <xs:complexContent> 
     <xs:extension base="SettingsElement"> 
     <xs:attribute name="Color" type="xs:string" /> 
     <xs:attribute name="Caption" type="xs:string" /> 
     </xs:extension> 
    </xs:complexContent> 
    </xs:complexType> 


    <xs:complexType name="TableData"> 
    <xs:complexContent> 
     <xs:extension base="SettingsElement"> 
     <xs:sequence> 
     <!-- the next Variable Node name beginning with "variable-column" and then a number --> 
     <xs:element name="Column" type="Column" minOccurs="0" maxOccurs="unbounded" /> 
     </xs:sequence> 
     </xs:extension> 
    </xs:complexContent> 
    </xs:complexType> 

    <xs:complexType name="Column"> 
    <xs:complexContent> 
     <xs:extension base="SettingsElement"> 
     <xs:attribute name="POS" type="xs:int" /> 
     <xs:attribute name="Visible" type="xs:boolean" /> 
     </xs:extension> 
    </xs:complexContent> 
    </xs:complexType> 

    <xs:element name="SettingsElement"> 
    </xs:element> 


    <xs:element name="Settings" > 
    <xs:complexType> 
      <xs:sequence> 
      <xs:element name="Window" type="Window" minOccurs="0" /> 
      <xs:element name="OpenData" type="OpenData" minOccurs="0" /> 
      </xs:sequence> 
    </xs:complexType> 
    </xs:element> 

</xs:schema> 

et après je générer i C lass OpenData avec liste de vue serait:

import java.io.Serializable; 
import java.util.ArrayList; 
import javax.xml.bind.annotation.XmlAccessType; 
import javax.xml.bind.annotation.XmlAccessorType; 
import javax.xml.bind.annotation.XmlElement; 
import javax.xml.bind.annotation.XmlType; 

@XmlAccessorType(XmlAccessType.FIELD) 
@XmlType(name = "OpenData", propOrder = { 
    "view" 
}) 
public class OpenData extends SettingsElement implements Serializable { 

    private final static long serialVersionUID = 1L; 
    @XmlElement(name = "View") 
    protected java.util.List<View> view; 

    public java.util.List<View> getview() { 
     if (view == null) { 
      view = new ArrayList<View>(); 
     } 
     return this.view; 
    } 

} 

je besoin d'un identifiant pour mon analyse syntaxique au travail et donc quelque chose comme changer l'Annotation

@XmlElement(name = "View") 

à

@XmlElement(name = "?") 

Alors Je sais que le nom de tag que je recherche n'est pas View mais pourrait être n'importe quoi.

Merci pour l'aide à l'avance.

+0

Bienvenue dans StackOverflow! Veuillez consulter les [guides pour poser des questions] (https://stackoverflow.com/help/asking), en particulier [comment créer un exemple minimal, complet et vérifiable] (https://stackoverflow.com/help/mcve) – AesSedai101

Répondre

0

Ma solution était de changer le générateur.

Tout d'abord je réajuste mon pom comme ceci:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 
    <modelVersion>4.0.0</modelVersion> 


    <groupId>com.example</groupId> 
    <artifactId>my-generator</artifactId> 
    <version>1.0.0-SNAPSHOT</version> 

    <dependencies> 
    <dependency> 
     <groupId>org.jvnet.jaxb2_commons</groupId> 
     <artifactId>jaxb2-basics-tools</artifactId> 
     <version>1.11.1</version> 
    </dependency> 
    </dependencies> 

    <build> 

    <plugins> 
     <plugin> 
     <groupId>org.jvnet.jaxb2.maven2</groupId> 
     <artifactId>maven-jaxb2-plugin</artifactId> 
     <executions> 
      <execution> 
      <id>example</id> 
      <phase>generate-sources</phase> 
      <goals> 
       <goal>generate</goal> 
      </goals> 
      <inherited>false</inherited> 
      <configuration> 
       <schemaDirectory>src/main/resources/META-INF/schemas/</schemaDirectory> 
       <schemaIncludes> 
       <include>configuration.xsd</include> 
       </schemaIncludes> 

       <generateDirectory>${project.build.directory}/generated-sources/</generateDirectory> 
       <generatePackage>com.example.config</generatePackage> 
       <extension>true</extension> 
       <args> 
       <arg>-Xannotate</arg> 
       </args> 

       <plugins> 
       <plugin> 
        <groupId>org.jvnet.jaxb2_commons</groupId> 
        <artifactId>jaxb2-basics-annotate</artifactId> 
        <version>1.0.1</version> 
       </plugin> 
       </plugins> 
      </configuration> 
      </execution> 
      </executions> 
     </plugin> 
    </plugins> 
    </build> 
</project> 

J'ai utilisé le org.jvnet.jaxb2.maven2.maven-jaxb2-plugin, car il est facile à utiliser avec le plugin jaxb2-bases-annoter. J'ai donné à la generationplugin une exécution avec un Id, une phase et un but, puis dans la configuration de l'exécution je lui ai montré le chemin vers le fichier xsd et le nom du schéma à utiliser. Puis je lui ai dit où mettre la sortie et lui a donné un argument, "-Xannotate" et c'est la partie importante, avec cela et le plugin donné, il est possible de modifier les annotations via un fichier * .xjb (fichier de liaison)

J'ai changé mon fichier * .episode en *.XJB fichier parce que le générateur peut les détecter automatiquement et ajouté les lignes de changer la « XmlElement » Annotation:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<jxb:bindings xmlns:jxb="http://java.sun.com/xml/ns/jaxb" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" xmlns:annox="http://annox.dev.java.net" jxb:extensionBindingPrefixes="Xequals annox" xmlns:javaee="http://java.sun.com/xml/ns/javaee" version="2.1"> 


    <jxb:globalBindings xmlns:jxb="http://java.sun.com/xml/ns/jaxb" xmlns:xs="http://www.w3.org/2001/XMLSchema"> 
    <xjc:serializable uid="1" /> 
    </jxb:globalBindings> 

    <jxb:bindings schemaLocation="configuration.xsd"> 
    <jxb:bindings node="//xs:element[@name='Settings']"> 
     <jxb:bindings node="//xs:element[@name='OpenData']"> 
     <jxb:bindings node="//xs:element[@name='View']"> 
      <annox:annotate target="field">@javax.xml.bind.annotation.XmlElement(name="?")</annox:annotate> 
      <jxb:bindings node="//xs:element[@name='TableData']"> 
      <jxb:bindings node="//xs:element[@name='Column']"> 
       <annox:annotate target="field">@javax.xml.bind.annotation.XmlElement(name="?")</annox:annotate> 
      </jxb:bindings> 
      </jxb:bindings> 
      <jxb:bindings node="//xs:element[@name='UserSettings']"> 
      <jxb:bindings node="//xs:element[@name='SeriesDefinition']"> 
       <annox:annotate target="field">@javax.xml.bind.annotation.XmlElement(name="?")</annox:annotate> 
      </jxb:bindings> 
      </jxb:bindings> 
     </jxb:bindings> 
     </jxb:bindings> 
    </jxb:bindings> 
    </jxb:bindings> 
</jxb:bindings> 

maintenant dans la classe Java générée par exemple UserSettings l'annotation XmlElement pour la SeriesDefinition variable est:

@XmlElement(name = "?") 

Et avec réflexion je peux obtenir cette annotation et vérifier si le « nom » propriétée est « ? » et écris que dans une valeur Name je peux donner la classe. Bien sûr cela ne fonctionne que s'il y a au maximum une variable avec l'annotation XmlElement (name = "?") Dans chaque classe, je dois d'abord obtenir tous les autres tags qui ont un nom défini et le reste noms de variables.