summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Burdess <dog@bluezoo.org>2005-12-23 12:43:20 +0000
committerChris Burdess <dog@bluezoo.org>2005-12-23 12:43:20 +0000
commit62c67d308f3ef692726e7aa3efa579523a0719f9 (patch)
tree94bf61e28b6f2821964cc15e4f6b776629876477
parent602e4b40fba62a3e487eadb8426cd39645a5e1ca (diff)
downloadclasspath-62c67d308f3ef692726e7aa3efa579523a0719f9.tar.gz
2005-12-23 Chris Burdess <dog@gnu.org>
* gnu/xml/stream/SAXParser.java, gnu/xml/stream/XMLParser.java: Interim commit during W3C XML conformance testing.
-rw-r--r--ChangeLog6
-rw-r--r--gnu/xml/stream/SAXParser.java78
-rw-r--r--gnu/xml/stream/XMLParser.java431
3 files changed, 376 insertions, 139 deletions
diff --git a/ChangeLog b/ChangeLog
index 29911efd3..1a1cd8341 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2005-12-23 Chris Burdess <dog@gnu.org>
+
+ * gnu/xml/stream/SAXParser.java,
+ gnu/xml/stream/XMLParser.java: Interim commit during W3C XML
+ conformance testing.
+
2005-12-22 Lillian Angel <langel@redhat.com>
* javax/swing/JInternalFrame.java
diff --git a/gnu/xml/stream/SAXParser.java b/gnu/xml/stream/SAXParser.java
index f17c11199..2ed6872c8 100644
--- a/gnu/xml/stream/SAXParser.java
+++ b/gnu/xml/stream/SAXParser.java
@@ -76,7 +76,8 @@ import org.xml.sax.ext.Locator2;
*/
public class SAXParser
extends javax.xml.parsers.SAXParser
- implements XMLReader, Attributes2, Locator2, XMLResolver, XMLReporter
+ implements XMLReader, Attributes2, Locator2, XMLReporter,
+ XMLParser.XMLResolver2
{
ContentHandler contentHandler;
@@ -377,6 +378,16 @@ public class SAXParser
uri = "";
localName = "";
}
+ else
+ {
+ int nc = reader.getNamespaceCount();
+ for (int i = 0; i < nc; i++)
+ {
+ String nsuri = reader.getNamespaceURI(i);
+ String nsprefix = reader.getNamespacePrefix(i);
+ contentHandler.startPrefixMapping(nsprefix, nsuri);
+ }
+ }
contentHandler.startElement(uri, localName, qName, this);
}
break;
@@ -396,6 +407,15 @@ public class SAXParser
localName = "";
}
contentHandler.endElement(uri, localName, qName);
+ if (namespaceAware)
+ {
+ int nc = reader.getNamespaceCount();
+ for (int i = 0; i < nc; i++)
+ {
+ String nsprefix = reader.getNamespacePrefix(i);
+ contentHandler.endPrefixMapping(nsprefix);
+ }
+ }
}
break;
case XMLStreamConstants.COMMENT:
@@ -499,17 +519,26 @@ public class SAXParser
if (ids.notationName != null)
{
if (dtdHandler != null)
- dtdHandler.unparsedEntityDecl(name,
- ids.publicId,
- ids.systemId,
- ids.notationName);
+ {
+ String pub = ids.publicId;
+ String url = ids.systemId;
+ String not = ids.notationName;
+ dtdHandler.unparsedEntityDecl(name,
+ pub,
+ url,
+ not);
+ }
}
else
{
if (declHandler != null)
- declHandler.externalEntityDecl(name,
- ids.publicId,
- ids.systemId);
+ {
+ String pub = ids.publicId;
+ String url = ids.systemId;
+ declHandler.externalEntityDecl(name,
+ pub,
+ url);
+ }
}
}
}
@@ -520,8 +549,9 @@ public class SAXParser
{
XMLParser.ExternalIds ids =
doctype.getNotation(name);
- dtdHandler.notationDecl(name, ids.publicId,
- ids.systemId);
+ String pub = ids.publicId;
+ String url = ids.systemId;
+ dtdHandler.notationDecl(name, pub, url);
}
}
}
@@ -536,6 +566,10 @@ public class SAXParser
contentHandler.startDocument();
SAXParseException e2 = new SAXParseException(e.getMessage(), this);
e2.initCause(e);
+ if (errorHandler != null)
+ errorHandler.fatalError(e2);
+ if (contentHandler != null)
+ contentHandler.endDocument();
throw e2;
}
finally
@@ -607,7 +641,9 @@ public class SAXParser
public String getType(int index)
{
- return reader.getAttributeType(index);
+ String ret = reader.getAttributeType(index);
+ // SAX doesn't permit ENUMERATION?
+ return ("ENUMERATION".equals(ret)) ? "NMTOKEN" : ret;
}
public String getType(String qName)
@@ -715,15 +751,22 @@ public class SAXParser
}
// -- XMLResolver --
-
+
public InputStream resolve(String uri)
throws XMLStreamException
{
+ return resolve(null, uri);
+ }
+
+ public InputStream resolve(String publicId, String systemId)
+ throws XMLStreamException
+ {
if (entityResolver != null)
{
try
{
- InputSource input = entityResolver.resolveEntity(null, uri);
+ InputSource input =
+ entityResolver.resolveEntity(publicId, systemId);
if (input != null)
return input.getByteStream();
}
@@ -777,5 +820,14 @@ public class SAXParser
}
}
}
+
+ public static void main(String[] args)
+ throws Exception
+ {
+ SAXParser parser = new SAXParser();
+ InputSource input = new InputSource(args[0]);
+ parser.parse(input, new org.xml.sax.helpers.DefaultHandler());
+
+ }
}
diff --git a/gnu/xml/stream/XMLParser.java b/gnu/xml/stream/XMLParser.java
index 82f860201..127382bfe 100644
--- a/gnu/xml/stream/XMLParser.java
+++ b/gnu/xml/stream/XMLParser.java
@@ -66,8 +66,9 @@ import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
-import java.util.LinkedHashMap;
+import java.util.HashSet;
import java.util.Iterator;
+import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.NoSuchElementException;
@@ -91,7 +92,7 @@ import gnu.java.net.CRLFInputStream;
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
*/
public class XMLParser
- implements XMLStreamReader, NamespaceContext, Location
+ implements XMLStreamReader, NamespaceContext
{
private static final int INIT = 0;
@@ -128,6 +129,7 @@ public class XMLParser
private ArrayList attrs = new ArrayList();
private StringBuffer buf = new StringBuffer();
private StringBuffer nmtokenBuf = new StringBuffer();
+ private StringBuffer literalBuf = new StringBuffer();
private char[] tmpBuf = new char[1024];
private String piTarget, piData;
@@ -148,15 +150,15 @@ public class XMLParser
private final boolean namespaceAware;
private final boolean baseAware;
- private final XMLReporter reporter;
- private final XMLResolver resolver;
+ final XMLReporter reporter;
+ final XMLResolver resolver;
private static final String TEST_START_ELEMENT = "<";
private static final String TEST_END_ELEMENT = "</";
private static final String TEST_COMMENT = "<!--";
private static final String TEST_PI = "<?";
private static final String TEST_CDATA = "<![CDATA[";
- private static final String TEST_XML_DECL = "<?xml ";
+ private static final String TEST_XML_DECL = "<?xml";
private static final String TEST_DOCTYPE_DECL = "<!DOCTYPE";
private static final String TEST_ELEMENT_DECL = "<!ELEMENT";
private static final String TEST_ATTLIST_DECL = "<!ATTLIST";
@@ -286,28 +288,6 @@ public class XMLParser
return acc.iterator();
}
- // -- Location --
-
- public int getCharacterOffset()
- {
- return input.offset;
- }
-
- public int getColumnNumber()
- {
- return input.column;
- }
-
- public int getLineNumber()
- {
- return input.line;
- }
-
- public String getLocationURI()
- {
- return input.systemId;
- }
-
// -- XMLStreamReader --
public void close()
@@ -370,7 +350,7 @@ public class XMLParser
if (att != null)
return att.type;
}
- return null;
+ return "CDATA";
}
public String getAttributeValue(int index)
@@ -458,7 +438,7 @@ public class XMLParser
public Location getLocation()
{
- return this;
+ return input;
}
public QName getName()
@@ -782,6 +762,8 @@ public class XMLParser
}
try
{
+ if (!input.initialized)
+ input.init();
//System.out.println("input="+input.name+" "+input.inputEncoding);
switch (state)
{
@@ -840,7 +822,7 @@ public class XMLParser
}
else if (replaceERefs)
{
- expandEntity(ref); //report start-entity
+ expandEntity(ref, false); //report start-entity
event = next();
}
else
@@ -857,6 +839,9 @@ public class XMLParser
}
break;
case EMPTY_ELEMENT:
+ String elementName = (String) stack.removeLast();
+ buf.setLength(0);
+ buf.append(elementName);
state = stack.isEmpty() ? MISC : CONTENT;
event = XMLStreamConstants.END_ELEMENT;
break;
@@ -1072,7 +1057,7 @@ public class XMLParser
if (c == '\uffff')
throw new EOFException();
else if (c < 32 && c != 10 && c != 9 && c != 13)
- error("Illegal XML character:", Character.toString(c));
+ error("illegal XML character", Character.toString(c));
buf.append(c);
}
}
@@ -1096,7 +1081,12 @@ public class XMLParser
if (white)
ret = true;
else if (c == '\uffff')
- throw new EOFException();
+ {
+ if (inputStack.size() > 1)
+ popInput();
+ else
+ throw new EOFException();
+ }
}
while (white);
reset();
@@ -1114,6 +1104,11 @@ public class XMLParser
{
mark(1);
char c = readCh();
+ while (c == '\uffff' && inputStack.size() > 1)
+ {
+ popInput();
+ c = readCh();
+ }
white = (c == ' ' || c == '\t' || c == '\n' || c == '\r');
}
while (white);
@@ -1150,6 +1145,13 @@ public class XMLParser
private void pushInput(String name, String text)
throws IOException, XMLStreamException
{
+ // Check for recursion
+ for (Iterator i = inputStack.iterator(); i.hasNext(); )
+ {
+ Input ctx = (Input) i.next();
+ if (name.equals(ctx.name))
+ error("entities may not be self-recursive", name);
+ }
pushInput(new Input(null, new StringReader(text), input.publicId,
input.systemId, name, input.inputEncoding));
//System.out.println("pushInput "+name+" "+text);
@@ -1166,18 +1168,47 @@ public class XMLParser
InputStream in = null;
String base = getXMLBase();
String url = absolutize(base, ids.systemId);
- // TODO try to resolve via public ID
+ // Unparsed entity?
+ boolean unparsedEntity = false;
+ if (ids.notationName != null)
+ {
+ ExternalIds notation = doctype.getNotation(ids.notationName);
+ if (notation == null)
+ error("reference to undeclared notation", ids.notationName);
+ unparsedEntity = true;
+ }
+ // Check for recursion
+ for (Iterator i = inputStack.iterator(); i.hasNext(); )
+ {
+ Input ctx = (Input) i.next();
+ if (url.equals(ctx.systemId))
+ error("entities may not be self-recursive", url);
+ if (name.equals(ctx.name))
+ error("entities may not be self-recursive", name);
+ }
if (in == null && url != null && resolver != null)
- in = resolver.resolve(url);
+ {
+ if (resolver instanceof XMLResolver2)
+ in = ((XMLResolver2) resolver).resolve(ids.publicId, url);
+ else
+ in = resolver.resolve(url);
+ }
if (in == null)
in = resolve(url);
if (in == null)
error("unable to resolve external entity",
(ids.systemId != null) ? ids.systemId : ids.publicId);
- pushInput(new Input(in, ids.publicId, url, name, input.inputEncoding));
- input.init();
- if (tryRead(TEST_XML_DECL))
- readTextDecl();
+ if (unparsedEntity)
+ {
+ // TODO read unparsed entity into buf
+ }
+ else
+ {
+ pushInput(new Input(in, ids.publicId, url, name, input.inputEncoding));
+ input.init();
+ if (tryRead(TEST_XML_DECL))
+ readTextDecl();
+ }
//System.out.println("pushInput "+name+" "+url);
}
@@ -1273,7 +1304,7 @@ public class XMLParser
private void popInput()
{
Input old = (Input) inputStack.removeLast();
- if (startEntityStack.contains(old.name))
+ if (!"".equals(old.name))
endEntityStack.addFirst(old.name);
input = (Input) inputStack.getLast();
//System.out.print("\n(-input:"+input.systemId+")");
@@ -1287,6 +1318,7 @@ public class XMLParser
throws IOException, XMLStreamException
{
final int flags = LIT_DISABLE_CREF | LIT_DISABLE_PE | LIT_DISABLE_EREF;
+ requireWhitespace();
if (tryRead("version"))
{
readEq();
@@ -1316,6 +1348,7 @@ public class XMLParser
{
final int flags = LIT_DISABLE_CREF | LIT_DISABLE_PE | LIT_DISABLE_EREF;
+ requireWhitespace();
require("version");
readEq();
xmlVersion = readLiteral(flags);
@@ -1386,7 +1419,7 @@ public class XMLParser
else
{
peIsError = expandPE = true;
- readMarkupdecl();
+ readMarkupdecl(false);
peIsError = expandPE = false;
}
}
@@ -1397,7 +1430,7 @@ public class XMLParser
// Parse external subset
if (ids.systemId != null && externalEntities)
{
- pushInput(null, ">");
+ pushInput("", ">");
pushInput("[dtd]", ids);
// loop until we get back to ">"
while (true)
@@ -1414,9 +1447,11 @@ public class XMLParser
else
{
reset();
- peIsError = expandPE = true;
- readMarkupdecl();
- peIsError = expandPE = false;
+ //peIsError = expandPE = true;
+ expandPE = true;
+ readMarkupdecl(true);
+ //peIsError = expandPE = false;
+ expandPE = true;
}
}
if (inputStack.size() != 2)
@@ -1429,7 +1464,7 @@ public class XMLParser
buf.append(rootName);
}
- private void readMarkupdecl()
+ private void readMarkupdecl(boolean inExternalSubset)
throws IOException, XMLStreamException
{
boolean saved = expandPE;
@@ -1450,12 +1485,12 @@ public class XMLParser
else if (tryRead(TEST_ENTITY_DECL))
{
expandPE = saved;
- readEntityDecl();
+ readEntityDecl(inExternalSubset);
}
else if (tryRead(TEST_NOTATION_DECL))
{
expandPE = saved;
- readNotationDecl();
+ readNotationDecl(inExternalSubset);
}
else if (tryRead(TEST_PI))
{
@@ -1481,7 +1516,7 @@ public class XMLParser
skipWhitespace();
while (!tryRead("]]>"))
{
- readMarkupdecl();
+ readMarkupdecl(inExternalSubset);
skipWhitespace();
}
}
@@ -1823,7 +1858,7 @@ public class XMLParser
doctype.addAttributeDecl(elementName, name, attribute);
}
- private void readEntityDecl()
+ private void readEntityDecl(boolean inExternalSubset)
throws IOException, XMLStreamException
{
int flags = 0;
@@ -1840,7 +1875,7 @@ public class XMLParser
// Read entity name
String name = readNmtoken(true);
if (name.indexOf(':') != -1)
- error("Illegal character ':' in entity name", name);
+ error("illegal character ':' in entity name", name);
if (peFlag)
name = "%" + name;
requireWhitespace();
@@ -1850,8 +1885,8 @@ public class XMLParser
if (c == '"' || c == '\'')
{
// Internal entity replacement text
- String value = readLiteral(flags);
- doctype.addEntityDecl(name, value);
+ String value = readLiteral(flags | LIT_DISABLE_EREF);
+ doctype.addEntityDecl(name, value, inExternalSubset);
}
else
{
@@ -1865,30 +1900,30 @@ public class XMLParser
requireWhitespace();
ids.notationName = readNmtoken(true);
}
- doctype.addEntityDecl(name, ids);
+ doctype.addEntityDecl(name, ids, inExternalSubset);
}
// finish
skipWhitespace();
require('>');
}
- private void readNotationDecl()
+ private void readNotationDecl(boolean inExternalSubset)
throws IOException, XMLStreamException
{
requireWhitespace();
String notationName = readNmtoken(true);
if (notationName.indexOf(':') != -1)
- error("Illegal character ':' in notation name", notationName);
+ error("illegal character ':' in notation name", notationName);
requireWhitespace();
ExternalIds ids = readExternalIds(true, false);
ids.notationName = notationName;
- doctype.addNotationDecl(notationName, ids);
+ doctype.addNotationDecl(notationName, ids, inExternalSubset);
skipWhitespace();
require('>');
}
/**
- * Returns a tuple {publicId, syatemId}.
+ * Returns a tuple {publicId, systemId}.
*/
private ExternalIds readExternalIds(boolean inNotation, boolean isSubset)
throws IOException, XMLStreamException
@@ -1908,12 +1943,12 @@ public class XMLParser
c = readCh();
reset();
if (c == '"' || c == '\'')
- ids.systemId = readLiteral(flags);
+ ids.systemId = absolutize(input.systemId, readLiteral(flags));
}
else
{
requireWhitespace();
- ids.systemId = readLiteral(flags);
+ ids.systemId = absolutize(input.systemId, readLiteral(flags));
}
for (int i = 0; i < ids.publicId.length(); i++)
@@ -1932,7 +1967,7 @@ public class XMLParser
else if (tryRead("SYSTEM"))
{
requireWhitespace();
- ids.systemId = readLiteral(flags);
+ ids.systemId = absolutize(input.systemId, readLiteral(flags));
}
else if (!isSubset)
{
@@ -2000,15 +2035,8 @@ public class XMLParser
if (ctx.containsKey(attName.substring(6)))
continue; // namespace was specified
}
- else
- {
- for (Iterator j = attrs.iterator(); j.hasNext(); )
- {
- Attribute a = (Attribute) j.next();
- if (attName.equals(a.name))
- continue; // attribute was specified
- }
- }
+ else if (attributeSpecified(attName))
+ continue;
AttributeDecl decl = (AttributeDecl) entry.getValue();
if (decl.value == null)
continue;
@@ -2031,11 +2059,11 @@ public class XMLParser
// make element name available for read
buf.setLength(0);
buf.append(elementName);
+ // push element onto stack
+ stack.addLast(elementName);
switch (c)
{
case '>':
- // push element onto stack
- stack.addLast(elementName);
return CONTENT;
case '/':
require('>');
@@ -2044,6 +2072,17 @@ public class XMLParser
return -1; // to satisfy compiler
}
+ private boolean attributeSpecified(String attName)
+ {
+ for (Iterator j = attrs.iterator(); j.hasNext(); )
+ {
+ Attribute a = (Attribute) j.next();
+ if (attName.equals(a.name))
+ return true;
+ }
+ return false;
+ }
+
/**
* Parse an attribute.
*/
@@ -2155,9 +2194,9 @@ public class XMLParser
expandPE = false;
piTarget = readNmtoken(true);
if (piTarget.indexOf(':') != -1)
- error("Illegal character in PI target", new Character(':'));
+ error("illegal character in PI target", new Character(':'));
if ("xml".equalsIgnoreCase(piTarget))
- error("Illegal PI target", piTarget);
+ error("illegal PI target", piTarget);
if (tryRead(TEST_END_PI))
piData = null;
else
@@ -2278,10 +2317,11 @@ public class XMLParser
buf.append(text);
else
{
- if (replaceERefs)
- expandEntity(entityName); //report start-entity
- else
- reset(); // report reference
+ //if (replaceERefs)
+ // expandEntity(entityName, false); //report start-entity
+ //else
+ // reset(); // report reference
+ pushInput("", "&" + entityName + ";");
done = true;
break;
}
@@ -2302,6 +2342,14 @@ public class XMLParser
}
entities = true;
break; // end of text sequence
+ case '>':
+ int l = buf.length();
+ if (l > 1 &&
+ buf.charAt(l - 1) == ']' &&
+ buf.charAt(l - 2) == ']')
+ error("Character data may not contain unescaped ']]>'");
+ buf.append(c);
+ break;
case '<':
reset();
read(tmpBuf, 0, i);
@@ -2325,14 +2373,14 @@ public class XMLParser
done = true;
}
if (entities)
- normalizeCRLF();
+ normalizeCRLF(buf);
return white ? XMLStreamConstants.SPACE : XMLStreamConstants.CHARACTERS;
}
/**
* Expands the specified entity.
*/
- private void expandEntity(String name)
+ private void expandEntity(String name, boolean inAttr)
throws IOException, XMLStreamException
{
if (doctype != null)
@@ -2340,8 +2388,28 @@ public class XMLParser
Object value = doctype.getEntity(name);
if (value != null)
{
+ if (xmlStandalone == Boolean.TRUE)
+ {
+ if (doctype.isEntityExternal(name))
+ error("reference to external entity in standalone document");
+ else if (value instanceof ExternalIds)
+ {
+ ExternalIds ids = (ExternalIds) value;
+ if (ids.notationName != null &&
+ doctype.isNotationExternal(ids.notationName))
+ error("reference to external notation in " +
+ "standalone document");
+ }
+ }
if (value instanceof String)
- pushInput(name, (String) value);
+ {
+ String text = (String) value;
+ if (inAttr && text.indexOf('<') != -1)
+ error("< in attribute value");
+ pushInput(name, text);
+ }
+ else if (inAttr)
+ error("reference to external entity in attribute value", name);
else
pushInput(name, (ExternalIds) value);
if (name != null)
@@ -2349,7 +2417,7 @@ public class XMLParser
return;
}
}
- error("Reference to undeclared entity", name);
+ error("reference to undeclared entity", name);
}
/**
@@ -2389,12 +2457,16 @@ public class XMLParser
char delim = readCh();
if (delim != '\'' && delim != '"')
error("expected '\"' or \"'\"", new Character(delim));
- buf.setLength(0);
+ literalBuf.setLength(0);
if ((flags & LIT_DISABLE_PE) != 0)
expandPE = false;
boolean entities = false;
- for (char c = literalReadCh(); c != delim; c = literalReadCh())
+ int inputStackSize = inputStack.size();
+ do
{
+ char c = literalReadCh();
+ if (c == delim && inputStackSize == inputStack.size())
+ break;
switch (c)
{
case '\n':
@@ -2412,61 +2484,83 @@ public class XMLParser
if (c == '#')
{
if ((flags & LIT_DISABLE_CREF) != 0)
- error("literal may not contain character reference");
- mark(1);
- c = readCh();
- boolean hex = (c == 'x');
- if (!hex)
- reset();
- char[] ref = readCharacterRef(hex ? 16 : 10);
- for (int i = 0; i < ref.length; i++)
{
- c = ref[i];
- if ((flags & (LIT_ATTRIBUTE | LIT_PUBID)) != 0 &&
- (c == '\n' || c == '\r'))
- c = ' '; // normalize
- else if ((flags & LIT_ATTRIBUTE) != 0 && c == '\t')
- c = ' '; // normalize
- buf.append(c);
+ reset();
+ c = '&';
+ }
+ else
+ {
+ mark(1);
+ c = readCh();
+ boolean hex = (c == 'x');
+ if (!hex)
+ reset();
+ char[] ref = readCharacterRef(hex ? 16 : 10);
+ for (int i = 0; i < ref.length; i++)
+ {
+ c = ref[i];
+ if ((flags & (LIT_ATTRIBUTE | LIT_PUBID)) != 0 &&
+ (c == '\n' || c == '\r'))
+ c = ' '; // normalize
+ else if ((flags & LIT_ATTRIBUTE) != 0 && c == '\t')
+ c = ' '; // normalize
+ literalBuf.append(c);
+ }
+ entities = true;
+ continue;
}
- entities = true;
- continue;
}
else
{
if ((flags & LIT_DISABLE_EREF) != 0)
- error("literal may not contain entity reference");
- reset();
- if (replaceERefs || (flags & LIT_NORMALIZE) > 0)
{
- String entityName = readNmtoken(true);
- require(';');
- String text = (String) PREDEFINED_ENTITIES.get(entityName);
- if (text != null)
- buf.append(text);
- else
- expandEntity(entityName);
- entities = true;
- continue;
+ reset();
+ c = '&';
}
else
- error("parser is configured not to replace entity " +
- "references");
+ {
+ reset();
+ if (replaceERefs || (flags & LIT_NORMALIZE) > 0)
+ {
+ String entityName = readNmtoken(true);
+ require(';');
+ String text =
+ (String) PREDEFINED_ENTITIES.get(entityName);
+ if (text != null)
+ literalBuf.append(text);
+ else
+ expandEntity(entityName,
+ (flags & LIT_ATTRIBUTE) != 0);
+ entities = true;
+ continue;
+ }
+ else
+ error("parser is configured not to replace entity " +
+ "references");
+ }
}
break;
case '<':
if ((flags & LIT_ATTRIBUTE) != 0)
error("attribute values may not contain '<'");
break;
+ case '\uffff':
+ if (inputStack.size() > 1)
+ {
+ popInput();
+ continue;
+ }
+ throw new EOFException();
}
- buf.append(c);
+ literalBuf.append(c);
}
+ while (true);
expandPE = saved;
if (entities)
- normalizeCRLF();
+ normalizeCRLF(literalBuf);
if ((flags & LIT_NORMALIZE) > 0)
- normalize();
- return buf.toString();
+ literalBuf = normalize(literalBuf);
+ return literalBuf.toString();
}
/**
@@ -2474,7 +2568,7 @@ public class XMLParser
* This discards leading and trailing whitespace, and replaces sequences
* of whitespace with a single space.
*/
- private void normalize()
+ private StringBuffer normalize(StringBuffer buf)
{
StringBuffer acc = new StringBuffer();
int len = buf.length();
@@ -2492,7 +2586,7 @@ public class XMLParser
avState = 2;
}
}
- buf = acc;
+ return acc;
}
/**
@@ -2500,7 +2594,7 @@ public class XMLParser
* This may be necessary if combinations of CR or LF were declared as
* (character) entity references in the input.
*/
- private void normalizeCRLF()
+ private void normalizeCRLF(StringBuffer buf)
{
int len = buf.length() - 1;
for (int i = 0; i < len; i++)
@@ -2522,18 +2616,29 @@ public class XMLParser
{
String name = readNmtoken(true);
require(';');
+ mark(1); // ensure we don't reset to before the semicolon
if (doctype != null)
{
- Object entity = doctype.getEntity("%" + name);
+ String entityName = "%" + name;
+ Object entity = doctype.getEntity(entityName);
if (entity != null)
{
+ if (xmlStandalone == Boolean.TRUE)
+ {
+ if (doctype.isEntityExternal(entityName))
+ error("reference to external parameter entity in " +
+ "standalone document");
+ }
if (entity instanceof String)
pushInput(name, (String) entity);
else
pushInput(name, (ExternalIds) entity);
}
+ else
+ error("reference to undeclared parameter entity", name);
}
- error("reference to undeclared parameter entity", name);
+ else
+ error("reference to parameter entity without doctype", name);
}
private char[] readCharacterRef(int base)
@@ -2888,6 +2993,8 @@ public class XMLParser
private final LinkedHashMap entities = new LinkedHashMap();
private final LinkedHashMap notations = new LinkedHashMap();
private final LinkedList entries = new LinkedList();
+ private final HashSet externalEntities = new HashSet();
+ private final HashSet externalNotations = new HashSet();
Doctype(String rootName, String publicId, String systemId)
{
@@ -2920,28 +3027,34 @@ public class XMLParser
entries.add(key);
}
- void addEntityDecl(String name, String text)
+ void addEntityDecl(String name, String text, boolean inExternalSubset)
{
if (entities.containsKey(name))
return;
entities.put(name, text);
entries.add("e" + name);
+ if (inExternalSubset)
+ externalEntities.add(name);
}
- void addEntityDecl(String name, ExternalIds ids)
+ void addEntityDecl(String name, ExternalIds ids, boolean inExternalSubset)
{
if (entities.containsKey(name))
return;
entities.put(name, ids);
entries.add("e" + name);
+ if (inExternalSubset)
+ externalEntities.add(name);
}
- void addNotationDecl(String name, ExternalIds ids)
+ void addNotationDecl(String name, ExternalIds ids, boolean inExternalSubset)
{
if (notations.containsKey(name))
return;
notations.put(name, ids);
entries.add("n" + name);
+ if (inExternalSubset)
+ externalNotations.add(name);
}
String getElementModel(String name)
@@ -2973,11 +3086,21 @@ public class XMLParser
return entities.get(name);
}
+ boolean isEntityExternal(String name)
+ {
+ return externalEntities.contains(name);
+ }
+
ExternalIds getNotation(String name)
{
return (ExternalIds) notations.get(name);
}
+ boolean isNotationExternal(String name)
+ {
+ return externalNotations.contains(name);
+ }
+
Iterator entryIterator()
{
return entries.iterator();
@@ -3011,7 +3134,17 @@ public class XMLParser
}
+ interface XMLResolver2
+ extends XMLResolver
+ {
+
+ InputStream resolve(String publicId, String systemId)
+ throws XMLStreamException;
+
+ }
+
static class Input
+ implements Location
{
int line = 1, markLine;
@@ -3075,6 +3208,29 @@ public class XMLParser
reader = new CRLFReader(reader);
}
this.reader = reader;
+ initialized = false;
+ }
+
+ // -- Location --
+
+ public int getCharacterOffset()
+ {
+ return offset;
+ }
+
+ public int getColumnNumber()
+ {
+ return column;
+ }
+
+ public int getLineNumber()
+ {
+ return line;
+ }
+
+ public String getLocationURI()
+ {
+ return systemId;
}
void init()
@@ -3106,6 +3262,8 @@ public class XMLParser
offset++;
int ret = reader.read();
//System.out.println("read1:"+((char) ret));
+ if (ret == 0x0d)
+ ret = 0x0a;
if (ret == 0x0a)
{
line++;
@@ -3129,6 +3287,11 @@ public class XMLParser
for (int i = 0; i < ret; i++)
{
char c = b[off + i];
+ if (c == 0x0d)
+ {
+ c = 0x0a;
+ b[off + i] = c;
+ }
if (c == 0x0a)
{
line++;
@@ -3251,6 +3414,22 @@ public class XMLParser
reader = new XMLInputStreamReader((XMLInputStreamReader) reader,
encoding);
}
+ else
+ {
+ /*if (reporter != null)
+ {
+ try
+ {
+ reporter.report("unable to set input encoding '" + encoding +
+ "': input is specified as reader", "WARNING",
+ encoding, this);
+ }
+ catch (XMLStreamException e)
+ {
+ // Am I bothered?
+ }}*/
+ System.err.println("Can't set input encoding "+encoding);
+ }
}
}