You are viewing a plain text version of this content. The canonical link for it is here.
Posted to rpc-dev@xml.apache.org by mp...@apache.org on 2003/01/18 14:40:03 UTC
cvs commit: xml-rpc/src/java/uk/co/wilson/xml MinML.java
mpoeschl 2003/01/18 05:40:03
Modified: src/java/uk/co/wilson/xml MinML.java
Log:
Update to MinML 1.7
Revision Changes Path
1.3 +768 -762 xml-rpc/src/java/uk/co/wilson/xml/MinML.java
Index: MinML.java
===================================================================
RCS file: /home/cvs/xml-rpc/src/java/uk/co/wilson/xml/MinML.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- MinML.java 14 Nov 2001 15:10:56 -0000 1.2
+++ MinML.java 18 Jan 2003 13:40:03 -0000 1.3
@@ -1,762 +1,768 @@
-// Copyright (c) 2000, 2001 The Wilson Partnership.
-// All Rights Reserved.
-// @(#)MinML.java, 1.6, 11th November 2001
-// Author: John Wilson - tug@wilson.co.uk
-
-package uk.co.wilson.xml;
-
-/*
-Copyright (c) 2000, 2001 John Wilson (tug@wilson.co.uk).
-All rights reserved.
-Redistribution and use in source and binary forms,
-with or without modification, are permitted provided
-that the following conditions are met:
-
-Redistributions of source code must retain the above
-copyright notice, this list of conditions and the
-following disclaimer.
-
-Redistributions in binary form must reproduce the
-above copyright notice, this list of conditions and
-the following disclaimer in the documentation and/or
-other materials provided with the distribution.
-
-All advertising materials mentioning features or use
-of this software must display the following acknowledgement:
-
-This product includes software developed by John Wilson.
-The name of John Wilson may not be used to endorse or promote
-products derived from this software without specific prior
-written permission.
-
-THIS SOFTWARE IS PROVIDED BY JOHN WILSON ``AS IS'' AND ANY
-EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JOHN WILSON
-BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
-TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
-IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
-OF THE POSSIBILITY OF SUCH DAMAGE
-*/
-
-import java.io.InputStream;
-import java.io.Reader;
-import java.io.Writer;
-import java.io.InputStreamReader;
-import java.io.IOException;
-
-import java.net.URL;
-
-import java.util.Locale;
-import java.util.Vector;
-import java.util.Stack;
-import java.util.EmptyStackException;
-
-import uk.org.xml.sax.Parser;
-import uk.org.xml.sax.DocumentHandler;
-
-import org.xml.sax.EntityResolver;
-import org.xml.sax.DTDHandler;
-import org.xml.sax.ErrorHandler;
-import org.xml.sax.Locator;
-import org.xml.sax.InputSource;
-import org.xml.sax.AttributeList;
-import org.xml.sax.SAXException;
-import org.xml.sax.SAXParseException;
-
-public class MinML implements Parser, Locator, DocumentHandler, ErrorHandler {
- public static final int endStartName = 0;
- public static final int emitStartElement = 1;
- public static final int emitEndElement = 2;
- public static final int emitCharacters = 3;
- public static final int emitCharactersSave = 4;
- public static final int saveAttributeName = 5;
- public static final int saveAttributeValue = 6;
- public static final int startComment = 7;
- public static final int endComment = 8;
- public static final int incLevel = 9;
- public static final int decLevel = 10;
- public static final int startCDATA = 11;
- public static final int endCDATA = 12;
- public static final int processCharRef = 13;
- public static final int writeCdata = 14;
- public static final int exitParser = 15;
- public static final int parseError = 16;
- public static final int discardAndChange = 17;
- public static final int discardSaveAndChange = 18;
- public static final int saveAndChange = 19;
- public static final int change = 20;
-
- public static final int inSkipping = 0;
- public static final int inSTag = 1;
- public static final int inPossiblyAttribute = 2;
- public static final int inNextAttribute = 3;
- public static final int inAttribute = 4;
- public static final int inAttribute1 = 5;
- public static final int inAttributeValue = 6;
- public static final int inAttributeQuoteValue = 7;
- public static final int inAttributeQuotesValue = 8;
- public static final int inETag = 9;
- public static final int inETag1 = 10;
- public static final int inMTTag = 11;
- public static final int inTag = 12;
- public static final int inTag1 = 13;
- public static final int inPI = 14;
- public static final int inPI1 = 15;
- public static final int inPossiblySkipping = 16;
- public static final int inCharData = 17;
- public static final int inCDATA = 18;
- public static final int inCDATA1 = 19;
- public static final int inComment =20;
- public static final int inDTD = 21;
-
- public MinML(final int initialBufferSize, final int bufferIncrement) {
- this.initialBufferSize = initialBufferSize;
- this.bufferIncrement = bufferIncrement;
- }
-
- public MinML() {
- this(256, 128);
- }
-
- public void parse(final Reader in) throws SAXException, IOException {
- final Vector attributeNames = new Vector();
- final Vector attributeValues = new Vector();
-
- final AttributeList attrs = new AttributeList() {
- public int getLength() {
- return attributeNames.size();
- }
-
- public String getName(final int i) {
- return (String)attributeNames.elementAt(i);
- }
-
- public String getType(final int i) {
- return "CDATA";
- }
-
- public String getValue(final int i) {
- return (String)attributeValues.elementAt(i);
- }
-
- public String getType(final String name) {
- return "CDATA";
- }
-
- public String getValue(final String name) {
- final int index = attributeNames.indexOf(name);
-
- return (index == -1) ? null : (String)attributeValues.elementAt(index);
- }
- };
-
- final MinMLBuffer buffer = new MinMLBuffer(in);
- int currentChar = 0, charCount = 0;
- int level = 0;
- int mixedContentLevel = -1;
- String elementName = null;
- String state = operands[inSkipping];
-
- this.lineNumber = 1;
- this.columnNumber = 0;
-
- try {
- while(true) {
- charCount++;
-
- //
- // this is to try and make the loop a bit faster
- // currentChar = buffer.read(); is simpler but is a bit slower.
- //
- currentChar = (buffer.nextIn == buffer.lastIn) ? buffer.read() : buffer.chars[buffer.nextIn++];
-
- final int transition;
-
- if (currentChar > ']') {
- transition = state.charAt(14);
- } else {
- final int charClass = charClasses[currentChar + 1];
-
- if (charClass == -1) fatalError("Document contains illegal control character with value " + currentChar, this.lineNumber, this.columnNumber);
-
- if (charClass == 12) {
- if (currentChar == '\r') {
- currentChar = '\n';
- charCount = -1;
- }
-
- if (currentChar == '\n') {
- if (charCount == 0) continue; // preceeded by '\r' so ignore
-
- if (charCount != -1) charCount = 0;
-
- this.lineNumber++;
- this.columnNumber = 0;
- }
- }
-
- transition = state.charAt(charClass);
- }
-
- this.columnNumber++;
-
- String operand = operands[transition >>> 8];
-
- switch (transition & 0XFF) {
- case endStartName:
- // end of start element name
- elementName = buffer.getString();
- if (currentChar != '>' && currentChar != '/') break; // change state to operand
- // drop through to emit start element (we have no attributes)
-
- case emitStartElement:
- // emit start element
-
- final Writer newWriter = this.extDocumentHandler.startElement(elementName, attrs,
- (this.tags.empty()) ?
- this.extDocumentHandler.startDocument(buffer)
- :
- buffer.getWriter());
-
- buffer.pushWriter(newWriter);
- this.tags.push(elementName);
-
- attributeValues.removeAllElements();
- attributeNames.removeAllElements();
-
- if (mixedContentLevel != -1) mixedContentLevel++;
-
- if (currentChar != '/') break; // change state to operand
-
- // <element/> drop through
-
- case emitEndElement:
- // emit end element
-
- try {
- final String begin = (String)this.tags.pop();
-
- buffer.popWriter();
- elementName = buffer.getString();
-
- if (currentChar != '/' && !elementName.equals(begin)) {
- fatalError("end tag </" + elementName + "> does not match begin tag <" + begin + ">",
- this.lineNumber, this.columnNumber);
- } else {
- this.documentHandler.endElement(begin);
-
- if (this.tags.empty()) {
- this.documentHandler.endDocument();
- return;
- }
- }
- }
- catch (final EmptyStackException e) {
- fatalError("end tag at begining of document", this.lineNumber, this.columnNumber);
- }
-
- if (mixedContentLevel != -1 && --mixedContentLevel == 0)
- operand = operands[inCharData];
-
- break; // change state to operand
-
- case emitCharacters:
- // emit characters
-
- buffer.flush();
- break; // change state to operand
-
- case emitCharactersSave:
- // emit characters and save current character
-
- if (mixedContentLevel == -1) mixedContentLevel = 0;
-
- buffer.flush();
-
- buffer.saveChar((char)currentChar);
-
- break; // change state to operand
-
- case saveAttributeName:
- // save attribute name
-
- attributeNames.addElement(buffer.getString());
- break; // change state to operand
-
- case saveAttributeValue:
- // save attribute value
-
- attributeValues.addElement(buffer.getString());
- break; // change state to operand
-
- case startComment:
- // change state if we have found "<!--"
-
- if (buffer.read() != '-') continue; // not "<!--"
-
- break; // change state to operand
-
- case endComment:
- // change state if we find "-->"
-
- if ((currentChar = buffer.read()) == '-') {
- // deal with the case where we might have "------->"
- while ((currentChar = buffer.read()) == '-');
-
- if (currentChar == '>') break; // end of comment, change state to operand
- }
-
- continue; // not end of comment, don't change state
-
- case incLevel:
-
- level++;
-
- break;
-
- case decLevel:
-
- if (level == 0) break; // outer level <> change state
-
- level--;
-
- continue; // in nested <>, don't change state
-
- case startCDATA:
- // change state if we have found "<![CDATA["
-
- if (buffer.read() != 'C') continue; // don't change state
- if (buffer.read() != 'D') continue; // don't change state
- if (buffer.read() != 'A') continue; // don't change state
- if (buffer.read() != 'T') continue; // don't change state
- if (buffer.read() != 'A') continue; // don't change state
- if (buffer.read() != '[') continue; // don't change state
- break; // change state to operand
-
- case endCDATA:
- // change state if we find "]]>"
-
- if ((currentChar = buffer.read()) == ']') {
- // deal with the case where we might have "]]]]]]]>"
- while ((currentChar = buffer.read()) == ']') buffer.write(']');
-
- if (currentChar == '>') break; // end of CDATA section, change state to operand
-
- buffer.write(']');
- }
-
- buffer.write(']');
- buffer.write(currentChar);
- continue; // not end of CDATA section, don't change state
-
- case processCharRef:
- // process character entity
-
- int crefState = 0;
-
- currentChar = buffer.read();
-
- while (true) {
- if ("#amp;&pos;'quot;\"gt;>lt;<".charAt(crefState) == currentChar) {
- crefState++;
-
- if (currentChar == ';') {
- buffer.write("#amp;&pos;'quot;\"gt;>lt;<".charAt(crefState));
- break;
-
- } else if (currentChar == '#') {
- final int radix;
-
- currentChar = buffer.read();
-
- if (currentChar == 'x') {
- radix = 16;
- currentChar = buffer.read();
- } else {
- radix = 10;
- }
-
- int charRef = Character.digit((char)currentChar, radix);
-
- while (true) {
- currentChar = buffer.read();
-
- final int digit = Character.digit((char)currentChar, radix);
-
- if (digit == -1) break;
-
- charRef = (char)((charRef * radix) + digit);
- }
-
- if (currentChar == ';' && charRef != -1) {
- buffer.write(charRef);
- break;
- }
-
- fatalError("invalid Character Entitiy", this.lineNumber, this.columnNumber);
- } else {
- currentChar = buffer.read();
- }
- } else {
- crefState = ("\u0001\u000b\u0006\u00ff\u00ff\u00ff\u00ff\u00ff\u00ff\u00ff\u00ff" +
-// # a m p ; & p o s ; '
-// 0 1 2 3 4 5 6 7 8 9 a
- "\u0011\u00ff\u00ff\u00ff\u00ff\u00ff\u0015\u00ff\u00ff\u00ff" +
-// q u o t ; " g t ; >
-// b b d e f 10 11 12 13 14
- "\u00ff\u00ff\u00ff").charAt(crefState);
-// l t ;
-// 15 16 17
-
- if (crefState == 255) fatalError("invalid Character Entitiy", this.lineNumber, this.columnNumber);
- }
- }
-
- break;
-
- case parseError:
- // report fatal error
-
- fatalError(operand, this.lineNumber, this.columnNumber);
- // drop through to exit parser
-
- case exitParser:
- // exit parser
-
- return;
-
- case writeCdata:
- // write character data
- // this will also write any skipped whitespace
-
- buffer.write(currentChar);
- break; // change state to operand
-
- case discardAndChange:
- // throw saved characters away and change state
-
- buffer.reset();
- break; // change state to operand
-
- case discardSaveAndChange:
- // throw saved characters away, save character and change state
-
- buffer.reset();
- // drop through to save character and change state
-
- case saveAndChange:
- // save character and change state
-
- buffer.saveChar((char)currentChar);
- break; // change state to operand
-
- case change:
- // change state to operand
-
- break; // change state to operand
- }
-
- state = operand;
- }
- }
- catch (final IOException e) {
- this.errorHandler.fatalError(new SAXParseException(e.toString(), null, null, this.lineNumber, this.columnNumber, e));
- }
- finally {
- this.errorHandler = this;
- this.documentHandler = this.extDocumentHandler = this;
- this.tags.removeAllElements();
- }
- }
-
- public void parse(final InputSource source) throws SAXException, IOException {
- if (source.getCharacterStream() != null)
- parse(source.getCharacterStream());
- else if (source.getByteStream() != null)
- parse(new InputStreamReader(source.getByteStream()));
- else
- parse(new InputStreamReader(new URL(source.getSystemId()).openStream()));
- }
-
- public void parse(final String systemId) throws SAXException, IOException {
- parse(new InputSource(systemId));
- }
-
- public void setLocale(final Locale locale) throws SAXException {
- throw new SAXException("Not supported");
- }
-
- public void setEntityResolver(final EntityResolver resolver) {
- // not supported
- }
-
- public void setDTDHandler(final DTDHandler handler) {
- // not supported
- }
-
- public void setDocumentHandler(final org.xml.sax.DocumentHandler handler) {
- this.documentHandler = (handler == null) ? this : handler;
- this.extDocumentHandler = this;
- }
-
- public void setDocumentHandler(final DocumentHandler handler) {
- this.documentHandler = this.extDocumentHandler = (handler == null) ? this : handler;
- this.documentHandler.setDocumentLocator(this);
- }
-
- public void setErrorHandler(final ErrorHandler handler) {
- this.errorHandler = (handler == null) ? this : handler;
- }
-
- public void setDocumentLocator(final Locator locator) {
- }
-
- public void startDocument() throws SAXException {
- }
-
- public Writer startDocument(final Writer writer) throws SAXException {
- this.documentHandler.startDocument();
- return writer;
- }
-
- public void endDocument() throws SAXException {
- }
-
- public void startElement(final String name, final AttributeList attributes) throws SAXException {
- }
-
- public Writer startElement(final String name, final AttributeList attributes, final Writer writer)
- throws SAXException
- {
- this.documentHandler.startElement(name, attributes);
- return writer;
- }
-
- public void endElement(final String name) throws SAXException {
- }
-
- public void characters(final char ch[], final int start, final int length) throws SAXException {
- }
-
- public void ignorableWhitespace(final char ch[], final int start, final int length) throws SAXException {
- }
-
- public void processingInstruction(final String target, final String data) throws SAXException {
- }
-
- public void warning(final SAXParseException e) throws SAXException {
- }
-
- public void error(final SAXParseException e) throws SAXException {
- }
-
- public void fatalError(final SAXParseException e) throws SAXException {
- throw e;
- }
-
- public String getPublicId() {
- return "";
- }
-
-
- public String getSystemId() {
- return "";
- }
-
- public int getLineNumber () {
- return this.lineNumber;
- }
-
- public int getColumnNumber () {
- return this.columnNumber;
- }
-
- private void fatalError(final String msg, final int lineNumber, final int columnNumber) throws SAXException {
- this.errorHandler.fatalError(new SAXParseException(msg, null, null, lineNumber, columnNumber));
- }
-
- private class MinMLBuffer extends Writer {
- public MinMLBuffer(final Reader in) {
- this.in = in;
- }
-
- public void close() throws IOException {
- flush();
- }
-
- public void flush() throws IOException {
- try {
- _flush();
- if (writer != this) writer.flush();
- }
- finally {
- flushed = true;
- }
- }
-
- public void write(final int c) throws IOException {
- written = true;
- chars[count++] = (char)c;
- }
-
- public void write(final char[] cbuf, final int off, final int len) throws IOException {
- written = true;
- System.arraycopy(cbuf, off, chars, count, len);
- count += len;
- }
-
- public void saveChar(final char c) {
- written = false;
- chars[count++] = c;
- }
-
- public void pushWriter(final Writer writer) {
- MinML.this.tags.push(this.writer);
-
- this.writer = (writer == null) ? this : writer;
-
- flushed = written = false;
- }
-
- public Writer getWriter() {
- return writer;
- }
-
- public void popWriter() throws IOException {
- try {
- if (!flushed && writer != this) writer.flush();
- }
- finally {
- writer = (Writer)MinML.this.tags.pop();
- flushed = written = false;
- }
- }
-
- public String getString() {
- final String result = new String(chars, 0, count);
-
- count = 0;
- return result;
- }
-
- public void reset() {
- count = 0;
- }
-
- public int read() throws IOException {
- if (nextIn == lastIn) {
- if (count != 0) {
- if (written) {
- _flush();
- } else if (count >= (chars.length - MinML.this.bufferIncrement)) {
- final char[] newChars = new char[chars.length + MinML.this.bufferIncrement];
-
- System.arraycopy(chars, 0, newChars, 0, count);
- chars = newChars;
- }
- }
-
- final int numRead = in.read(chars, count, chars.length - count);
-
- if (numRead == -1) return -1;
-
- nextIn = count;
- lastIn = count + numRead;
- }
-
- return chars[nextIn++];
- }
-
- private void _flush() throws IOException {
- if (count != 0) {
- try {
- if (writer == this) {
- try {
- MinML.this.documentHandler.characters(chars, 0, count);
- }
- catch (final SAXException e) {
- throw new IOException(e.toString());
- }
- } else {
- writer.write(chars, 0, count);
- }
- }
- finally {
- count = 0;
- }
- }
- }
-
- private int nextIn = 0, lastIn = 0;
- private char[] chars = new char[MinML.this.initialBufferSize];
- private final Reader in;
- private int count = 0;
- private Writer writer = this;
- private boolean flushed = false;
- private boolean written = false;
- }
-
- private DocumentHandler extDocumentHandler = this;
- private org.xml.sax.DocumentHandler documentHandler = this;
- private ErrorHandler errorHandler = this;
- private final Stack tags = new Stack();
- private int lineNumber = 1;
- private int columnNumber = 0;
- private final int initialBufferSize;
- private final int bufferIncrement;
-
- private static final byte[] charClasses = {
- // EOF
- 13,
- // \t \n \r
- -1, -1, -1, -1, -1, -1, -1, -1, -1, 12, 12, -1, -1, 12, -1, -1,
- //
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- // SP ! " # $ % & ' ( ) * + , - . /
- 12, 8, 7, 14, 14, 14, 3, 6, 14, 14, 14, 14, 14, 11, 14, 2,
- // 0 1 2 3 4 5 6 7 8 9 : ; < = > ?
- 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 5, 1, 4,
- //
- 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
- // [ \ ]
- 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 9, 14, 10
- };
-
- private static final String[] operands = {
- "\u0d14\u1610\u1610\u1610\u1610\u1610\u1610\u1610\u1610\u1610\u1610\u1610\u0014\u000f\u1610",
- "\u1710\u1000\u0b00\u1710\u1710\u1710\u1710\u1710\u1710\u1710\u1710\u0113\u0200\u1810\u0113",
- "\u1710\u1001\u0b01\u1710\u1710\u1710\u1710\u1710\u1710\u1710\u1710\u1710\u0214\u1810\u0413",
- "\u1710\u1001\u0b01\u1710\u1910\u1910\u1910\u1910\u1910\u1910\u1910\u1910\u0314\u1810\u0413",
- "\u1910\u1910\u1910\u1910\u1910\u0605\u1910\u1910\u1910\u1910\u1910\u0413\u0514\u1810\u0413",
- "\u1910\u1910\u1910\u1910\u1910\u0605\u1910\u1910\u1910\u1910\u1910\u1910\u0514\u1810\u1910",
- "\u1a10\u1a10\u1a10\u1a10\u1a10\u1a10\u0714\u0814\u1a10\u1a10\u1a10\u1a10\u0614\u1810\u1a10",
- "\u0713\u0713\u0713\u070d\u0713\u0713\u0306\u0713\u0713\u0713\u0713\u0713\u0713\u1810\u0713",
- "\u0813\u0813\u0813\u080d\u0813\u0813\u0813\u0306\u0813\u0813\u0813\u0813\u0813\u1810\u0813",
- "\u1710\u1002\u1710\u1710\u1710\u1710\u1710\u1710\u1710\u1710\u1710\u0913\u0914\u1810\u0913",
- "\u1b10\u1b10\u0903\u1b10\u1b10\u1b10\u1b10\u1b10\u1214\u1b10\u1b10\u1b10\u1b10\u1810\u0104",
- "\u1710\u1014\u1710\u1710\u1710\u1710\u1710\u1710\u1710\u1710\u1710\u1710\u1710\u1810\u1710",
- "\u1710\u1c10\u0911\u1710\u0e11\u1710\u1710\u1710\u1211\u1710\u1710\u1710\u1710\u1810\u0112",
- "\u1710\u1c10\u0911\u1710\u0e11\u1710\u1710\u1710\u1211\u1710\u1710\u1710\u1710\u1810\u0112",
- "\u0e14\u0e14\u0e14\u0e14\u0f14\u0e14\u0e14\u0e14\u0e14\u0e14\u0e14\u0e14\u0e14\u1810\u0e14",
- "\u0e14\u0014\u0e14\u0e14\u0f14\u0e14\u0e14\u0e14\u0e14\u0e14\u0e14\u0e14\u0e14\u1810\u0e14",
- "\u0c14\u110e\u110e\u110d\u110e\u110e\u110e\u110e\u110e\u110e\u110e\u110e\u1013\u1810\u110e",
- "\u0a14\u110e\u110e\u110d\u110e\u110e\u110e\u110e\u110e\u110e\u110e\u110e\u110e\u1810\u110e",
- "\u1d10\u1d10\u1d10\u1d10\u1d10\u1d10\u1d10\u1d10\u1d10\u130b\u1d10\u1407\u1d10\u1810\u1514",
- "\u130e\u130e\u130e\u130e\u130e\u130e\u130e\u130e\u130e\u130e\u110c\u130e\u130e\u1810\u130e",
- "\u1414\u1414\u1414\u1414\u1414\u1414\u1414\u1414\u1414\u1414\u1414\u0008\u1414\u1810\u1414",
- "\u1509\n\u1514\u1514\u1514\u1514\u1514\u1514\u1514\u1514\u1514\u1514\u1514\u1810\u1514",
- "expected Element",
- "unexpected character in tag",
- "unexpected end of file found",
- "attribute name not followed by '='",
- "invalid attribute value",
- "expecting end tag",
- "empty tag",
- "unexpected character after <!"
- };
-}
+// Copyright (c) 2000, 2001 The Wilson Partnership.
+// All Rights Reserved.
+// @(#)MinML.java, 1.7, 18th November 2001
+// Author: John Wilson - tug@wilson.co.uk
+
+package uk.co.wilson.xml;
+
+/*
+Copyright (c) 2000, 2001 John Wilson (tug@wilson.co.uk).
+All rights reserved.
+Redistribution and use in source and binary forms,
+with or without modification, are permitted provided
+that the following conditions are met:
+
+Redistributions of source code must retain the above
+copyright notice, this list of conditions and the
+following disclaimer.
+
+Redistributions in binary form must reproduce the
+above copyright notice, this list of conditions and
+the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+All advertising materials mentioning features or use
+of this software must display the following acknowledgement:
+
+This product includes software developed by John Wilson.
+The name of John Wilson may not be used to endorse or promote
+products derived from this software without specific prior
+written permission.
+
+THIS SOFTWARE IS PROVIDED BY JOHN WILSON ``AS IS'' AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JOHN WILSON
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+OF THE POSSIBILITY OF SUCH DAMAGE
+*/
+
+import java.io.InputStream;
+import java.io.Reader;
+import java.io.Writer;
+import java.io.InputStreamReader;
+import java.io.IOException;
+
+import java.net.URL;
+
+import java.util.Locale;
+import java.util.Vector;
+import java.util.Stack;
+import java.util.EmptyStackException;
+
+import uk.org.xml.sax.Parser;
+import uk.org.xml.sax.DocumentHandler;
+
+import org.xml.sax.EntityResolver;
+import org.xml.sax.DTDHandler;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.Locator;
+import org.xml.sax.InputSource;
+import org.xml.sax.AttributeList;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+
+public class MinML implements Parser, Locator, DocumentHandler, ErrorHandler {
+ public static final int endStartName = 0;
+ public static final int emitStartElement = 1;
+ public static final int emitEndElement = 2;
+ public static final int possiblyEmitCharacters = 3;
+ public static final int emitCharacters = 4;
+ public static final int emitCharactersSave = 5;
+ public static final int saveAttributeName = 6;
+ public static final int saveAttributeValue = 7;
+ public static final int startComment = 8;
+ public static final int endComment = 9;
+ public static final int incLevel = 10;
+ public static final int decLevel = 11;
+ public static final int startCDATA = 12;
+ public static final int endCDATA = 13;
+ public static final int processCharRef = 14;
+ public static final int writeCdata = 15;
+ public static final int exitParser = 16;
+ public static final int parseError = 17;
+ public static final int discardAndChange = 18;
+ public static final int discardSaveAndChange = 19;
+ public static final int saveAndChange = 20;
+ public static final int change = 21;
+
+ public static final int inSkipping = 0;
+ public static final int inSTag = 1;
+ public static final int inPossiblyAttribute = 2;
+ public static final int inNextAttribute = 3;
+ public static final int inAttribute = 4;
+ public static final int inAttribute1 = 5;
+ public static final int inAttributeValue = 6;
+ public static final int inAttributeQuoteValue = 7;
+ public static final int inAttributeQuotesValue = 8;
+ public static final int inETag = 9;
+ public static final int inETag1 = 10;
+ public static final int inMTTag = 11;
+ public static final int inTag = 12;
+ public static final int inTag1 = 13;
+ public static final int inPI = 14;
+ public static final int inPI1 = 15;
+ public static final int inPossiblySkipping = 16;
+ public static final int inCharData = 17;
+ public static final int inCDATA = 18;
+ public static final int inCDATA1 = 19;
+ public static final int inComment =20;
+ public static final int inDTD = 21;
+
+ public MinML(final int initialBufferSize, final int bufferIncrement) {
+ this.initialBufferSize = initialBufferSize;
+ this.bufferIncrement = bufferIncrement;
+ }
+
+ public MinML() {
+ this(256, 128);
+ }
+
+ public void parse(final Reader in) throws SAXException, IOException {
+ final Vector attributeNames = new Vector();
+ final Vector attributeValues = new Vector();
+
+ final AttributeList attrs = new AttributeList() {
+ public int getLength() {
+ return attributeNames.size();
+ }
+
+ public String getName(final int i) {
+ return (String)attributeNames.elementAt(i);
+ }
+
+ public String getType(final int i) {
+ return "CDATA";
+ }
+
+ public String getValue(final int i) {
+ return (String)attributeValues.elementAt(i);
+ }
+
+ public String getType(final String name) {
+ return "CDATA";
+ }
+
+ public String getValue(final String name) {
+ final int index = attributeNames.indexOf(name);
+
+ return (index == -1) ? null : (String)attributeValues.elementAt(index);
+ }
+ };
+
+ final MinMLBuffer buffer = new MinMLBuffer(in);
+ int currentChar = 0, charCount = 0;
+ int level = 0;
+ int mixedContentLevel = -1;
+ String elementName = null;
+ String state = operands[inSkipping];
+
+ this.lineNumber = 1;
+ this.columnNumber = 0;
+
+ try {
+ while(true) {
+ charCount++;
+
+ //
+ // this is to try and make the loop a bit faster
+ // currentChar = buffer.read(); is simpler but is a bit slower.
+ //
+ currentChar = (buffer.nextIn == buffer.lastIn) ? buffer.read() : buffer.chars[buffer.nextIn++];
+
+ final int transition;
+
+ if (currentChar > ']') {
+ transition = state.charAt(14);
+ } else {
+ final int charClass = charClasses[currentChar + 1];
+
+ if (charClass == -1) fatalError("Document contains illegal control character with value " + currentChar, this.lineNumber, this.columnNumber);
+
+ if (charClass == 12) {
+ if (currentChar == '\r') {
+ currentChar = '\n';
+ charCount = -1;
+ }
+
+ if (currentChar == '\n') {
+ if (charCount == 0) continue; // preceeded by '\r' so ignore
+
+ if (charCount != -1) charCount = 0;
+
+ this.lineNumber++;
+ this.columnNumber = 0;
+ }
+ }
+
+ transition = state.charAt(charClass);
+ }
+
+ this.columnNumber++;
+
+ final String operand = operands[transition >>> 8];
+
+ switch (transition & 0XFF) {
+ case endStartName:
+ // end of start element name
+ elementName = buffer.getString();
+ if (currentChar != '>' && currentChar != '/') break; // change state to operand
+ // drop through to emit start element (we have no attributes)
+
+ case emitStartElement:
+ // emit start element
+
+ final Writer newWriter = this.extDocumentHandler.startElement(elementName, attrs,
+ (this.tags.empty()) ?
+ this.extDocumentHandler.startDocument(buffer)
+ :
+ buffer.getWriter());
+
+ buffer.pushWriter(newWriter);
+ this.tags.push(elementName);
+
+ attributeValues.removeAllElements();
+ attributeNames.removeAllElements();
+
+ if (mixedContentLevel != -1) mixedContentLevel++;
+
+ if (currentChar != '/') break; // change state to operand
+
+ // <element/> drop through
+
+ case emitEndElement:
+ // emit end element
+
+ try {
+ final String begin = (String)this.tags.pop();
+
+ buffer.popWriter();
+ elementName = buffer.getString();
+
+ if (currentChar != '/' && !elementName.equals(begin)) {
+ fatalError("end tag </" + elementName + "> does not match begin tag <" + begin + ">",
+ this.lineNumber, this.columnNumber);
+ } else {
+ this.documentHandler.endElement(begin);
+
+ if (this.tags.empty()) {
+ this.documentHandler.endDocument();
+ return;
+ }
+ }
+ }
+ catch (final EmptyStackException e) {
+ fatalError("end tag at begining of document", this.lineNumber, this.columnNumber);
+ }
+
+ if (mixedContentLevel != -1) --mixedContentLevel;
+
+ break; // change state to operand
+
+ case emitCharacters:
+ // emit characters
+
+ buffer.flush();
+ break; // change state to operand
+
+ case emitCharactersSave:
+ // emit characters and save current character
+
+ if (mixedContentLevel == -1) mixedContentLevel = 0;
+
+ buffer.flush();
+
+ buffer.saveChar((char)currentChar);
+
+ break; // change state to operand
+
+ case possiblyEmitCharacters:
+ // write any skipped whitespace if in mixed content
+
+ if (mixedContentLevel != -1) buffer.flush();
+ break; // change state to operand
+
+ case saveAttributeName:
+ // save attribute name
+
+ attributeNames.addElement(buffer.getString());
+ break; // change state to operand
+
+ case saveAttributeValue:
+ // save attribute value
+
+ attributeValues.addElement(buffer.getString());
+ break; // change state to operand
+
+ case startComment:
+ // change state if we have found "<!--"
+
+ if (buffer.read() != '-') continue; // not "<!--"
+
+ break; // change state to operand
+
+ case endComment:
+ // change state if we find "-->"
+
+ if ((currentChar = buffer.read()) == '-') {
+ // deal with the case where we might have "------->"
+ while ((currentChar = buffer.read()) == '-');
+
+ if (currentChar == '>') break; // end of comment, change state to operand
+ }
+
+ continue; // not end of comment, don't change state
+
+ case incLevel:
+
+ level++;
+
+ break;
+
+ case decLevel:
+
+ if (level == 0) break; // outer level <> change state
+
+ level--;
+
+ continue; // in nested <>, don't change state
+
+ case startCDATA:
+ // change state if we have found "<![CDATA["
+
+ if (buffer.read() != 'C') continue; // don't change state
+ if (buffer.read() != 'D') continue; // don't change state
+ if (buffer.read() != 'A') continue; // don't change state
+ if (buffer.read() != 'T') continue; // don't change state
+ if (buffer.read() != 'A') continue; // don't change state
+ if (buffer.read() != '[') continue; // don't change state
+ break; // change state to operand
+
+ case endCDATA:
+ // change state if we find "]]>"
+
+ if ((currentChar = buffer.read()) == ']') {
+ // deal with the case where we might have "]]]]]]]>"
+ while ((currentChar = buffer.read()) == ']') buffer.write(']');
+
+ if (currentChar == '>') break; // end of CDATA section, change state to operand
+
+ buffer.write(']');
+ }
+
+ buffer.write(']');
+ buffer.write(currentChar);
+ continue; // not end of CDATA section, don't change state
+
+ case processCharRef:
+ // process character entity
+
+ int crefState = 0;
+
+ currentChar = buffer.read();
+
+ while (true) {
+ if ("#amp;&pos;'quot;\"gt;>lt;<".charAt(crefState) == currentChar) {
+ crefState++;
+
+ if (currentChar == ';') {
+ buffer.write("#amp;&pos;'quot;\"gt;>lt;<".charAt(crefState));
+ break;
+
+ } else if (currentChar == '#') {
+ final int radix;
+
+ currentChar = buffer.read();
+
+ if (currentChar == 'x') {
+ radix = 16;
+ currentChar = buffer.read();
+ } else {
+ radix = 10;
+ }
+
+ int charRef = Character.digit((char)currentChar, radix);
+
+ while (true) {
+ currentChar = buffer.read();
+
+ final int digit = Character.digit((char)currentChar, radix);
+
+ if (digit == -1) break;
+
+ charRef = (char)((charRef * radix) + digit);
+ }
+
+ if (currentChar == ';' && charRef != -1) {
+ buffer.write(charRef);
+ break;
+ }
+
+ fatalError("invalid Character Entitiy", this.lineNumber, this.columnNumber);
+ } else {
+ currentChar = buffer.read();
+ }
+ } else {
+ crefState = ("\u0001\u000b\u0006\u00ff\u00ff\u00ff\u00ff\u00ff\u00ff\u00ff\u00ff" +
+// # a m p ; & p o s ; '
+// 0 1 2 3 4 5 6 7 8 9 a
+ "\u0011\u00ff\u00ff\u00ff\u00ff\u00ff\u0015\u00ff\u00ff\u00ff" +
+// q u o t ; " g t ; >
+// b b d e f 10 11 12 13 14
+ "\u00ff\u00ff\u00ff").charAt(crefState);
+// l t ;
+// 15 16 17
+
+ if (crefState == 255) fatalError("invalid Character Entitiy", this.lineNumber, this.columnNumber);
+ }
+ }
+
+ break;
+
+ case parseError:
+ // report fatal error
+
+ fatalError(operand, this.lineNumber, this.columnNumber);
+ // drop through to exit parser
+
+ case exitParser:
+ // exit parser
+
+ return;
+
+ case writeCdata:
+ // write character data
+ // this will also write any skipped whitespace
+
+ buffer.write(currentChar);
+ break; // change state to operand
+
+ case discardAndChange:
+ // throw saved characters away and change state
+
+ buffer.reset();
+ break; // change state to operand
+
+ case discardSaveAndChange:
+ // throw saved characters away, save character and change state
+
+ buffer.reset();
+ // drop through to save character and change state
+
+ case saveAndChange:
+ // save character and change state
+
+ buffer.saveChar((char)currentChar);
+ break; // change state to operand
+
+ case change:
+ // change state to operand
+
+ break; // change state to operand
+ }
+
+ state = operand;
+ }
+ }
+ catch (final IOException e) {
+ this.errorHandler.fatalError(new SAXParseException(e.toString(), null, null, this.lineNumber, this.columnNumber, e));
+ }
+ finally {
+ this.errorHandler = this;
+ this.documentHandler = this.extDocumentHandler = this;
+ this.tags.removeAllElements();
+ }
+ }
+
+ public void parse(final InputSource source) throws SAXException, IOException {
+ if (source.getCharacterStream() != null)
+ parse(source.getCharacterStream());
+ else if (source.getByteStream() != null)
+ parse(new InputStreamReader(source.getByteStream()));
+ else
+ parse(new InputStreamReader(new URL(source.getSystemId()).openStream()));
+ }
+
+ public void parse(final String systemId) throws SAXException, IOException {
+ parse(new InputSource(systemId));
+ }
+
+ public void setLocale(final Locale locale) throws SAXException {
+ throw new SAXException("Not supported");
+ }
+
+ public void setEntityResolver(final EntityResolver resolver) {
+ // not supported
+ }
+
+ public void setDTDHandler(final DTDHandler handler) {
+ // not supported
+ }
+
+ public void setDocumentHandler(final org.xml.sax.DocumentHandler handler) {
+ this.documentHandler = (handler == null) ? this : handler;
+ this.extDocumentHandler = this;
+ }
+
+ public void setDocumentHandler(final DocumentHandler handler) {
+ this.documentHandler = this.extDocumentHandler = (handler == null) ? this : handler;
+ this.documentHandler.setDocumentLocator(this);
+ }
+
+ public void setErrorHandler(final ErrorHandler handler) {
+ this.errorHandler = (handler == null) ? this : handler;
+ }
+
+ public void setDocumentLocator(final Locator locator) {
+ }
+
+ public void startDocument() throws SAXException {
+ }
+
+ public Writer startDocument(final Writer writer) throws SAXException {
+ this.documentHandler.startDocument();
+ return writer;
+ }
+
+ public void endDocument() throws SAXException {
+ }
+
+ public void startElement(final String name, final AttributeList attributes) throws SAXException {
+ }
+
+ public Writer startElement(final String name, final AttributeList attributes, final Writer writer)
+ throws SAXException
+ {
+ this.documentHandler.startElement(name, attributes);
+ return writer;
+ }
+
+ public void endElement(final String name) throws SAXException {
+ }
+
+ public void characters(final char ch[], final int start, final int length) throws SAXException {
+ }
+
+ public void ignorableWhitespace(final char ch[], final int start, final int length) throws SAXException {
+ }
+
+ public void processingInstruction(final String target, final String data) throws SAXException {
+ }
+
+ public void warning(final SAXParseException e) throws SAXException {
+ }
+
+ public void error(final SAXParseException e) throws SAXException {
+ }
+
+ public void fatalError(final SAXParseException e) throws SAXException {
+ throw e;
+ }
+
+ public String getPublicId() {
+ return "";
+ }
+
+
+ public String getSystemId() {
+ return "";
+ }
+
+ public int getLineNumber () {
+ return this.lineNumber;
+ }
+
+ public int getColumnNumber () {
+ return this.columnNumber;
+ }
+
+ private void fatalError(final String msg, final int lineNumber, final int columnNumber) throws SAXException {
+ this.errorHandler.fatalError(new SAXParseException(msg, null, null, lineNumber, columnNumber));
+ }
+
+ private class MinMLBuffer extends Writer {
+ public MinMLBuffer(final Reader in) {
+ this.in = in;
+ }
+
+ public void close() throws IOException {
+ flush();
+ }
+
+ public void flush() throws IOException {
+ try {
+ _flush();
+ if (writer != this) writer.flush();
+ }
+ finally {
+ flushed = true;
+ }
+ }
+
+ public void write(final int c) throws IOException {
+ written = true;
+ chars[count++] = (char)c;
+ }
+
+ public void write(final char[] cbuf, final int off, final int len) throws IOException {
+ written = true;
+ System.arraycopy(cbuf, off, chars, count, len);
+ count += len;
+ }
+
+ public void saveChar(final char c) {
+ written = false;
+ chars[count++] = c;
+ }
+
+ public void pushWriter(final Writer writer) {
+ MinML.this.tags.push(this.writer);
+
+ this.writer = (writer == null) ? this : writer;
+
+ flushed = written = false;
+ }
+
+ public Writer getWriter() {
+ return writer;
+ }
+
+ public void popWriter() throws IOException {
+ try {
+ if (!flushed && writer != this) writer.flush();
+ }
+ finally {
+ writer = (Writer)MinML.this.tags.pop();
+ flushed = written = false;
+ }
+ }
+
+ public String getString() {
+ final String result = new String(chars, 0, count);
+
+ count = 0;
+ return result;
+ }
+
+ public void reset() {
+ count = 0;
+ }
+
+ public int read() throws IOException {
+ if (nextIn == lastIn) {
+ if (count != 0) {
+ if (written) {
+ _flush();
+ } else if (count >= (chars.length - MinML.this.bufferIncrement)) {
+ final char[] newChars = new char[chars.length + MinML.this.bufferIncrement];
+
+ System.arraycopy(chars, 0, newChars, 0, count);
+ chars = newChars;
+ }
+ }
+
+ final int numRead = in.read(chars, count, chars.length - count);
+
+ if (numRead == -1) return -1;
+
+ nextIn = count;
+ lastIn = count + numRead;
+ }
+
+ return chars[nextIn++];
+ }
+
+ private void _flush() throws IOException {
+ if (count != 0) {
+ try {
+ if (writer == this) {
+ try {
+ MinML.this.documentHandler.characters(chars, 0, count);
+ }
+ catch (final SAXException e) {
+ throw new IOException(e.toString());
+ }
+ } else {
+ writer.write(chars, 0, count);
+ }
+ }
+ finally {
+ count = 0;
+ }
+ }
+ }
+
+ private int nextIn = 0, lastIn = 0;
+ private char[] chars = new char[MinML.this.initialBufferSize];
+ private final Reader in;
+ private int count = 0;
+ private Writer writer = this;
+ private boolean flushed = false;
+ private boolean written = false;
+ }
+
+ private DocumentHandler extDocumentHandler = this;
+ private org.xml.sax.DocumentHandler documentHandler = this;
+ private ErrorHandler errorHandler = this;
+ private final Stack tags = new Stack();
+ private int lineNumber = 1;
+ private int columnNumber = 0;
+ private final int initialBufferSize;
+ private final int bufferIncrement;
+
+ private static final byte[] charClasses = {
+ // EOF
+ 13,
+ // \t \n \r
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 12, 12, -1, -1, 12, -1, -1,
+ //
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ // SP ! " # $ % & ' ( ) * + , - . /
+ 12, 8, 7, 14, 14, 14, 3, 6, 14, 14, 14, 14, 14, 11, 14, 2,
+ // 0 1 2 3 4 5 6 7 8 9 : ; < = > ?
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 5, 1, 4,
+ //
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+ // [ \ ]
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 9, 14, 10
+ };
+
+ private static final String[] operands = {
+ "\u0d15\u1611\u1611\u1611\u1611\u1611\u1611\u1611\u1611\u1611\u1611\u1611\u0015\u0010\u1611",
+ "\u1711\u1000\u0b00\u1711\u1711\u1711\u1711\u1711\u1711\u1711\u1711\u0114\u0200\u1811\u0114",
+ "\u1711\u1001\u0b01\u1711\u1711\u1711\u1711\u1711\u1711\u1711\u1711\u1711\u0215\u1811\u0414",
+ "\u1711\u1001\u0b01\u1711\u1911\u1911\u1911\u1911\u1911\u1911\u1911\u1911\u0315\u1811\u0414",
+ "\u1911\u1911\u1911\u1911\u1911\u0606\u1911\u1911\u1911\u1911\u1911\u0414\u0515\u1811\u0414",
+ "\u1911\u1911\u1911\u1911\u1911\u0606\u1911\u1911\u1911\u1911\u1911\u1911\u0515\u1811\u1911",
+ "\u1a11\u1a11\u1a11\u1a11\u1a11\u1a11\u0715\u0815\u1a11\u1a11\u1a11\u1a11\u0615\u1811\u1a11",
+ "\u0714\u0714\u0714\u070e\u0714\u0714\u0307\u0714\u0714\u0714\u0714\u0714\u0714\u1811\u0714",
+ "\u0814\u0814\u0814\u080e\u0814\u0814\u0814\u0307\u0814\u0814\u0814\u0814\u0814\u1811\u0814",
+ "\u1711\u1002\u1711\u1711\u1711\u1711\u1711\u1711\u1711\u1711\u1711\u0914\u0915\u1811\u0914",
+ "\u1b11\u1b11\u0904\u1b11\u1b11\u1b11\u1b11\u1b11\u1215\u1b11\u1b11\u1b11\u1b11\u1811\u0105",
+ "\u1711\u1012\u1711\u1711\u1711\u1711\u1711\u1711\u1711\u1711\u1711\u1711\u1711\u1811\u1711",
+ "\u1711\u1c11\u0912\u1711\u0e12\u1711\u1711\u1711\u1212\u1711\u1711\u1711\u1711\u1811\u0113",
+ "\u1711\u1c11\u0912\u1711\u0e12\u1711\u1711\u1711\u1212\u1711\u1711\u1711\u1711\u1811\u0113",
+ "\u0e15\u0e15\u0e15\u0e15\u0f15\u0e15\u0e15\u0e15\u0e15\u0e15\u0e15\u0e15\u0e15\u1811\u0e15",
+ "\u0e15\u0015\u0e15\u0e15\u0f15\u0e15\u0e15\u0e15\u0e15\u0e15\u0e15\u0e15\u0e15\u1811\u0e15",
+ "\u0c03\u110f\u110f\u110e\u110f\u110f\u110f\u110f\u110f\u110f\u110f\u110f\u1014\u1811\u110f",
+ "\u0a15\u110f\u110f\u110e\u110f\u110f\u110f\u110f\u110f\u110f\u110f\u110f\u110f\u1811\u110f",
+ "\u1d11\u1d11\u1d11\u1d11\u1d11\u1d11\u1d11\u1d11\u1d11\u130c\u1d11\u1408\u1d11\u1811\u1515",
+ "\u130f\u130f\u130f\u130f\u130f\u130f\u130f\u130f\u130f\u130f\u110d\u130f\u130f\u1811\u130f",
+ "\u1415\u1415\u1415\u1415\u1415\u1415\u1415\u1415\u1415\u1415\u1415\u0009\u1415\u1811\u1415",
+ "\u150a\u000b\u1515\u1515\u1515\u1515\u1515\u1515\u1515\u1515\u1515\u1515\u1515\u1811\u1515",
+ "expected Element",
+ "unexpected character in tag",
+ "unexpected end of file found",
+ "attribute name not followed by '='",
+ "invalid attribute value",
+ "expecting end tag",
+ "empty tag",
+ "unexpected character after <!"
+ };
+}