2009-07-11 11 views
4

einige Code-Schnipsel.Validierung JAXB, aber Leerzeichen nicht ignoriert

Die Java-Codierung macht das Jaxb-Abmarshalling. ziemlich einfach, kopiert aus Tutorials online.

JAXBContext jc = JAXBContext.newInstance("xmlreadtest"); 
Unmarshaller u = jc.createUnmarshaller(); 

// setting up for validation. 
SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); 
StreamSource schemaSource = new StreamSource(ReadXml.class.getResource("level.xsd").getFile()); 
Schema schema = schemaFactory.newSchema(schemaSource); 
u.setSchema(schema); 

// parsing the xml 
URL url = ReadXml.class.getResource("level.xml"); 
Source sourceRoot = (Source)u.unmarshal(url); 

Das Problemelement aus der XML-Datei. Das Element enthält nichts als ignorierbare Leerzeichen. Es ist schlecht formatiert, wie es gezeigt genau wie es in der Datei gefunden.

<HashLine _id='FI6' 
ppLine='1' 
origLine='1' 
origFname='level.cpp'> 
</HashLine> 

Das XSD-Element, das dieses Element beschrieben.

<xs:element name="HashLine"> 
    <xs:complexType> 
    <xs:attribute name="origLine" type="xs:NMTOKEN" use="required" /> 
    <xs:attribute name="origFname" type="xs:string" use="required" /> 
    <xs:attribute name="_id" type="xs:ID" use="required" /> 
    <xs:attribute name="ppLine" type="xs:NMTOKEN" use="required" /> 
    </xs:complexType> 
</xs:element> 

der Fehler

[org.xml.sax.SAXParseException: cvc-complex-type.2.1: Element 'HashLine' must have no character or element information item [children], because the type's content type is empty.] 

ich den Fehler bestätigt haben aus diesem Element kommt.

Es lädt gut ohne Validierung. Aber ich muss Validierung verwenden, da ich schwere Änderungen und Ergänzungen an der Anwendung vornehmen werde, und ich muss sicher sein, dass alles ordnungsgemäß gemarshallt/abmarschiert wird.

Es funktioniert auch gut, wenn ich den complexType ändern, um einen SimpleContext mit einer xs: string-Erweiterung einzuschließen. Aber ich bekomme dieses Problem von Entitäten überall, von denen es viele, und in vielen xsd-Dateien gibt. Es ist also nicht möglich, jedes Element in den XML-Dokumenten auf xs: string zu basieren, nur um dieses Problem zu umgehen.

Event obwohl j2se 6 die SchemaFactory von Apache-Xerces verwendet, scheint es nicht das 'Ignorieren-Whitespace' Feature von Xerces zu akzeptieren. (Dh schemaFactory.setFeature())

Antwort

4

Sie konnten die StAX API verwenden, um leere Zeichenblöcke vor der Validierung herauszufiltern mit einem EventFilter:

class WhitespaceFilter implements EventFilter { 
    @Override 
    public boolean accept(XMLEvent event) { 
    return !(event.isCharacters() && ((Characters) event) 
     .isWhiteSpace()); 
    } 
} 

Damit kann Ihre Eingabe wickeln:

// strip unwanted whitespace 
XMLInputFactory inputFactory = XMLInputFactory.newInstance(); 
XMLEventReader eventReader = inputFactory 
    .createXMLEventReader(ReadXml.class.getResourceAsStream("level.xml")); 
eventReader = inputFactory.createFilteredReader(eventReader, 
    new WhitespaceFilter()); 

// parsing the xml 
Source sourceRoot = (Source) unmarshaller.unmarshal(eventReader); 

//TODO: proper error + stream handling 
2

Ich würde vorschlagen, eine sehr einfache XSLT-Transformation zu schreiben, um den leeren Inhalt von jenen spezifischen Elementen zu entfernen, die das Problem verursachen (zB nur die HashLine-Elemente). Fügen Sie dann einen Verarbeitungsschritt ein, bevor Sie die Daten über JAXB übergeben, indem Sie TransformerFactory, Transformer usw. verwenden, wodurch die Daten mit der XSLT-Transformation "bereinigt" werden. Sie könnten verschiedene Arten von Reinigungslogik im XSLT hinzufügen, wenn Sie im Quell-XML andere Strukturen finden, die nicht von JAXB unterstützt werden.

+0

Ich glaube nicht, dass es so viel ist, dass das Dokument nicht JAXB-freundlich ist, da es nicht validierungsfreundlich ist. Sie haben wahrscheinlich recht, dass es besser ist, auf bestimmte Elemente zu zielen. Ich könnte mir vorstellen, dass Sie mit DOM/XPath etwas Ähnliches machen könnten, aber es wäre nicht so elegant wie XSLT. – McDowell

+0

Ja, ich denke, ein deklarativer Ansatz wird in diesem Fall nie ein Imperativ sein. Wenn Ihre XML-Dokumente nicht dem Schema entsprechen, müssen Sie dies beheben, bevor Sie sie durch den Validator führen. XSLT ist in dieser Hinsicht gut. – skaffman

+0

beide Antworten funktionierten. Aber ich habe zuerst die andere Antwort versucht, da sie ein paar nette Beispielcodes enthielt. Später wechselte ich aus verschiedenen Gründen zu dieser Lösung. – DragonFax

Verwandte Themen