2012-11-16 11 views
6

Sto tentando di analizzare un file XML con EclipseLink MOXy e non è in linea con l'attributo xsi. Se rimuovo questo, si analizza bene. Tuttavia, ho 100GiB di XML da guadare e cambiare i file sorgente non è un'opzione.Come impostare lo spazio dei nomi su false?

È stato suggerito che se è possibile impostare XmlParser.setNamespaceAware(false), allora dovrebbe funzionare, ma non ho idea di come configurarlo, senza entrare nelle viscere di MOXy.

<record> 
<header> 
    <!-- citation-id: 14404534; type: journal_article; --> 
    <identifier>info:doi/10.1007/s10973-004-0435-2</identifier> 
    <datestamp>2009-04-28</datestamp> 
    <setSpec>J</setSpec> 
    <setSpec>J:1007</setSpec> 
    <setSpec>J:1007:2777</setSpec> 
</header> 
<metadata> 
    <crossref xmlns="http://www.crossref.org/xschema/1.0" 
     xsi:schemaLocation="http://www.crossref.org/xschema/1.0 http://www.crossref.org/schema/unixref1.0.xsd"> 
     <journal> 
      <journal_metadata language="en"> 
[...] 

L'eccezione che provo quando il prefisso xsi: è presente è:

org.springframework.oxm.UnmarshallingFailureException: JAXB unmarshalling exception; nested exception is javax.xml.bind.UnmarshalException 
- with linked exception: 
[Exception [EclipseLink-25004] (Eclipse Persistence Services - 2.4.0.v20120608-r11652): org.eclipse.persistence.exceptions.XMLMarshalException 
Exception Description: An error occurred unmarshalling the document 
Internal Exception: javax.xml.stream.XMLStreamException: ParseError at [row,col]:[13,107] 
Message: http://www.w3.org/TR/1999/REC-xml-names-19990114#AttributePrefixUnbound?crossref&xsi:schemaLocation&xsi] 
+0

Qual è il problema originale che stai colpendo? –

+0

@BlaiseDoughan aggiornato. Spero davvero che tu possa aiutare :) –

+0

Nel tuo caso d'uso sei in grado di aggiungere la necessaria dichiarazione 'xmlns: xsi'? Basta controllare prima di tuffarci in opzioni alternative. –

risposta

8

Attualmente non è un'opzione in EclipseLink JAXB (MOXy) di raccontarla di ignorare gli spazi dei nomi. Ma esiste un approccio che puoi utilizzare sfruttando un parser StAX.

Demo

È possibile creare uno StAX XMLStreamReader sull'ingresso XML che non è a conoscenza namespace e quindi avere Moxy unmarshal da questo.

package forum13416681; 

import javax.xml.bind.*; 
import javax.xml.stream.*; 
import javax.xml.transform.stream.StreamSource; 

public class Demo { 

    public static void main(String[] args) throws Exception { 
     JAXBContext jc = JAXBContext.newInstance(Foo.class); 

     XMLInputFactory xif = XMLInputFactory.newFactory(); 
     xif.setProperty(XMLInputFactory.IS_NAMESPACE_AWARE, false); 
     StreamSource source = new StreamSource("src/forum13416681/input.xml"); 
     XMLStreamReader xsr = xif.createXMLStreamReader(source); 

     Unmarshaller unmarshaller = jc.createUnmarshaller(); 
     Foo root = (Foo) unmarshaller.unmarshal(xsr); 

     Marshaller marshaller = jc.createMarshaller(); 
     marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); 
     marshaller.marshal(root, System.out); 
    } 

} 

Java Model (Foo)

package forum13416681; 

import javax.xml.bind.annotation.XmlRootElement; 

@XmlRootElement 
public class Foo { 

    private String bar; 

    public String getBar() { 
     return bar; 
    } 

    public void setBar(String bar) { 
     this.bar = bar; 
    } 

} 

ingresso (input.xml)

Qui di seguito è una versione semplificata del XML dalla tua domanda. Si noti che questo XML non è qualificato come spazio dei nomi poiché manca la dichiarazione dello spazio dei nomi per il prefisso xsi.

<?xml version="1.0" encoding="UTF-8"?> 
<foo xsi:schemaLocation="http://www.crossref.org/xschema/1.0 http://www.crossref.org/schema/unixref1.0.xsd"> 
    <bar>Hello World</bar> 
</foo> 

uscita

Di seguito si riporta l'uscita dalla esecuzione del codice demo.

<?xml version="1.0" encoding="UTF-8"?> 
<foo> 
    <bar>Hello World</bar> 
</foo> 
2

Piuttosto che disabilitando la consapevolezza dello spazio dei nomi del tutto, si può essere in grado di utilizzare un meccanismo specifico StAX-implementazione di dichiarare il prefisso xsi in anticipo, quindi analizzare con spazi dei nomi abilitati. Ad esempio, con Woodstox si può dire:

import javax.xml.bind.*; 
import javax.xml.stream.*; 
import javax.xml.transform.stream.StreamSource; 
import com.ctc.wstx.sr.BasicStreamReader; 

public class Demo { 

    public static void main(String[] args) throws Exception { 
     JAXBContext jc = JAXBContext.newInstance("com.example"); 

     XMLInputFactory xif = XMLInputFactory.newFactory(); 
     StreamSource source = new StreamSource("input.xml"); 
     XMLStreamReader xsr = xif.createXMLStreamReader(source); 
     ((BasicStreamReader)xsr).getInputElementStack().addNsBinding(
       "xsi", "http://www.w3.org/2001/XMLSchema-instance"); 

e quindi creare l'unmarshaller e unmarshalling il xsr come in Blaise's answer. Mentre questo ovviamente ti lega a una specifica implementazione di StAX, significa che non devi modificare le tue classi di modelli JAXB esistenti se si aspettano che l'elemento <crossref> e i suoi figli siano nello spazio dei nomi http://www.crossref.org/xschema/1.0.

Problemi correlati