Ashish
Ashish

Reputation: 1567

An invalid XML character (Unicode: 0xc) was found

Parsing an XML file using the Java DOM parser results in:

[Fatal Error] os__flag_8c.xml:103:135: An invalid XML character (Unicode: 0xc) was found in the element content of the document.
org.xml.sax.SAXParseException: An invalid XML character (Unicode: 0xc) was found in the element content of the document.
    at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(Unknown Source)
    at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(Unknown Source)
    at javax.xml.parsers.DocumentBuilder.parse(Unknown Source)

Upvotes: 50

Views: 215041

Answers (12)

eda
eda

Reputation: 139

org.xml.sax.SAXParseException contains existing invalid character line number and column number.

For catching and logging this details:

try {
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();

        DocumentBuilder builder = factory.newDocumentBuilder();
        InputStream inputStream = new FileInputStream(path);
        Document document = builder.parse(inputStream);

    } catch (SAXParseException e) {
        logger.error("Xml parse error, cause of the line number: {}, column number: {} .", e.getLineNumber(), e.getColumnNumber(), e);
    }

Upvotes: 0

Martin Husted Hartvig
Martin Husted Hartvig

Reputation: 54

I just used this project, and found it very handy: https://github.com/rwitzel/streamflyer

Using the InvalidXmlCharacterModifier, as the documentation says.

Like this example:

public String stripNonValidXMLCharacters(final String in) {

  final Modifier modifier = new InvalidXmlCharacterModifier("",
    InvalidXmlCharacterModifier.XML_10_VERSION);

  final ModifyingReader modifyingReader = 
         new ModifyingReader(new StringReader(in), modifier);

  return IOUtils.toString(modifyingReader);
}

Upvotes: 1

Topera
Topera

Reputation: 12389

On UTF-8, all the codes on these ranges are not allowed, for XML 1.0:

  • 0..8
  • B..C
  • E..1F
  • D800..DFFF
  • FFFE..FFFF

A regex that can remove then is:

text.replaceAll('[\\x{0}-\\x{8}]|[\\x{B}-\\x{C}]|[\\x{E}-\\x{1F}]|[\\x{D800}-\\x{DFFF}]|[\\x{FFFE}-\\x{FFFF}]', "")

Note: if you are working with XML 1.1, you also need to remove these intervals:

  • 7F..84
  • 86..9F

Refs:

Upvotes: 4

P. Wolff
P. Wolff

Reputation: 41

Today, I've got a similar error:

Servlet.service() for servlet [remoting] in context with path [/***] threw exception [Request processing failed; nested exception is java.lang.RuntimeException: buildDocument failed.] with root cause org.xml.sax.SAXParseException; lineNumber: 19; columnNumber: 91; An invalid XML character (Unicode: 0xc) was found in the value of attribute "text" and element is "label".


After my first encouter with the error, I had re-typed the entire line by hand, so that there was no way for a special character to creep in, and Notepad++ didn't show any non-printable characters (black on white), nevertheless I got the same error over and over.

When I looked up what I've done different than my predecessors, it turned out it was one additional space just before the closing /> (as I've heard was recommended for older parsers, but it shouldn't make any difference anyway, by the XML standards):

<label text="this label's text" layout="cell 0 0, align left" />

When I removed the space:

<label text="this label's text" layout="cell 0 0, align left"/>

everything worked just fine.


So it's definitely a misleading error message.

Upvotes: 0

Jerry Miller
Jerry Miller

Reputation: 981

All of these answers seem to assume that the user is generating the bad XML, rather than receiving it from gSOAP, which should know better!

Upvotes: 0

BatBold
BatBold

Reputation: 19

For people who are reading byte array into String and trying to convert to object with JAXB, you can add "iso-8859-1" encoding by creating String from byte array like this:

String JAXBallowedString= new String(byte[] input, "iso-8859-1");

This would replace the conflicting byte to single-byte encoding which JAXB can handle. Obviously this solution is only to parse the xml.

Upvotes: 0

Vadim Zin4uk
Vadim Zin4uk

Reputation: 1806

You can filter all 'invalid' chars with a custom FilterReader class:

public class InvalidXmlCharacterFilter extends FilterReader {

    protected InvalidXmlCharacterFilter(Reader in) {
        super(in);
    }

    @Override
    public int read(char[] cbuf, int off, int len) throws IOException {
        int read = super.read(cbuf, off, len);
        if (read == -1) return read;

        for (int i = off; i < off + read; i++) {
            if (!XMLChar.isValid(cbuf[i])) cbuf[i] = '?';
        }
        return read;
    }
}

And run it like this:

InputStream fileStream = new FileInputStream(xmlFile);
Reader reader = new BufferedReader(new InputStreamReader(fileStream, charset));
InvalidXmlCharacterFilter filter = new InvalidXmlCharacterFilter(reader);
InputSource is = new InputSource(filter);
xmlReader.parse(is);

Upvotes: 4

Komal
Komal

Reputation: 200

Whenever invalid xml character comes xml, it gives such error. When u open it in notepad++ it look like VT, SOH,FF like these are invalid xml chars. I m using xml version 1.0 and i validate text data before entering it in database by pattern

Pattern p = Pattern.compile("[^\u0009\u000A\u000D\u0020-\uD7FF\uE000-\uFFFD\u10000-\u10FFF]+"); 
retunContent = p.matcher(retunContent).replaceAll("");

It will ensure that no invalid special char will enter in xml

Upvotes: 8

Dima
Dima

Reputation: 1065

public String stripNonValidXMLCharacters(String in) {
    StringBuffer out = new StringBuffer(); // Used to hold the output.
    char current; // Used to reference the current character.

    if (in == null || ("".equals(in))) return ""; // vacancy test.
    for (int i = 0; i < in.length(); i++) {
        current = in.charAt(i); // NOTE: No IndexOutOfBoundsException caught here; it should not happen.
        if ((current == 0x9) ||
            (current == 0xA) ||
            (current == 0xD) ||
            ((current >= 0x20) && (current <= 0xD7FF)) ||
            ((current >= 0xE000) && (current <= 0xFFFD)) ||
            ((current >= 0x10000) && (current <= 0x10FFFF)))
            out.append(current);
    }
    return out.toString();
}    

Upvotes: 23

Mohit
Mohit

Reputation: 1755

I faced a similar issue where XML was containing control characters. After looking into the code, I found that a deprecated class,StringBufferInputStream, was used for reading string content.

http://docs.oracle.com/javase/7/docs/api/java/io/StringBufferInputStream.html

This class does not properly convert characters into bytes. As of JDK 1.1, the preferred way to create a stream from a string is via the StringReader class.

I changed it to ByteArrayInputStream and it worked fine.

Upvotes: 0

jishi
jishi

Reputation: 24634

There are a few characters that are dissallowed in XML documents, even when you encapsulate data in CDATA-blocks.

If you generated the document you will need to entity encode it or strip it out. If you have an errorneous document, you should strip away these characters before trying to parse it.

See dolmens answer in this thread: Invalid Characters in XML

Where he links to this article: http://www.w3.org/TR/xml/#charsets

Basically, all characters below 0x20 is disallowed, except 0x9 (TAB), 0xA (CR?), 0xD (LF?)

Upvotes: 50

J&#246;rn Horstmann
J&#246;rn Horstmann

Reputation: 34034

The character 0x0C is be invalid in XML 1.0 but would be a valid character in XML 1.1. So unless the xml file specifies the version as 1.1 in the prolog it is simply invalid and you should complain to the producer of this file.

Upvotes: 7

Related Questions