2012-11-16 4 views
6

Ich versuche, einige XML mit EclipseLink MOXy zu analysieren, und es ist in der Zeile mit dem xsi Attribut fehlgeschlagen. Wenn ich das entferne, parst es gut. Wie auch immer, ich habe 100GiB XML, um durchzuwaten und das Ändern der Quelldateien ist keine Option.Wie setzt man Namespace bewusst auf falsch?

Es wurde vorgeschlagen, dass, wenn ich XmlParser.setNamespaceAware(false) einstellen kann, dann sollte es funktionieren - aber ich habe keine Ahnung, wie das zu konfigurieren, ohne direkt in den Eingeweiden von 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"> 
[...] 

Die Ausnahme, die ich bekommen, wenn das xsi: Präfix vorhanden ist:

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

Was ist das ursprüngliche Problem, das Sie treffen? –

+0

@BlaiseDoughan aktualisiert. Wirklich hoffe, dass Sie helfen können :) –

+0

In Ihrem Anwendungsfall können Sie die erforderliche 'xmlns: xsi' Deklaration hinzufügen? Überprüfen Sie, bevor wir in alternative Optionen eintauchen. –

Antwort

8

Es gibt derzeit keine Option in EclipseLink JAXB (MOXy) es zu sagen, Namensräume zu ignorieren. Aber es gibt einen Ansatz, den Sie verwenden können, indem Sie einen StAX-Parser nutzen.

Demo

Sie können eine StAX erstellen XMLStreamReader auf dem XML-Eingang, der nicht bewusst ist der Namespace und dann haben moxy Abstellungs davon.

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

} 

Eingang (input.xml)

Unten ist eine vereinfachte Version des XML aus Ihrer Frage. Beachten Sie, dass dieser XML-Code nicht ordnungsgemäß für den Namespace qualifiziert ist, da die Namespacedeklaration für das Präfix xsi fehlt.

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

Ausgabe

Unten finden Sie die Ausgabe aus dem Demo-Code ausgeführt wird.

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

Anstatt Namespace Bewusstsein zu deaktivieren insgesamt, können Sie möglicherweise einen StAX-Implementierung spezifische Mechanismus verwenden, um den xsi Präfix im Voraus zu erklären, dann mit Namespaces aktiviert analysieren. Zum Beispiel mit Woodstox kann man sagen:

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"); 

und dann die Unmarshaller erstellen und entpacken Sie die xsr wie in Blaise's answer. Dies führt zwar zu einer bestimmten StAX-Implementierung, bedeutet jedoch, dass Sie Ihre vorhandenen JAXB-Modellklassen nicht ändern müssen, wenn Sie erwarten, dass das <crossref>-Element und seine untergeordneten Elemente sich im Namespace http://www.crossref.org/xschema/1.0 befinden.