We are using StAXON (due to its performance via StAX processing) to parse json input which contains colon(:) as element name. Colon is valid element name in JSON but while parsing via StAXON we are getting exception (XMLStreamException).
It works if I use namespaceSeparator as '\0', like new JsonXMLConfigBuilder().namespaceSeparator(Character.MIN_VALUE). But this just changes the namespace separator.
My Question/Doubt:
Is it safe to do this? Are there chances of getting issue(s)
Is there a way to ignore colon while parsing (reading/writing) JSON?
Is there any other alternative to StAXON to parse JSON based on events like StAX parsing is done for XML.
Sample Input : {"cust:person":{"name":"John Doe","phone":"555-1111"}}
Exception
Exception in thread "main" javax.xml.stream.XMLStreamException: Unbound prefix: cust
at de.odysseus.staxon.base.AbstractXMLStreamScope.verify(AbstractXMLStreamScope.java:212)
at de.odysseus.staxon.base.AbstractXMLStreamScope.setStartTagClosed(AbstractXMLStreamScope.java:234)
at de.odysseus.staxon.base.AbstractXMLStreamReader.ensureStartTagClosed(AbstractXMLStreamReader.java:191)
at de.odysseus.staxon.base.AbstractXMLStreamReader.readStartElementTag(AbstractXMLStreamReader.java:272)
at de.odysseus.staxon.json.JsonXMLStreamReader.readStartElementTag(JsonXMLStreamReader.java:93)
at de.odysseus.staxon.json.JsonXMLStreamReader.consume(JsonXMLStreamReader.java:202)
at de.odysseus.staxon.json.JsonXMLStreamReader.consume(JsonXMLStreamReader.java:153)
at de.odysseus.staxon.json.JsonXMLStreamReader.consume(JsonXMLStreamReader.java:183)
at de.odysseus.staxon.json.JsonXMLStreamReader.consume(JsonXMLStreamReader.java:153)
at de.odysseus.staxon.json.JsonXMLStreamReader.consume(JsonXMLStreamReader.java:183)
at de.odysseus.staxon.base.AbstractXMLStreamReader.initialize(AbstractXMLStreamReader.java:216)
at de.odysseus.staxon.json.JsonXMLStreamReader.initialize(JsonXMLStreamReader.java:87)
at de.odysseus.staxon.json.JsonXMLStreamReader.(JsonXMLStreamReader.java:78)
at de.odysseus.staxon.json.JsonXMLInputFactory.createXMLStreamReader(JsonXMLInputFactory.java:150)
at de.odysseus.staxon.json.JsonXMLInputFactory.createXMLStreamReader(JsonXMLInputFactory.java:45)
at JsonXml.main(JsonXml.java:27)
Thanks
Colon is a legal name character in case the parser is not namespace aware. You should be able to turn off namespace awareness on the underlying XMLInputFactory (don't know the details of StAXON).
It’s safe to do this but it’s probably not what you want. Since StAXON tries to treat JSON like XML, you should give the library what it wants: A namespace for the „cust“ prefix. Read about StAXON‘s conventions here.
To declare a namespace:
new JsonXMLConfigBuilder().namespaceMapping(„cust“, „http://example.com/ns/cust“)
Currently, I'm working on a feature that involves parsing XML that we receive from another product. I decided to run some tests against some actual customer data, and it looks like the other product is allowing input from users that should be considered invalid. Anyways, I still have to try and figure out a way to parse it. We're using javax.xml.parsers.DocumentBuilder and I'm getting an error on input that looks like the following.
<xml>
...
<description>Example:Description:<THIS-IS-PART-OF-DESCRIPTION></description>
...
</xml>
As you can tell, the description has what appears to be an invalid tag inside of it (<THIS-IS-PART-OF-DESCRIPTION>). Now, this description tag is known to be a leaf tag and shouldn't have any nested tags inside of it. Regardless, this is still an issue and yields an exception on DocumentBuilder.parse(...)
I know this is invalid XML, but it's predictably invalid. Any ideas on a way to parse such input?
That "XML" is worse than invalid – it's not well-formed; see Well Formed vs Valid XML.
An informal assessment of the predictability of the transgressions does not help. That textual data is not XML. No conformant XML tools or libraries can help you process it.
Options, most desirable first:
Have the provider fix the problem on their end. Demand well-formed XML. (Technically the phrase well-formed XML is redundant but may be useful for emphasis.)
Use a tolerant markup parser to cleanup the problem ahead of parsing as XML:
Standalone: xmlstarlet has robust recovering and repair capabilities credit: RomanPerekhrest
xmlstarlet fo -o -R -H -D bad.xml 2>/dev/null
Standalone and C/C++: HTML Tidy works with XML too. Taggle is a port of TagSoup to C++.
Python: Beautiful Soup is Python-based. See notes in the Differences between parsers section. See also answers to this question for more
suggestions for dealing with not-well-formed markup in Python,
including especially lxml's recover=True option.
See also this answer for how to use codecs.EncodedFile() to cleanup illegal characters.
Java: TagSoup and JSoup focus on HTML. FilterInputStream can be used for preprocessing cleanup.
.NET:
XmlReaderSettings.CheckCharacters can
be disabled to get past illegal XML character problems.
#jdweng notes that XmlReaderSettings.ConformanceLevel can be set to
ConformanceLevel.Fragment so that XmlReader can read XML Well-Formed Parsed Entities lacking a root element.
#jdweng also reports that XmlReader.ReadToFollowing() can sometimes
be used to work-around XML syntactical issues, but note
rule-breaking warning in #3 below.
Microsoft.Language.Xml.XMLParser is said to be “error-tolerant”.
Go: Set Decoder.Strict to false as shown in this example by #chuckx.
PHP: See DOMDocument::$recover and libxml_use_internal_errors(true). See nice example here.
Ruby: Nokogiri supports “Gentle Well-Formedness”.
R: See htmlTreeParse() for fault-tolerant markup parsing in R.
Perl: See XML::Liberal, a "super liberal XML parser that parses broken XML."
Process the data as text manually using a text editor or
programmatically using character/string functions. Doing this
programmatically can range from tricky to impossible as
what appears to be
predictable often is not -- rule breaking is rarely bound by rules.
For invalid character errors, use regex to remove/replace invalid characters:
PHP: preg_replace('/[^\x{0009}\x{000a}\x{000d}\x{0020}-\x{D7FF}\x{E000}-\x{FFFD}]+/u', ' ', $s);
Ruby: 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, '')
For ampersands, use regex to replace matches with &: credit: blhsin, demo
&(?!(?:#\d+|#x[0-9a-f]+|\w+);)
Note that the above regular expressions won't take comments or CDATA
sections into account.
A standard XML parser will NEVER accept invalid XML, by design.
Your only option is to pre-process the input to remove the "predictably invalid" content, or wrap it in CDATA, prior to parsing it.
The accepted answer is good advice, and contains very useful links.
I'd like to add that this, and many other cases of not-wellformed and/or DTD-invalid XML can be repaired using SGML, the ISO-standardized superset of HTML and XML. In your case, what works is to declare the bogus THIS-IS-PART-OF-DESCRIPTION element as SGML empty element and then use eg. the osx program (part of the OpenSP/OpenJade SGML package) to convert it to XML. For example, if you supply the following to osx
<!DOCTYPE xml [
<!ELEMENT xml - - ANY>
<!ELEMENT description - - ANY>
<!ELEMENT THIS-IS-PART-OF-DESCRIPTION - - EMPTY>
]>
<xml>
<description>blah blah
<THIS-IS-PART-OF-DESCRIPTION>
</description>
</xml>
it will output well-formed XML for further processing with the XML tools of your choice.
Note, however, that your example snippet has another problem in that element names starting with the letters xml or XML or Xml etc. are reserved in XML, and won't be accepted by conforming XML parsers.
IMO these cases should be solved by using JSoup.
Below is a not-really answer for this specific case, but found this on the web (thanks to inuyasha82 on Coderwall). This code bit did inspire me for another similar problem while dealing with malformed XMLs, so I share it here.
Please do not edit what is below, as it is as it on the original website.
The XML format, requires to be valid a unique root element declared in the document.
So for example a valid xml is:
<root>
<element>...</element>
<element>...</element>
</root>
But if you have a document like:
<element>...</element>
<element>...</element>
<element>...</element>
<element>...</element>
This will be considered a malformed XML, so many xml parsers just throw an Exception complaining about no root element. Etc.
In this example there is a solution on how to solve that problem and succesfully parse the malformed xml above.
Basically what we will do is to add programmatically a root element.
So first of all you have to open the resource that contains your "malformed" xml (i. e. a file):
File file = new File(pathtofile);
Then open a FileInputStream:
FileInputStream fis = new FileInputStream(file);
If we try to parse this stream with any XML library at that point we will raise the malformed document Exception.
Now we create a list of InputStream objects with three lements:
A ByteIputStream element that contains the string: <root>
Our FileInputStream
A ByteInputStream with the string: </root>
So the code is:
List<InputStream> streams =
Arrays.asList(
new ByteArrayInputStream("<root>".getBytes()),
fis,
new ByteArrayInputStream("</root>".getBytes()));
Now using a SequenceInputStream, we create a container for the List created above:
InputStream cntr =
new SequenceInputStream(Collections.enumeration(str));
Now we can use any XML Parser library, on the cntr, and it will be parsed without any problem. (Checked with Stax library);
How do you determine whether a Document object in Java contains valid XML. Is this checked when the object is constructed?
I can't appear to find any information on this in
http://docs.oracle.com/javase/1.5.0/docs/api/org/w3c/dom/Document.html
How do you determine whether you have a valid XML Document without using external libraries?
Note: I received this Document object by parsing from an input stream with a DOM XML parser.
Use the Java DOM API. It can handle any valid XML document. A valid document will give no exception. You need no external libraries for DOM.
In case of an error the exception message looks like this:
[Fatal Error] MyXMLFile.xml:6:2: The end-tag for element type "lastname" must end with a '>' delimiter.
The end-tag for element type "lastname" must end with a '>' delimiter.
BUILD SUCCESSFUL (total time: 0 seconds)
I want to validate an xml file against it schema. Once the validation is completed I want to remove any invalid data and save this invalid data into a new file. I can perfom the validation, just stuck on the removing and saving invalid data into new file.
I take back everything I just wrote. ... :) You can get the node you need using the Current Element Node property at Exception time, it seems.
Element curElement = (Element)validator.getProperty("http://apache.org/xml/properties/dom/current-element-node");
Because the Schema is defined via Xerces, I think this will work. See http://xerces.apache.org/xerces2-j/properties.html#dom.current-element-node .
There is more explanation in the answer at How can I get more information on an invalid DOM element through the Validator? .
I need to validate XML Schema Instance (XSD) documents which are programmatically generated so I'm using the following Java snippet, which works fine:
SchemaFactory factory = SchemaFactory.newInstance(
XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema xsdSchema = factory.newSchema( // Reads URL every time...
new URL("http://www.w3.org/2001/XMLSchema.xsd"));
Validator xsdValidator = xsdSchema.newValidator();
xsdValidator.validate(new StreamSource(schemaInstanceStream));
However, when I save the XML Schema definition file locally and refer to it this way:
Schema schema = factory.newSchema(
new File("test/xsd/XMLSchema.xsd"));
It fails with the following exception:
org.xml.sax.SAXParseException: schema_reference.4: Failed to read schema document 'file:/Users/foo/bar/test/xsd/XMLSchema.xsd', because 1) could not find the document; 2) the document could not be read; 3) the root element of the document is not <xsd:schema>.
I've ensured that the file exists and is readable by doing exists() and canRead() assertions on the File object. I've also downloaded the file with a couple different utilities (web browser, wget) to ensure that there is no corruption.
Any idea why I can validate XSD instance documents when I generate the schema from the HTTP URL but I get the above exception when trying to generate from a local file with the same contents?
[Edit]
To elaborate, I've tried multiple forms of factory.newSchema(...) using Readers and InputStreams (instead of the File directly) and still get exactly the same error. Moreover, I've dumped the file contents before using it or the various input streams to ensure it's the right one. Quite vexing.
Full Answer
It turns out that there are three additional files referenced by XML Schema which must be also stored locally and XMLSchema.xsd contains an import statement whose schemaLocation attribute must be changed. Here are the files that must be saved in the same directory:
XMLSchema.xsd - change schemaLocation to "xml.xsd" in the "import" element for XML Namespace.
XMLSchema.dtd - as is.
datatypes.dtd - as is.
xml.xsd - as is.
Thanks to #Blaise Doughan and #Tomasz Nurkiewicz for their hints.
I assume you are trying to load XMLSchema.xsd. Please also download XMLSchema.dtd and datatypes.dtd and put them in the same directory. This should push you a little bit further.
UPDATE
Is XMLSchema.xsd importing any other schemas by relative paths that are not on the local file systen?
Your relative path may not be correct wrt your working directory. Try entering a fully qualified path to eliminate the possibility that the file can not be found.
org.xml.sax.SAXParseException: schema_reference.4: Failed to read
schema document 'file:/Users/foo/bar/test/xsd/XMLSchema.xsd', because
1) could not find the document; 2) the document could not be read; 3)
the root element of the document is not .