XML Parser Recovery Behavior After Well-Formedness Errors Lacks Standardization
0 reputation · 26 Jul 2024, 20:03 UTC
0 reputation · 26 Jul 2024, 20:03 UTC
The XML 1.0 specification (Fifth Edition, Section 2.1) mandates that a well-formedness error is fatal and the processor must not continue normal processing. Despite this requirement, widely used parsers including Xerces, libxml2, and MSXML provide non-standard recovery modes that attempt to continue parsing after such errors.
Applications that need to process potentially malformed XML from external sources often enable these recovery flags (for example, Xerces continueAfterFatalError or libxml2 XML_PARSE_RECOVER) to avoid complete parse failure. However, the resulting document trees, error reporting, and heuristic decisions differ significantly between implementations, and no standard API or configuration exists to control recovery behavior.
This implementation-defined variance creates portability risk when switching parsers or upgrading parser versions, and recovery modes may produce trees that do not correspond to any well-formed XML document, potentially violating downstream validation or business logic.
There is no standardized way to continue parsing after a well‑formedness error; the XML 1.0 spec treats such errors as fatal. Consequently, portable recovery depends on either rejecting malformed input outright or wrapping each parser in a layer that normalizes its output.
continueAfterFatalError), libxml2 (XML_PARSE_RECOVER), and MSXML (via setProperty with SAXProperty::http://apache.org/xml/features/continue-after-fatal-error or DOM flags) each expose a non‑standard recovery flag that allows the parser to attempt recovery.The spec deliberately forbids continuation to guarantee deterministic error handling. Vendors added proprietary recovery modes to improve usability for tolerant applications, but because the spec provides no guidance, each vendor implemented its own heuristics, leading to divergence.
xmllint --noout or an equivalent SAX‑based validator) and reject the input if it fails.# Example using xmllint (libxml2) and Xerces C++ command line xmllint --noout --recover test-bad.xml 2>&1 xerces-c -continueAfterFatalError test-bad.xml 2>&1 # Compare exit codes and any produced output files
Repeat with MSXML via a short script that sets the appropriate property and checks the parse result.
If your application can tolerate a partial or altered tree (e.g., for best‑effort data extraction), please confirm whether such a tolerance exists; otherwise, the safe path is to reject malformed input outright.
Use comments to ask for clarification. Post a solution as an answer.
33,775 reputation · 27 Jul 2024, 06:32 UTC
To build on the discussion of portability risks, it is important to note that recovery heuristics often involve "guessing" where a missing closing tag should reside. Because these heuristics are not standardized, different parsers may nest subsequent elements differently within the resulting DOM tree.
When testing for behavioral divergence, a reliable method is to use a document with a missing closing tag for a mid-level element. Compare the resulting parent-child relationships across parsers:
This structural variance can lead to silent logic failures in downstream XPath queries or CSS selectors that rely on a specific hierarchy, even if the parser technically "recovered" the document.