Ausgabe
Derzeit arbeite ich an einer Funktion, bei der XML analysiert wird, die wir von einem anderen Produkt erhalten. Ich habe mich entschieden, einige Tests mit einigen tatsächlichen Kundendaten durchzuführen, und es sieht so aus, als ob das andere Produkt Eingaben von Benutzern zulässt, die als ungültig betrachtet werden sollten. Wie auch immer, ich muss noch versuchen, einen Weg zu finden, es zu analysieren. Wir verwenden javax.xml.parsers.DocumentBuilder
und ich erhalte einen Fehler bei der Eingabe, der wie folgt aussieht.
<xml>
...
<description>Example:Description:<THIS-IS-PART-OF-DESCRIPTION></description>
...
</xml>
Wie Sie sehen können, enthält die Beschreibung ein scheinbar ungültiges Tag ( <THIS-IS-PART-OF-DESCRIPTION>
). Nun, dieses Beschreibungs-Tag ist als Blatt-Tag bekannt und sollte keine verschachtelten Tags enthalten. Unabhängig davon ist dies immer noch ein Problem und führt zu einer AusnahmeDocumentBuilder.parse(...)
Ich weiß, dass dies ungültiges XML ist, aber es ist vorhersehbar ungültig. Irgendwelche Ideen, wie man solche Eingaben analysieren kann?
Lösung
Dieses „XML“ ist schlimmer als ungültig – es ist nicht wohlgeformt ; siehe Wohlgeformtes vs. gültiges XML .
Eine informelle Einschätzung der Vorhersehbarkeit der Überschreitungen hilft nicht weiter. Diese Textdaten sind kein XML. Keine konformen XML-Tools oder -Bibliotheken können Ihnen bei der Verarbeitung helfen.
Optionen, am wünschenswertesten zuerst:
-
Lassen Sie den Anbieter das Problem auf seiner Seite beheben. Fordern Sie wohlgeformtes XML. (Technisch gesehen ist der Ausdruck wohlgeformtes XML überflüssig, kann aber zur Hervorhebung nützlich sein.)
-
Verwenden Sie einen toleranten Markup-Parser , um das Problem vor dem Parsen als XML zu bereinigen:
-
Eigenständig: xmlstarlet verfügt über robuste Wiederherstellungs- und Reparaturfunktionen . Gutschrift: RomanPerekhrest
xmlstarlet fo -o -R -H -D bad.xml 2>/dev/null
-
Standalone und C/C++: HTML Tidy funktioniert auch mit XML. Taggle ist eine Portierung von TagSoup nach C++.
-
Python: Beautiful Soup basiert auf Python. Siehe Hinweise im Abschnitt Unterschiede zwischen Parsern . Siehe auch Antworten auf diese Frage für weitere Vorschläge zum Umgang mit nicht wohlgeformtem Markup in Python, einschließlich insbesondere der Option von lxml
recover=True
. Siehe auch diese Antwort , umcodecs.EncodedFile()
zu erfahren, wie Sie illegale Zeichen bereinigen können. -
Java: TagSoup und JSoup konzentrieren sich auf HTML.
FilterInputStream
kann für die Vorverarbeitung der Bereinigung verwendet werden . -
.NETZ:
- XmlReaderSettings.CheckCharacters kann deaktiviert werden, um Probleme mit illegalen XML-Zeichen zu umgehen.
- @jdweng-Hinweise ,
XmlReaderSettings.ConformanceLevel
die festgelegt werden können,
ConformanceLevel.Fragment
damit wohlgeformte geparste XML-EntitätenXmlReader
gelesen werden können, denen ein Stammelement fehlt. - @jdweng berichtet auch, dass
XmlReader.ReadToFollowing()
dies manchmal zur Umgehung von XML- Syntaktproblemen verwendet werden kann , beachten Sie jedoch die Warnung zu Regelverstößen in Nr. 3 unten. Microsoft.Language.Xml.XMLParser
soll „fehlertolerant“ sein.
-
Go: Auf setzen
Decoder.Strict
,false
wie in diesem Beispiel von @chuckx gezeigt . -
PHP: Siehe DOMDocument::$recover und libxml_use_internal_errors(true) . Siehe schönes Beispiel hier .
-
Rubin: Nokogiri unterstützt die „ Sanfte Wohlgeformtheit “.
-
R: Siehe htmlTreeParse() für fehlertolerantes Markup-Parsing in R.
-
Perl: Siehe XML::Liberal , ein „superliberaler XML-Parser, der fehlerhaftes XML analysiert“.
-
-
Verarbeiten Sie die Daten als Text manuell mit einem Texteditor oder programmgesteuert mit Zeichen-/String-Funktionen. Dies programmgesteuert zu tun kann schwierig bis unmöglich sein, da das, was vorhersehbar erscheint, es oft nicht ist – Regelverstöße sind selten an Regeln gebunden .
-
Verwenden Sie bei Fehlern aufgrund ungültiger Zeichen Regex, um ungültige Zeichen zu entfernen/ersetzen:
- PHP:
preg_replace('/[^\x{0009}\x{000a}\x{000d}\x{0020}-\x{D7FF}\x{E000}-\x{FFFD}]+/u', ' ', $s);
- Rubin:
string.tr("^\u{0009}\u{000a}\u{000d}\u{0020}-\u{D7FF}\u{E000}-\u{FFFD}", ' ')
- Javascript:
inputStr.replace(/[^\x09\x0A\x0D\x20-\xFF\x85\xA0-\uD7FF\uE000-\uFDCF\uFDE0-\uFFFD]/gm, '')
- PHP:
-
Verwenden Sie für kaufmännische Und- Zeichen Regex, um Übereinstimmungen mit
&
: credit: blhsin , demo zu ersetzen&(?!(?:#\d+|#x[0-9a-f]+|\w+);)
-
Beachten Sie, dass die obigen regulären Ausdrücke keine Kommentare oder CDATA-Abschnitte berücksichtigen.
Beantwortet von – kjhughes
Antwort geprüft von – Candace Johnson (FixError Volunteer)