2013-01-11 5 views
7

Ecco un estratto dal mio banale file XSDAggiunta di metodi più per una classe JAXB generata da schema

<?xml version="1.0" encoding="UTF-8"?> 
<schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="ns" 
    xmlns:tns="sns" elementFormDefault="qualified"> 

    <element name="document"> 
     <attribute name="title" use="required"/> 
    </element> 
</schema> 

uso il maven-jaxb2-plugin per generare le classi Java da questo. La classe Document ha un metodo getTitle() per restituire il testo dell'attributo title.

Voglio aggiungere un ulteriore metodo per Document:

public String getStrippedTitle() { 
    return getTitle().replaceAll("\\s+", ""); 
} 

voglio che il mio metodo in più per apparire sull'oggetto deserializzati (piuttosto che me solo chiamando o scrivendo una classe wrapper) perché voglio passare l'oggetto unmarshalled di livello superiore a un modello di stringa e lo ha iterato su sotto-elementi che chiamano il mio metodo extra.

Ho trovato instructions ma mi hanno detto di impostare una proprietà su Unmarshaller e l'implementazione mia (Mac OS X, Java 7) non sembra supportare alcuna proprietà.

Come devo fare?

risposta

7

Seguendo il collegamento che Brian Henry ha dato, ho scoperto che potevo eseguire la personalizzazione del binding inline nel mio file di schema per fare ciò che volevo. L'effetto è esattamente lo stesso della soluzione di Brian, ma non richiede un riferimento a un riferimento a com.sun.xml.internal.

In primo luogo, il file di schema viene modificato in qualche modo:

<schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="ns" 
    xmlns:tns="sns" elementFormDefault="qualified" 
    xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" 
jaxb:version="2.0"> 

    <element name="document"> 
     <annotation> 
      <appinfo> 
       <jaxb:class implClass="DocumentEx" /> 
      </appinfo> 
     </annotation> 
     <attribute name="title" use="required"/> 
    </element> 
</schema> 

Quando lo schema viene compilato in codice Java, l'ObjectFactory generato farà riferimento al DocumentEx invece di Document. DocumentEx è una classe creo, che assomiglia a questo:

public class DocumentEx extends Document { 
    public String getStrippedTitle() { 
     return getTitle().replaceAll("\\s+", ""); 
    } 
} 

Document (classe sto estensione) è ancora generato dal compilatore schema-to-Java. Ora, quando ho unmarshall un documento che in realtà ottenere un oggetto DocumentEx:

JAXBContext jaxbContext = JAXBContext.newInstance("com.example.xml"); 
    Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); 
    unmarshaller.setSchema(testSchema); 
    DocumentEx doc = (DocumentEx)unmarshaller.unmarshal(xmlFile); 

V'è una certa (difficili da analizzare) la documentazione per questo a Oracle e alcuni esempi utili a O'Reilly.

2

Si potrebbe provare ad aggiornare il nome della proprietà che si sta vedendo nel documento collegato. Prova a modificare:

com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.FACTORY 

o

"com.sun.xml.internal.bind.ObjectFactory" 

Direi che ti porterà oltre il PropertyException Immagino che stai vedendo. La risposta più completa, here, suggerisce che non è garantito che funzioni, ma vale la pena provarci da quando sei arrivato fin qui. Il codice sorgente, per quanto ho visto (non lontano) sembra supportare questa proprietà.

+0

Questo funziona. Grazie! Avete qualche suggerimento per un migliore metodo generale di smantellamento di un file XML in classi Java con alcuni metodi aggiuntivi? Stavo provando SAX prima di JAXB, ma sembrava che stavo solo scrivendo la mia (scadente) implementazione JAXB. –

+1

@NathanielWaisbrot - Non è necessario generare il modello JAXB da uno schema XML. È possibile iniziare da qualsiasi modello di oggetto desiderato e utilizzare le annotazioni JAXB per configurare il mapping XML. –