SAXException [1] is thrown because character encoding errors are fatal errors (as defined by the XML spec) and SAX says fatal errors are reported to the application using that exception.
Specifically XML 1.0 [2] says: "It is a fatal error when an XML processor encounters an entity with an encoding that it is unable to process. It is a fatal error if an XML entity is determined (via default, encoding declaration, or higher-level protocol) to be in a certain encoding but contains byte sequences that are not legal in that encoding. Specifically, it is a fatal error if an entity encoded in UTF-8 contains any irregular code unit sequences, as defined in Unicode 3.1 [Unicode3]. Unless an encoding is determined by a higher-level protocol, it is also a fatal error if an XML entity contains no encoding declaration and its content is not legal UTF-8 or UTF-16." [1] http://issues.apache.org/jira/browse/XERCESJ-913 [2] http://www.w3.org/TR/2006/REC-xml-20060816/#charencoding Michael Glavassevich XML Parser Development IBM Toronto Lab E-mail: [EMAIL PROTECTED] E-mail: [EMAIL PROTECTED] Stanimir Stamenkov <[EMAIL PROTECTED]> wrote on 09/13/2006 10:46:41 AM: > Even before I've been trying to find a convenient way to identify > whether a parsing has stopped because of a character encoding > problem. I'm attaching a sample (the main application entry is in > "ParsingText.java"): it tries to parse an "UTF-8" encoding > mislabeled document which is actually encoded using "ISO-8859-1" > ("charter.xml"). Upon encountering he first non-ASCII character the > reading fails and the parser throws |SAXParseException|... while I'm > more convinced I should get an |IOException| type. > > The problem is I have to detect specific exception messages to guess > the problem is the one I'm looking for and those messages could > easily change between parser versions and are surely different > between different parser implementations. I think it would be nice > if the whatever relevant underlying exception is initialized as > |cause| of the |SAXParseException| being thrown so one can detect > the problem in more Java natural way. > > Something I've noticed when I provide a custom input stream of data > ("TestStream.java"), when the reading from that stream throws > |java.io.CharConversionException| it is not propagated as > |IOException| but again a |SAXParseException| is thrown with its > message containing the original exception message. > > I've noticed the optimized Xerces readers already throw > |java.io.CharConversionException| > (|org.apache.xerces.impl.io.MalformedByteSequenceException|) upon > character encoding problem and while I don't know why it is not > propagated as general |IOException| (do you know why?), if they are > initialized as |cause| of the |SAXParseException| being thrown I > could do something like: > > XMLReader xmlReader; > InputSource input; > ... > try { > xmlReader.parse(input); > } catch (CharConversionException ex) { > /* encoding problem detected */ > } catch (IOException ex) { > ... > } catch (SAXException ex) { > if (ex.getCause() instanceof CharConversionException) { > /* encoding problem detected */ > } > } > > Then in interactive environment I could present a user with > convenient options to retry the operation specifying different > source encoding, for example. > > Has this been considered before? > > -- > Stanimir > package net.example; > > import java.io.IOException; > import java.net.URL; > > import javax.xml.parsers.ParserConfigurationException; > import javax.xml.parsers.SAXParserFactory; > > import org.xml.sax.ErrorHandler; > import org.xml.sax.InputSource; > import org.xml.sax.SAXException; > import org.xml.sax.SAXParseException; > import org.xml.sax.XMLReader; > > public class ParsingTest { > > public static void main(String[] args) { > SAXParserFactory spf = SAXParserFactory.newInstance(); > XMLReader xmlReader; > try { > xmlReader = spf.newSAXParser().getXMLReader(); > } catch (SAXException ex) { > ex.printStackTrace(); > return; > } catch (ParserConfigurationException ex) { > ex.printStackTrace(); > return; > } > > ErrorHandler errorHandler = new ErrorHandler() { > public void warning(SAXParseException exception) { > System.err.println("[warning] " + exception); > } > public void fatalError(SAXParseException exception) { > System.err.println("[fatal] " + exception); > } > public void error(SAXParseException exception) { > System.err.println("[error] " + exception); > } > }; > xmlReader.setErrorHandler(errorHandler); > > URL source = ParsingTest.class.getResource("charter.xml"); > InputSource input = new InputSource(source.toExternalForm()); > //new InputSource(new TestStream()); > > try { > xmlReader.parse(input); > } catch (IOException ex) { > System.err.println(); > ex.printStackTrace(); > } catch (SAXException ex) { > System.err.println(); > ex.printStackTrace(); > } > } > > } > <?xml version="1.0" encoding="UTF-8" ?> > <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US"> > <head> > <title>Xerces Project Charter</title> > <link rel="source" href=" http://xerces.apache.org/xerces2-j/charter.html" > title="Xerces Project Charter" /> > </head> > <body> > > <h1>Xerces Project Charter</h1> > <p> > The following charter applies to all Xerces projects.</p> > > <h2>Introduction</h2> > <p> > Apache Xerces est un projet de collaboration de développement de logiciel > consacré à fournir robuste, complet, à la commercial-qualité, et > librement aux > analyseurs disponibles de XML et aux technologies étroitement liées sur une > grande variété de plateformes soutenant plusieurs langues. Ce projet est > contrôlé dans le monde entier en coopération avec les divers individus (les > experts indépendants et compagnie-filiales), qui emploient l'Internet pour > communiquer, projeter, et développer le logiciel de XML et la documentation > relative.</p> > <p> > Cette charte décrit brièvement la mission, l'histoire, l'organisation, et les > processus du projet.</p> > > <h2>Mission</h2> > <p> > Apache Xerces existe pour favoriser l'utilisation de XML. Nous regardons XML > comme paradigme contraignant qui structure des données comme information, > facilitant de ce fait l'échange, la transformation, et la présentation de la > connaissance. La capacité de transformer des données brutes en information > utilisable a le grand potentiel d'améliorer la fonctionnalité et > l'utilisation > des systèmes d'information. Nous avons l'intention d'établir librement des > analyseurs disponibles de XML et des technologies étroitement liées afin > d'engendrer de telles améliorations.</p> > <p> > Les analyseurs d'Apache Xerces soutiennent APIs standard (formel, defait, ou > proposé). Ils sont conçus pour être rendement élevé, fiable, et facile à > employer. Pour faciliter la mise en communication facile des idées entre les > langues, les api soutenus devraient être aussi semblables comme > possible, donné > les contraintes des langues et des architectures existantes. Des analyseurs > d'Apache Xerces devraient également être conçus pour travailler efficacement > avec l'autre Apache projette qu'affaire avec XML autant que possible.</p> > <p> > Nous croyons que la meilleure manière à autre ces buts est en ayant des > individus et les sociétés collaborent sur la meilleure infrastructure, APIs, > code, examinant, et des cycles de dégagement. Les composants doivent être > fournisseur neutre et utilisable comme composants de noyau pour tous.</p> > <p> > Afin de réaliser une architecture logique entre les analyseurs > d'Apache Xerces > et d'autres composants et applications, des normes (formelles ou de > fait) seront > employées autant que possible pour des protocoles et APIs. Le cas > échéant, des > expériences et des leçons appriss sera rétroagi aux organismes de > normalisation > dans un effort d'aider au développement de ces normes. Nous encouragerons > également l'innovation de nouveaux protocoles, d'APIs, et de > composants afin de > semer de nouveaux concepts pas encore définis par des normes.</p> > > <div>...</div> > > </body> > </html> > package net.example; > > import java.io.ByteArrayInputStream; > import java.io.CharConversionException; > import java.io.IOException; > import java.io.InputStream; > import java.io.UnsupportedEncodingException; > > > public class TestStream extends InputStream { > > private static final String SOURCE = > "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>" > + "<document>" > + "<title>Sample Document</title>" > + "<paragraph>" > + "..."; > > private InputStream mContent; > > public TestStream() { > try { > mContent = new ByteArrayInputStream(SOURCE.getBytes("UTF-8")); > } catch (UnsupportedEncodingException ueex) { > throw new AssertionError(ueex); > } > } > > public int read() throws IOException { > int ch = mContent.read(); > if (ch == -1) { > throw new MyException(); > } > return ch; > } > > } > > > class MyException extends CharConversionException { > //extends IOException { > > private static final long serialVersionUID = 1L; > > MyException() { > super("My Custom Exception"); > } > > } > > > --------------------------------------------------------------------- > To unsubscribe, e-mail: [EMAIL PROTECTED] > For additional commands, e-mail: [EMAIL PROTECTED] --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]