Ho un piccolo documento XML in formato FIXML. Sto smantellandoli usando jaxb.Jaxb unmarshalls fixml oggetto ma tutti i campi sono nulli
Il problema
Il processo completo senza errori ma gli oggetti che vengono creati sono completamente nullo. Ogni campo è vuoto. I campi che sono liste (come la Qtà) hanno il giusto numero di oggetti al loro interno. Ma anche i campi di questi oggetti sono nulli.
Setup
Ho scaricato lo schema FIXML da here e ho creato le classi con xjc e il plugin Maven. Sono tutti nel pacchetto org.fixprotocol.fixml_5_0_sp2. Ho il XML di esempio in un file
FIXML.XML
<?xml version="1.0" encoding="ISO-8859-1"?>
<FIXML>
<Batch>
<PosRpt>
<Pty ID="GS" R="22"/>
<Pty ID="01" R="5"/>
<Pty ID="6U8" R="28">
<Sub ID="2" Typ="21"/>
</Pty>
<Pty ID="GS" R="22"/>
<Pty ID="6U2" R="2"/>
<Instrmt ID="GHPKRW" SecTyp="FWD" MMY="20121018" MatDt="2012-10-18" Mult="1" Exch="GS" PxQteCcy="KJS" FnlSettlCcy="GBP" Fctr="0.192233298" SettlMeth="G" ValMeth="FWDC2" UOM="Ccy" UOMCCy="USD">
<Evnt EventTyp="121" Dt="2013-10-17"/>
<Evnt EventTyp="13" Dt="2013-10-17"/>
</Instrmt>
<Qty Long="0.000" Short="22000000.000" Typ="PNTN"/>
<Qty Long="0.000" Short="22000000.000" Typ="FIN"/>
<Qty Typ="DLV" Long="0.00" Short="0.00" Net="0.0"/>
<Amt Typ="FMTM" Amt="32.332" Ccy="USD"/>
<Amt Typ="CASH" Amt="1" Rsn="3" Ccy="USD"/>
<Amt Typ="IMTM" Amt="329.19" Ccy="USD"/>
<Amt Typ="DLV" Amt="0.00" Ccy="USD"/>
<Amt Typ="BANK" Amt="432.23" Ccy="USD"/>
</PosRpt>
Poi chiamo l'unmarshaller con gestore di eventi personalizzati che solo genera un'eccezione su un errore di analisi. L'analisi è completa, quindi so che non vengono generati errori. Sto anche gestire lo spazio dei nomi come suggerito here
// sort out the file
String xmlFile = "C:\\FIXML.XML.xml";
System.out.println("Loading XML File..." + xmlFile);
InputStream input = new FileInputStream(xmlFile);
InputSource is = new InputSource(input);
// create jaxb context
JAXBContext jc = JAXBContext.newInstance("org.fixprotocol.fixml_5_0_sp2");
Unmarshaller unmarshaller = jc.createUnmarshaller();
// add event handler so jacB will fail on an error
CustomEventHandler validationEventHandler = new CustomEventHandler();
unmarshaller.setEventHandler(validationEventHandler);
// set the namespace
NamespaceFilter inFilter = new NamespaceFilter("http://www.fixprotocol.org/FIXML-5-0-SP2", true);
inFilter.setParent(SAXParserFactory.newInstance().newSAXParser().getXMLReader());
SAXSource source = new SAXSource(inFilter, is);
// GO!
JAXBElement<FIXML> fixml = unmarshaller.unmarshal(source, FIXML.class);
Viene creato l'oggetto FIXML. Nell'esempio sopra l'array Amt avrà cinque elementi che corrispondono al numero di amts nel file. Ma tutti i campi come ccy sono nulli. Ho messo i breakpoint nelle classi create da xjc e nessuno dei setter è mai stato chiamato.
Quindi sembra che jaxb non si sbarazzi e crei tutti gli oggetti corretti, ma non chiama mai i setter ??
Sono completamente perplesso su questo. Ho visto alcuni post che sono più sicuri che il file package.info generato da xjc sia presente nei pacchetti e mi sono assicurato che fosse lì. Non ci sono avvisi nell'IDE sul codice generato.
Qualsiasi aiuto molto apprezzato.
Aggiornamento Ho provato a impostare il file di schema sul unmarshaller prima di iniziare il unmarshalling.
Schema schema = sf.newSchema(f);
unmarshaller.setSchema(schema);
io non ero sicuro che lo schema da utilizzare quindi l'ho fatto in un ciclo cercare ogni file a sua volta. Il risultato è nessuno di loro farlo funzionare. Causano l'errore È stato trovato un contenuto non valido a partire dall'elemento 'PosRpt'.
Che è sorprendente. Ora sto pensando che il problema sia qualcosa da fare con namespace.
Aggiornamento 2 Ancora nessun progresso. Ho provato JAXB 2.0 & 2.2. Ora guardando diversi plugin Maven per chiamare xjc.Ma non penso sia così.
Aggiornamento 3 Così ora dopo aver letto il fixml in sto marshalling in un file separato.
// GO!
JAXBElement<FIXML> fixml = unmarshaller.unmarshal(source, FIXML.class);
//Write
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(fixml, output);
I risultati sono:
inputfile.xml
<FIXML>
<Batch>
<PosRpt RptID="5952323" ReqID="434242" SetSesID="EOD" MtchStat="2" PriSetPx="11.284328" SetPx="11.4432" SetPxTyp="1" SettlCcy="EUR" ReqTyp="1" MsgEvtSrc="REG" BizDt="2012-11-17" SettlDt="2018-11-20">
<Pty ID="CC" R="22"/>
....
Output.xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<FIXML xmlns="http://www.fixprotocol.org/FIXML-5-0-SP2">
<Batch>
<PosRpt>
<Pty/>
<Pty/>
<Pty/>
Così la struttura del file è corretto, ma è vuoto come previsto. C'è uno spazio dei nomi esplicito quindi ho provato ad aggiungere quello spazio dei nomi al file di input di test, ma questo non fa alcuna differenza. Successivamente proverò a popolare l'oggetto fixml prima di eseguirne il marshalling.
Update 4
Io non sono la creazione di una semplice classe FIXML e marhelling esso.
simple_fxixml_out.xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<FIXML xmlns="http://www.fixprotocol.org/FIXML-5-0-SP2" cv="DDDD">
<Batch ID="dfddd">
<PositionReportMessageT Ccy="CCC"/>
</Batch>
</FIXML>
Quando provo e letto che nel ottengo:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<FIXML xmlns="http://www.fixprotocol.org/FIXML-5-0-SP2">
<Batch/>
Le cose che faccio notare forma questo sono:
- Il generato lo spazio dei nomi è lo stesso
- Ho creato PositionReportMessageT piuttosto che un tag PosRpt
- Anche l'attributo DDDD su FIXML sopravvive alla transizione.
Provare a creare prima l'oggetto JAXB con alcuni dati di esempio, quindi eseguire il marshalling su un file. Verifica se torni indietro a un oggetto JAXB quando leggi di nuovo. Dai un'occhiata agli spazi dei nomi sul file generato. – artbristol
Questa è una buona idea. Ci proveremo (aggiornamento da seguire). – DUFF