2016-05-18 3 views
0

Ich habe ein Problem mit XML-Validierung mit einem XSD-Schema mit Woodstox und Stax2. Die Validierung schlägt fehl, obwohl die XML-Daten dem Schema entsprechen.Validierung fehlgeschlagen beim Schreiben von XML mit Woodstox/Stax2

Überraschenderweise nur die Validierung Problem tritt auf, wenn Schreiben von XML (mit XMLStreamWriter2), nicht, wenn Lesen XML (mit XMLStreamReader2).

Ich habe ein kleines Beispiel erstellt, um den Fehler zu reproduzieren und zu isolieren. Im Grunde liest es einfach XML aus einer Datei in einen XMLStreamReader2 (validiert mit einem XSD-Schema) und kopiert es dann in einen XMLStreamWriter2 (auch mit derselben XSD validierend).

Nun schlägt dies mit einem Validierungsfehler von Writer fehl. Wenn ich die Validierung des Writers deaktiviere, läuft alles reibungslos und der Writer liefert perfekt konformes XML. Hier

ist der Code:

import com.ctc.wstx.stax.WstxInputFactory; 
import com.ctc.wstx.stax.WstxOutputFactory; 
import org.codehaus.stax2.XMLStreamReader2; 
import org.codehaus.stax2.XMLStreamWriter2; 
import org.codehaus.stax2.validation.XMLValidationSchema; 
import org.codehaus.stax2.validation.XMLValidationSchemaFactory; 

import javax.xml.stream.XMLStreamException; 
import java.io.InputStream; 
import java.io.StringWriter; 

public class Converter { 

    public static void main(String... args) throws XMLStreamException { 

     InputStream reader = Converter.class.getClassLoader().getResourceAsStream("test.xml"); 
     StringWriter writer = new StringWriter(); 

     XMLValidationSchema schema = XMLValidationSchemaFactory.newInstance(XMLValidationSchema.SCHEMA_ID_W3C_SCHEMA) 
       .createSchema(Converter.class.getClassLoader().getResourceAsStream("schema.xsd")); 


     XMLStreamReader2 xmlReader = (XMLStreamReader2) new WstxInputFactory().createXMLStreamReader(reader); 
     xmlReader.validateAgainst(schema); 

     XMLStreamWriter2 xmlWriter = (XMLStreamWriter2) new WstxOutputFactory().createXMLStreamWriter(writer); 
     xmlWriter.validateAgainst(schema); 

     xmlWriter.copyEventFromReader(xmlReader, false); 

     while (xmlReader.hasNext()) { 
      xmlReader.next(); 

      xmlWriter.copyEventFromReader(xmlReader, false); 
     } 

     System.out.println(writer.toString()); 
    } 
} 

Hier ist der XML:

<?xml version="1.0" encoding="UTF-8"?> 
<JobStatus xsdVersion="NA"> 
    <Document> 
     <DocumentId>1234567890</DocumentId> 
    </Document> 
    <Document> 
     <DocumentId>1234567891</DocumentId> 
    </Document> 
</JobStatus> 

Und hier ist das Schema:

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

    <xs:element name="JobStatus"> 
     <xs:complexType> 
      <xs:sequence> 
       <xs:element name="Document" maxOccurs="unbounded"> 
        <xs:complexType> 
         <xs:sequence> 
          <xs:element name="DocumentId" type="xs:string"/> 
         </xs:sequence> 
        </xs:complexType> 
       </xs:element> 
      </xs:sequence> 
      <xs:attribute name="xsdVersion" type="xs:string" use="required"/> 
     </xs:complexType> 
    </xs:element> 
</xs:schema> 

Und das alles Ergebnis in (mit Validierung der Schreiber aktiviert):

Exception in thread "main" com.ctc.wstx.exc.WstxValidationException: element "JobStatus" is missing "xsdVersion" attribute 
     at [row,col {unknown-source}]: [1,66] 
     at com.ctc.wstx.exc.WstxValidationException.create(WstxValidationException.java:50) 
     at com.ctc.wstx.sw.BaseStreamWriter.reportProblem(BaseStreamWriter.java:1223) 
     at com.ctc.wstx.msv.GenericMsvValidator.reportError(GenericMsvValidator.java:549) 
     at com.ctc.wstx.msv.GenericMsvValidator.reportError(GenericMsvValidator.java:541) 
     at com.ctc.wstx.msv.GenericMsvValidator.reportError(GenericMsvValidator.java:535) 
     at com.ctc.wstx.msv.GenericMsvValidator.validateElementAndAttributes(GenericMsvValidator.java:343) 
     at com.ctc.wstx.sw.BaseNsStreamWriter.closeStartElement(BaseNsStreamWriter.java:420) 
     at com.ctc.wstx.sw.BaseStreamWriter.copyEventFromReader(BaseStreamWriter.java:807) 
     at Converter.main(Converter.java:34) 

Ohne Validierung auf dem Autor, läuft das Programm in Ordnung und gibt dieselbe XML als Eingabe zur Verfügung gestellt (Modulo einig Einzug und Zeilenumbruch Unterschiede)

Also meine Frage ist: bin ich etwas falsch mit Woodstox hier? Warum schlägt die Validierung nur beim Schreiber fehl?

Ich kann dieses Problem mit anderen Paaren von XSD und XML reproduzieren, in diesem Fall können Sie verschiedene Arten von Fehlern erhalten, aber immer auf der Schreiberseite. Die Validierung auf der Leserseite funktioniert immer (solange das XML offensichtlich der XSD entspricht).

Alle Einsichten würden sehr geschätzt werden!

PS: Referenz, hier sind die Abhängigkeiten und Version das Beispiel verwendet

  • org.codehaus.woodstox stax2-api 4.0.0
  • com.fasterxml.woodstox Woodstox-Core 5.0.2
  • net.java.dev.msv msv-Core-2013.6.1
  • net.java.dev.msv xsdlib 2013.6.1 <
+0

haben Sie versucht, 'copyEventFromReader (xmlReader, true)' aufzurufen, d. H. Mit 'true' für den zweiten Parameter? – wero

+0

Hi @wero, ja, ich habe versucht, Sie erhalten immer noch die gleiche Ausnahme mit 'preserveEventData' auf' true' gesetzt, wie Sie vorschlagen. – ahelix

+0

Sie könnten debuggen und finden Sie heraus, warum 'GenericMsvValidator.validateElementAndAttributes' ein Problem hat – wero

Antwort