PDA

View Full Version : JDOM - XML Parser - Validierung schlägt fehl



CarstenS
14-12-09, 10:18
Hallo zusammen,

grundsätzlich läuft das Programm zuverlässig durch.

Ich lade per FTP gezippte XML Files täglich runter und lese die darin befindlichen XML-Files über JDOM aus und aktualisiere meine Datenbanken.

Leider sind teilweise die XML-Files nicht valide. So kann es vorkommen, dass in einzelnen Tags im Inhalt ein "&" anstatt dem richtigen "&" steht.
Der zweite Fehler in den XML-Files ist, dass manchmal fehlerhafte Unicode Zeichen enthalten sind. Ich denke es sind Zeilenumbrüche (Fehlerzeichen ist 0x0B) (<- müsste chr(13) entsprechen, nach meinem Verständnis sollte aber 0x0B 12 entsprechen?...)

Da ich keinerlei Zugriff auf die XML-Files habe, stehe ich vor einem kleinen Dilemma. Zwar kann ich heruntergeladene XML-Files per Hand korrigieren, nachdem das Programm normalerweise per cronjob läuft, ist das nicht gerade eine schöne Sache.

Folgender Code macht in diesen Situationen Fehler:
SAXBuilder builder=new SAXBuilder(false);
Document document = builder.build(this.datXml);

Bekomme ich nun solche schlechten XML-Files (ZIP-Files) steigt er mir bei zweiter Zeile aus bzw. nach der ersten Zeile, soweit ich hier Validierung zulasse. (datXML ist ein InputStream aus dem ZIPfile heraus)

Wo ich im Moment keine Klarheit habe:
Ist es möglich meinem XML-Parser zu sagen, dass er diese zwei Fehler übersehen soll und weiter machen soll. Kann ich hier eine Fehlertoleranz einbauen und wenn ja wie?

Ich würde gerne verhindern, den Inputstream erst in einen temporären File zu kopieren und den File dann über String Operationen zu "berichtigen" und dann an den Parser zu übergeben.

Bin für jegliche Vorschläge dankbar.

Gruß Carsten

BenderD
15-12-09, 07:26
... sieht mir nicht danach aus, dass der Parser meckert, der reicht wahrscheinlich nur die Exception des InputStreams hoch, der falsches Character encoding moniert (müsste im printStackTrace zu sehen sein). Angeben kann man das Character encoding, wenn man einen FileInputStream verwendet und über diesen einen InputStreamReader legt.
Allen möglichen Quatsch kann man natürlich durchgehen lassen, wenn man einen eigenen InputStream schreibt (extends auf das jetzt real verwendete Objekt) und dort die read Methoden überschreibt und darin selber filtert.

Dieter Bender


Hallo zusammen,

grundsätzlich läuft das Programm zuverlässig durch.

Ich lade per FTP gezippte XML Files täglich runter und lese die darin befindlichen XML-Files über JDOM aus und aktualisiere meine Datenbanken.

Leider sind teilweise die XML-Files nicht valide. So kann es vorkommen, dass in einzelnen Tags im Inhalt ein "&" anstatt dem richtigen "&amp;" steht.
Der zweite Fehler in den XML-Files ist, dass manchmal fehlerhafte Unicode Zeichen enthalten sind. Ich denke es sind Zeilenumbrüche (Fehlerzeichen ist 0x0B) (<- müsste chr(13) entsprechen, nach meinem Verständnis sollte aber 0x0B 12 entsprechen?...)

Da ich keinerlei Zugriff auf die XML-Files habe, stehe ich vor einem kleinen Dilemma. Zwar kann ich heruntergeladene XML-Files per Hand korrigieren, nachdem das Programm normalerweise per cronjob läuft, ist das nicht gerade eine schöne Sache.

Folgender Code macht in diesen Situationen Fehler:
SAXBuilder builder=new SAXBuilder(false);
Document document = builder.build(this.datXml);

Bekomme ich nun solche schlechten XML-Files (ZIP-Files) steigt er mir bei zweiter Zeile aus bzw. nach der ersten Zeile, soweit ich hier Validierung zulasse. (datXML ist ein InputStream aus dem ZIPfile heraus)

Wo ich im Moment keine Klarheit habe:
Ist es möglich meinem XML-Parser zu sagen, dass er diese zwei Fehler übersehen soll und weiter machen soll. Kann ich hier eine Fehlertoleranz einbauen und wenn ja wie?

Ich würde gerne verhindern, den Inputstream erst in einen temporären File zu kopieren und den File dann über String Operationen zu "berichtigen" und dann an den Parser zu übergeben.

Bin für jegliche Vorschläge dankbar.

Gruß Carsten

Fuerchau
15-12-09, 07:41
X'0B' ist chr(11) und nicht chr(12).
Normalerweise sind diese Zeichen nicht relevant sondern dienen nur der optischen Darstellung.
Insoweit gebe ich Dieter Recht, dass es beim Lesen auf das Encoding ankommt.
Dieses steht meistens direkt am Anfang der Datei mit z.B. Encoding="iso 8859-1".
Entsprechend muss der Datenstrom gelesen werden, ansonsten wird binär gelesen und das passt ggf. gar nicht.

Ich helfe mir meist damit, dass ich die ersten Zeilen selber lese, das Encoding suche und einen entsprechenden Textencoder wähle bevor ich die Datei an den Parser weitergebe.

Alternativ kann man ja auch erst mal als Default 8859-1 wählen, das Encoding-Attribut auslesen und bei Abweichung halt noch einmal mit einem anderen Encoder lesen.

CarstenS
15-12-09, 08:55
... sieht mir nicht danach aus, dass der Parser meckert, der reicht wahrscheinlich nur die Exception des InputStreams hoch, der falsches Character encoding moniert (müsste im printStackTrace zu sehen sein).

Leider ist dem nicht so, es scheint dass hier Xerces erst meckert.

StackTrace:

org.jdom.input.JDOMParseException: Error on line 9: Im Elementinhalt des Dokuments wurde ein ungültiges XML-Zeichen (Unicode: 0xb) gefunden.
at org.jdom.input.SAXBuilder.build(SAXBuilder.java:53 3)
at org.jdom.input.SAXBuilder.build(SAXBuilder.java:86 5)
at st2009.schmitz.OnixParser.getDieProdukte(OnixParse r.java:23)
at st2009.schmitz.OnixAktualisierung.main(OnixAktuali sierung.java:77)
Caused by: org.xml.sax.SAXParseException: Im Elementinhalt des Dokuments wurde ein ungültiges XML-Zeichen (Unicode: 0xb) gefunden.
at org.apache.xerces.util.ErrorHandlerWrapper.createS AXParseException(Unknown Source)
at org.apache.xerces.util.ErrorHandlerWrapper.fatalEr ror(Unknown Source)
at org.apache.xerces.impl.XMLErrorReporter.reportErro r(Unknown Source)
at org.apache.xerces.impl.XMLErrorReporter.reportErro r(Unknown Source)
at org.apache.xerces.impl.XMLScanner.reportFatalError (Unknown Source)
at org.apache.xerces.impl.XMLDocumentFragmentScannerI mpl$FragmentContentDispatcher.dispatch(Unknown Source)
at org.apache.xerces.impl.XMLDocumentFragmentScannerI mpl.scanDocument(Unknown Source)
at org.apache.xerces.parsers.XML11Configuration.parse (Unknown Source)
at org.apache.xerces.parsers.XML11Configuration.parse (Unknown Source)
at org.apache.xerces.parsers.XMLParser.parse(Unknown Source)
at org.apache.xerces.parsers.AbstractSAXParser.parse( Unknown Source)
at org.apache.xerces.jaxp.SAXParserImpl$JAXPSAXParser .parse(Unknown Source)
at org.jdom.input.SAXBuilder.build(SAXBuilder.java:51 8)
... 3 more
Caused by: org.xml.sax.SAXParseException: Im Elementinhalt des Dokuments wurde ein ungültiges XML-Zeichen (Unicode: 0xb) gefunden.
at org.apache.xerces.util.ErrorHandlerWrapper.createS AXParseException(Unknown Source)
at org.apache.xerces.util.ErrorHandlerWrapper.fatalEr ror(Unknown Source)
at org.apache.xerces.impl.XMLErrorReporter.reportErro r(Unknown Source)
at org.apache.xerces.impl.XMLErrorReporter.reportErro r(Unknown Source)
at org.apache.xerces.impl.XMLScanner.reportFatalError (Unknown Source)
at org.apache.xerces.impl.XMLDocumentFragmentScannerI mpl$FragmentContentDispatcher.dispatch(Unknown Source)
at org.apache.xerces.impl.XMLDocumentFragmentScannerI mpl.scanDocument(Unknown Source)
at org.apache.xerces.parsers.XML11Configuration.parse (Unknown Source)
at org.apache.xerces.parsers.XML11Configuration.parse (Unknown Source)
at org.apache.xerces.parsers.XMLParser.parse(Unknown Source)
at org.apache.xerces.parsers.AbstractSAXParser.parse( Unknown Source)
at org.apache.xerces.jaxp.SAXParserImpl$JAXPSAXParser .parse(Unknown Source)
at org.jdom.input.SAXBuilder.build(SAXBuilder.java:51 8)
at org.jdom.input.SAXBuilder.build(SAXBuilder.java:86 5)
at st2009.schmitz.OnixParser.getDieProdukte(OnixParse r.java:23)
at st2009.schmitz.OnixAktualisierung.main(OnixAktuali sierung.java:77)
Caused by: org.xml.sax.SAXParseException: Im Elementinhalt des Dokuments wurde ein ungültiges XML-Zeichen (Unicode: 0xb) gefunden.
at org.apache.xerces.util.ErrorHandlerWrapper.createS AXParseException(Unknown Source)
at org.apache.xerces.util.ErrorHandlerWrapper.fatalEr ror(Unknown Source)
at org.apache.xerces.impl.XMLErrorReporter.reportErro r(Unknown Source)
at org.apache.xerces.impl.XMLErrorReporter.reportErro r(Unknown Source)
at org.apache.xerces.impl.XMLScanner.reportFatalError (Unknown Source)
at org.apache.xerces.impl.XMLDocumentFragmentScannerI mpl$FragmentContentDispatcher.dispatch(Unknown Source)
at org.apache.xerces.impl.XMLDocumentFragmentScannerI mpl.scanDocument(Unknown Source)
at org.apache.xerces.parsers.XML11Configuration.parse (Unknown Source)
at org.apache.xerces.parsers.XML11Configuration.parse (Unknown Source)
at org.apache.xerces.parsers.XMLParser.parse(Unknown Source)
at org.apache.xerces.parsers.AbstractSAXParser.parse( Unknown Source)
at org.apache.xerces.jaxp.SAXParserImpl$JAXPSAXParser .parse(Unknown Source)
at org.jdom.input.SAXBuilder.build(SAXBuilder.java:51 8)
at org.jdom.input.SAXBuilder.build(SAXBuilder.java:86 5)
at st2009.schmitz.OnixParser.getDieProdukte(OnixParse r.java:23)
at st2009.schmitz.OnixAktualisierung.main(OnixAktuali sierung.java:77)
Exception in thread "main" java.lang.NullPointerException
at st2009.schmitz.OnixAktualisierung.main(OnixAktuali sierung.java:79)
Die Nullpointer Exception kommt von einem Produkt Array, der durch das fehlerhafte Parsen keine Produkte enthält. Nachdem in einer Schleife auf die Länge des Arrays geprüft wird ohne Null abzufangen, steigt er dann aus. Eigentlich ein zu korrigierender Fehler, aber erst mal drin belassen, damit mir das Programm aussteigt. Es handelt sich um mehrere tägliche Update Files, die chronologisch eingelesen werden müssen.



Angeben kann man das Character encoding, wenn man einen FileInputStream verwendet und über diesen einen InputStreamReader legt.
Allen möglichen Quatsch kann man natürlich durchgehen lassen, wenn man einen eigenen InputStream schreibt (extends auf das jetzt real verwendete Objekt) und dort die read Methoden überschreibt und darin selber filtert.

Dieter Bender

Ich glaube, ich werde diesen Weg einschlagen und versuchen auf dieser Ebene "vorzufiltern". Damit sollte ich dann auch das Entitätenproblem mit dem "&" wegbekommen können.


X'0B' ist chr(11) und nicht chr(12).
Normalerweise sind diese Zeichen nicht relevant sondern dienen nur der optischen Darstellung.

Ähm ja, da hast Du natürlich recht, ich sollte mir die Hex Notation noch mal genauer anschauen... Demnach kann es vorher jedes nicht verwertbare Zeichen gewesen sein.


Insoweit gebe ich Dieter Recht, dass es beim Lesen auf das Encoding ankommt.
Dieses steht meistens direkt am Anfang der Datei mit z.B. Encoding="iso 8859-1".
Entsprechend muss der Datenstrom gelesen werden, ansonsten wird binär gelesen und das passt ggf. gar nicht.

Ich helfe mir meist damit, dass ich die ersten Zeilen selber lese, das Encoding suche und einen entsprechenden Textencoder wähle bevor ich die Datei an den Parser weitergebe.

Alternativ kann man ja auch erst mal als Default 8859-1 wählen, das Encoding-Attribut auslesen und bei Abweichung halt noch einmal mit einem anderen Encoder lesen.

Als Encoding ist UTF-8 im XML-File angegeben, ich glaube da wird sich in diesen Fällen aber nicht dran gehalten... Ich werde mal mit dem Encoding ein bisschen rumspielen.

Vielen Dank schon mal für Eure Tips, jetzt werde ich mich mal wieder ans Coding machen. Wies ausgeht werde ich dann im neuen Jahr berichten, hab erst mal "Wichtigeres" zu tun. Im Normalfall läufts ja durch.

BenderD
15-12-09, 09:24
... Herr Google war wieder mal schlauer...
[jdom-interest] JDOM Exception: invalid XML character ( Unico d e: 0xb) found (http://www.jdom.org/pipermail/jdom-interest/2002-July/010297.html)
Extensible Markup Language (XML) 1.0 (Second Edition) (http://www.w3.org/TR/2000/REC-xml-20001006#charsets)
Es handelt sich wohl um legale UTF-8 Zeichen, die aber in XML Dokumenten nicht vorkommen dürfen, was ein Parser wohl in jedem Fall zu prüfen hat.
Kosequenz aus dem Ganzen: da geht an einem eigenen Filter nix vorbei, wenn der Ersteller keinen ordentlichen Parser benutzt (klingt nach AS/400 und XPAT, oder was ähnlich krankes)

D*B


Leider ist dem nicht so, es scheint dass hier Xerces erst meckert.

CarstenS
15-12-09, 09:58
Vielen Dank BenderD für die zwei Links, das werde ich dann mal abarbeiten, ist sehr hilfreich.

CarstenS
14-01-10, 07:59
Sodala vielen Dank für die Tips. Ich filtere jetzt vor und das Ganze läuft nun immer durch. Allerdings hat der Lieferant der XML-Files jetzt auch umgestellt und es werden seit meiner letzten "Beschwerde" keine nicht wohlgeformten XML-Files mehr bereit gestellt.
Mir kanns nur recht sein.