diff options
author | Chris Burdess <dog@bluezoo.org> | 2005-12-18 12:28:20 +0000 |
---|---|---|
committer | Chris Burdess <dog@bluezoo.org> | 2005-12-18 12:28:20 +0000 |
commit | d04bf782436cf12e5688a7b0f991513dc042ba74 (patch) | |
tree | 844cc3fca7154d36edcaed8c57c6cae876f442df /gnu/xml/stream/XMLParser.java | |
parent | 12115b752b91a3bd704c130114b7db6a904beb59 (diff) | |
download | classpath-d04bf782436cf12e5688a7b0f991513dc042ba74.tar.gz |
2005-12-18 Chris Burdess <dog@gnu.org>
* gnu/xml/stream/SAXParser.java,
gnu/xml/stream/XMLParser.java: Various fixes post SAX conformance
testing.
Diffstat (limited to 'gnu/xml/stream/XMLParser.java')
-rw-r--r-- | gnu/xml/stream/XMLParser.java | 313 |
1 files changed, 198 insertions, 115 deletions
diff --git a/gnu/xml/stream/XMLParser.java b/gnu/xml/stream/XMLParser.java index a9e6267c8..82f860201 100644 --- a/gnu/xml/stream/XMLParser.java +++ b/gnu/xml/stream/XMLParser.java @@ -366,14 +366,9 @@ public class XMLParser { if (doctype != null) { - LinkedHashMap attlist = - (LinkedHashMap) doctype.attlists.get(elementName); - if (attlist != null) - { - AttributeDecl att = (AttributeDecl) attlist.get(attName); - if (att != null) - return att.type; - } + AttributeDecl att = doctype.getAttributeDecl(elementName, attName); + if (att != null) + return att.type; } return null; } @@ -408,10 +403,7 @@ public class XMLParser String qn = ("".equals(a.prefix)) ? a.localName : a.prefix + ":" + a.localName; String elementName = buf.toString(); - LinkedHashMap attlist = (LinkedHashMap) doctype.attlists.get(elementName); - if (attlist == null) - return false; - return attlist.containsKey(qn); + return doctype.isAttributeDeclared(elementName, qn); } public String getCharacterEncodingScheme() @@ -790,15 +782,6 @@ public class XMLParser } try { - if (!input.initialized) - { - input.init(); - if (inputStack.size() > 1) - { - if (tryRead(TEST_XML_DECL)) - readTextDecl(); - } - } //System.out.println("input="+input.name+" "+input.inputEncoding); switch (state) { @@ -927,6 +910,10 @@ public class XMLParser { if (event == XMLStreamConstants.END_DOCUMENT) throw new NoSuchElementException(); + char c = readCh(); + if (c != '\uffff') + error("Only comments and PIs may appear after " + + "the root element"); event = XMLStreamConstants.END_DOCUMENT; } break; @@ -981,17 +968,7 @@ public class XMLParser private char readCh() throws IOException, XMLStreamException { - int c = read(); - /*if (c == -1) - { - if (inputStack.size() > 1) - { - popInput(); - return readCh(); - } - return (char) -1; - }*/ - char ret = (char) c; + char c = (char) read(); if (expandPE && c == '%') { if (peIsError) @@ -999,7 +976,7 @@ public class XMLParser parsePEReference(); return readCh(); } - return ret; + return c; } private void require(char delim) @@ -1092,6 +1069,10 @@ public class XMLParser while (!tryRead(delim)) { char c = readCh(); + if (c == '\uffff') + throw new EOFException(); + else if (c < 32 && c != 10 && c != 9 && c != 13) + error("Illegal XML character:", Character.toString(c)); buf.append(c); } } @@ -1194,6 +1175,9 @@ public class XMLParser 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(); //System.out.println("pushInput "+name+" "+url); } @@ -1208,6 +1192,12 @@ public class XMLParser { if (href == null) return null; + int ci = href.indexOf(':'); + if (ci > 1 && isLowercaseAscii(href.substring(0, ci))) + { + // href is absolute already + return href; + } if (base == null) base = ""; else @@ -1255,6 +1245,18 @@ public class XMLParser return base + href; } + private static boolean isLowercaseAscii(String text) + { + int len = text.length(); + for (int i = 0; i < len; i++) + { + char c = text.charAt(i); + if (c < 97 || c > 122) + return false; + } + return true; + } + private InputStream resolve(String url) throws IOException { @@ -1500,6 +1502,9 @@ public class XMLParser case ']': if (tryRead("]>")) nesting--; + break; + case '\uffff': + throw new EOFException(); } } expandPE = true; @@ -1527,9 +1532,9 @@ public class XMLParser throws IOException, XMLStreamException { if (tryRead("EMPTY")) - doctype.elements.put(elementName, "EMPTY"); + doctype.addElementDecl(elementName, "EMPTY"); else if (tryRead("ANY")) - doctype.elements.put(elementName, "ANY"); + doctype.addElementDecl(elementName, "ANY"); else { StringBuffer acc = new StringBuffer(); @@ -1562,7 +1567,7 @@ public class XMLParser } else readElements(acc); - doctype.elements.put(elementName, acc.toString()); + doctype.addElementDecl(elementName, acc.toString()); } } @@ -1812,25 +1817,10 @@ public class XMLParser else value = readLiteral(flags); expandPE = saved; - /*if ("ENUMERATION".equals(type)) - type = enumer; - else if ("NOTATION".equals(type)) - type = "NOTATION " + enumer;*/ // Register attribute def - LinkedHashMap attlist = - (LinkedHashMap) doctype.attlists.get(elementName); - if (attlist == null) - { - attlist = new LinkedHashMap(); - doctype.attlists.put(elementName, attlist); - } - if (attlist.containsKey(name)) - { - return; - } AttributeDecl attribute = new AttributeDecl(type, value, valueType, enumeration); - attlist.put(name, attribute); + doctype.addAttributeDecl(elementName, name, attribute); } private void readEntityDecl() @@ -1861,7 +1851,7 @@ public class XMLParser { // Internal entity replacement text String value = readLiteral(flags); - doctype.entities.put(name, value); + doctype.addEntityDecl(name, value); } else { @@ -1875,7 +1865,7 @@ public class XMLParser requireWhitespace(); ids.notationName = readNmtoken(true); } - doctype.entities.put(name, ids); + doctype.addEntityDecl(name, ids); } // finish skipWhitespace(); @@ -1892,7 +1882,7 @@ public class XMLParser requireWhitespace(); ExternalIds ids = readExternalIds(true, false); ids.notationName = notationName; - doctype.notations.put(notationName, ids); + doctype.addNotationDecl(notationName, ids); skipWhitespace(); require('>'); } @@ -1969,7 +1959,11 @@ public class XMLParser attrs.clear(); // Push namespace context if (namespaceAware) - namespaces.addFirst(new LinkedHashMap()); + { + if (":".equals(elementName)) + error("XML Namespaces forbids names consisting of a single colon"); + namespaces.addFirst(new LinkedHashMap()); + } // Read element content boolean white = tryWhitespace(); mark(1); @@ -1988,50 +1982,45 @@ public class XMLParser // supply defaulted attributes if (doctype != null) { - LinkedHashMap attlist = - (LinkedHashMap) doctype.attlists.get(elementName); - if (attlist != null) + for (Iterator i = doctype.attlistIterator(elementName); i.hasNext(); ) { - for (Iterator i = attlist.entrySet().iterator(); i.hasNext(); ) + Map.Entry entry = (Map.Entry) i.next(); + String attName = (String) entry.getKey(); + if (namespaceAware && attName.equals("xmlns")) { - Map.Entry entry = (Map.Entry) i.next(); - String attName = (String) entry.getKey(); - if (namespaceAware && attName.equals("xmlns")) - { - LinkedHashMap ctx = - (LinkedHashMap) namespaces.getFirst(); - if (ctx.containsKey(XMLConstants.DEFAULT_NS_PREFIX)) - continue; // namespace was specified - } - else if (namespaceAware && attName.startsWith("xmlns:")) - { - LinkedHashMap ctx = - (LinkedHashMap) namespaces.getFirst(); - 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 - } - } - AttributeDecl decl = (AttributeDecl) entry.getValue(); - if (decl.value == null) - continue; - Attribute attr = - new Attribute(attName, decl.type, false, decl.value); - if (namespaceAware) + LinkedHashMap ctx = + (LinkedHashMap) namespaces.getFirst(); + if (ctx.containsKey(XMLConstants.DEFAULT_NS_PREFIX)) + continue; // namespace was specified + } + else if (namespaceAware && attName.startsWith("xmlns:")) + { + LinkedHashMap ctx = + (LinkedHashMap) namespaces.getFirst(); + if (ctx.containsKey(attName.substring(6))) + continue; // namespace was specified + } + else + { + for (Iterator j = attrs.iterator(); j.hasNext(); ) { - if (!addNamespace(attr)) - attrs.add(attr); + Attribute a = (Attribute) j.next(); + if (attName.equals(a.name)) + continue; // attribute was specified } - else + } + AttributeDecl decl = (AttributeDecl) entry.getValue(); + if (decl.value == null) + continue; + Attribute attr = + new Attribute(attName, decl.type, false, decl.value); + if (namespaceAware) + { + if (!addNamespace(attr)) attrs.add(attr); } + else + attrs.add(attr); } } if (baseAware) @@ -2072,23 +2061,27 @@ public class XMLParser readLiteral(flags) : readLiteral(flags | LIT_NORMALIZE); // add attribute event Attribute attr = this.new Attribute(attributeName, type, true, value); - if (namespaceAware && attributeName.equals("xmlns")) - { - LinkedHashMap ctx = (LinkedHashMap) namespaces.getFirst(); - if (ctx.containsKey(XMLConstants.DEFAULT_NS_PREFIX)) - error("duplicate default namespace"); - } - else if (namespaceAware && attributeName.startsWith("xmlns:")) - { - LinkedHashMap ctx = (LinkedHashMap) namespaces.getFirst(); - if (ctx.containsKey(attributeName.substring(6))) - error("duplicate namespace", attributeName.substring(6)); - } - else + if (namespaceAware) { - if (attrs.contains(attr)) + if (attributeName.equals(":")) + error("XML Namespaces forbids names consisting of a single colon"); + else if (attributeName.equals("xmlns")) + { + LinkedHashMap ctx = (LinkedHashMap) namespaces.getFirst(); + if (ctx.containsKey(XMLConstants.DEFAULT_NS_PREFIX)) + error("duplicate default namespace"); + } + else if (attributeName.startsWith("xmlns:")) + { + LinkedHashMap ctx = (LinkedHashMap) namespaces.getFirst(); + if (ctx.containsKey(attributeName.substring(6))) + error("duplicate namespace", attributeName.substring(6)); + } + else if (attrs.contains(attr)) error("duplicate attribute", attributeName); } + else if (attrs.contains(attr)) + error("duplicate attribute", attributeName); if (namespaceAware) { if (!addNamespace(attr)) @@ -2344,7 +2337,7 @@ public class XMLParser { if (doctype != null) { - Object value = doctype.entities.get(name); + Object value = doctype.getEntity(name); if (value != null) { if (value instanceof String) @@ -2531,7 +2524,7 @@ public class XMLParser require(';'); if (doctype != null) { - Object entity = doctype.entities.get("%" + name); + Object entity = doctype.getEntity("%" + name); if (entity != null) { if (entity instanceof String) @@ -2547,7 +2540,7 @@ public class XMLParser throws IOException, XMLStreamException { StringBuffer b = new StringBuffer(); - for (char c = readCh(); c != ';'; c = readCh()) + for (char c = readCh(); c != ';' && c != '\uffff'; c = readCh()) b.append(c); try { @@ -2890,10 +2883,11 @@ public class XMLParser final String rootName; final String publicId; final String systemId; - final LinkedHashMap elements = new LinkedHashMap(); - final LinkedHashMap attlists = new LinkedHashMap(); - final LinkedHashMap entities = new LinkedHashMap(); - final LinkedHashMap notations = new LinkedHashMap(); + private final LinkedHashMap elements = new LinkedHashMap(); + private final LinkedHashMap attlists = new LinkedHashMap(); + private final LinkedHashMap entities = new LinkedHashMap(); + private final LinkedHashMap notations = new LinkedHashMap(); + private final LinkedList entries = new LinkedList(); Doctype(String rootName, String publicId, String systemId) { @@ -2901,6 +2895,93 @@ public class XMLParser this.publicId = publicId; this.systemId = systemId; } + + void addElementDecl(String name, String model) + { + if (elements.containsKey(name)) + return; + elements.put(name, model); + entries.add("E" + name); + } + + void addAttributeDecl(String ename, String aname, AttributeDecl decl) + { + LinkedHashMap attlist = (LinkedHashMap) attlists.get(ename); + if (attlist == null) + { + attlist = new LinkedHashMap(); + attlists.put(ename, attlist); + } + else if (attlist.containsKey(aname)) + return; + attlist.put(aname, decl); + String key = "A" + ename; + if (!entries.contains(key)) + entries.add(key); + } + + void addEntityDecl(String name, String text) + { + if (entities.containsKey(name)) + return; + entities.put(name, text); + entries.add("e" + name); + } + + void addEntityDecl(String name, ExternalIds ids) + { + if (entities.containsKey(name)) + return; + entities.put(name, ids); + entries.add("e" + name); + } + + void addNotationDecl(String name, ExternalIds ids) + { + if (notations.containsKey(name)) + return; + notations.put(name, ids); + entries.add("n" + name); + } + + String getElementModel(String name) + { + return (String) elements.get(name); + } + + AttributeDecl getAttributeDecl(String ename, String aname) + { + LinkedHashMap attlist = (LinkedHashMap) attlists.get(ename); + return (attlist == null) ? null : (AttributeDecl) attlist.get(aname); + } + + boolean isAttributeDeclared(String ename, String aname) + { + LinkedHashMap attlist = (LinkedHashMap) attlists.get(ename); + return (attlist == null) ? false : attlist.containsKey(aname); + } + + Iterator attlistIterator(String ename) + { + LinkedHashMap attlist = (LinkedHashMap) attlists.get(ename); + return (attlist == null) ? Collections.EMPTY_LIST.iterator() : + attlist.entrySet().iterator(); + } + + Object getEntity(String name) + { + return entities.get(name); + } + + ExternalIds getNotation(String name) + { + return (ExternalIds) notations.get(name); + } + + Iterator entryIterator() + { + return entries.iterator(); + } } @@ -2999,6 +3080,8 @@ public class XMLParser void init() throws IOException { + if (initialized) + return; if (!forceReader && in != null) detectEncoding(); initialized = true; |