This patch fixes some DOM conformance failures. 2005-12-31 Chris Burdess <[EMAIL PROTECTED]>
* gnu/xml/dom/DomNamedNodeMap.java, gnu/xml/dom/DomNode.java, gnu/xml/dom/ls/SAXEventSink.java, gnu/xml/stream/SAXParser.java, gnu/xml/stream/XMLParser.java: Fix entity reference DOM construction and correct DOM tree normalisation. -- Chris Burdess "They that can give up essential liberty to obtain a little safety deserve neither liberty nor safety." - Benjamin Franklin
Index: gnu/xml/dom/DomNamedNodeMap.java =================================================================== RCS file: /cvsroot/classpath/classpath/gnu/xml/dom/DomNamedNodeMap.java,v retrieving revision 1.4 diff -u -r1.4 DomNamedNodeMap.java --- gnu/xml/dom/DomNamedNodeMap.java 2 Jul 2005 20:32:15 -0000 1.4 +++ gnu/xml/dom/DomNamedNodeMap.java 31 Dec 2005 10:27:00 -0000 @@ -319,7 +319,7 @@ if (ns) { String tln = ctx.getLocalName(); - if (tln.equals(name)) + if (name != null && name.equals(tln)) { String tu = ctx.getNamespaceURI(); if ((tu == null && uri == null) || Index: gnu/xml/dom/DomNode.java =================================================================== RCS file: /cvsroot/classpath/classpath/gnu/xml/dom/DomNode.java,v retrieving revision 1.10 diff -u -r1.10 DomNode.java --- gnu/xml/dom/DomNode.java 24 Dec 2005 18:02:36 -0000 1.10 +++ gnu/xml/dom/DomNode.java 31 Dec 2005 10:27:00 -0000 @@ -361,6 +361,16 @@ return; } break; + case DOCUMENT_TYPE_NODE: + if (!owner.building) + break; + switch (childNodeType) + { + case COMMENT_NODE: + case PROCESSING_INSTRUCTION_NODE: + return; + } + break; } if (owner.checkingWellformedness) { @@ -1734,6 +1744,8 @@ readonly = false; for (DomNode ctx = first; ctx != null; ctx = ctx.next) { + boolean saved2 = ctx.readonly; + ctx.readonly = false; switch (ctx.nodeType) { case TEXT_NODE: @@ -1749,7 +1761,11 @@ int len = attrs.getLength(); for (int i = 0; i < len; i++) { - attrs.item(i).normalize(); + DomNode attr = (DomNode) attrs.item(i); + boolean saved3 = attr.readonly; + attr.readonly = false; + attr.normalize(); + attr.readonly = saved3; } // Fall through case DOCUMENT_NODE: @@ -1759,6 +1775,7 @@ ctx.normalize(); break; } + ctx.readonly = saved2; } readonly = saved; } Index: gnu/xml/dom/ls/SAXEventSink.java =================================================================== RCS file: /cvsroot/classpath/classpath/gnu/xml/dom/ls/SAXEventSink.java,v retrieving revision 1.5 diff -u -r1.5 SAXEventSink.java --- gnu/xml/dom/ls/SAXEventSink.java 24 Dec 2005 14:14:48 -0000 1.5 +++ gnu/xml/dom/ls/SAXEventSink.java 31 Dec 2005 10:27:00 -0000 @@ -37,6 +37,7 @@ package gnu.xml.dom.ls; +import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; import java.util.List; @@ -45,6 +46,7 @@ import org.w3c.dom.DocumentType; import org.w3c.dom.Element; import org.w3c.dom.Entity; +import org.w3c.dom.EntityReference; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.w3c.dom.Text; @@ -63,6 +65,7 @@ import gnu.xml.dom.DomAttr; import gnu.xml.dom.DomDocument; import gnu.xml.dom.DomDoctype; +import gnu.xml.dom.DomNode; /** * A SAX content and lexical handler used to construct a DOM document. @@ -75,6 +78,15 @@ private static final String XMLNS_URI = XMLConstants.XMLNS_ATTRIBUTE_NS_URI; private static final String XMLNS_PREFIX = XMLConstants.XMLNS_ATTRIBUTE; + private static final HashSet PREDEFINED_ENTITIES = new HashSet(); + static + { + PREDEFINED_ENTITIES.add("amp"); + PREDEFINED_ENTITIES.add("lt"); + PREDEFINED_ENTITIES.add("gt"); + PREDEFINED_ENTITIES.add("quot"); + PREDEFINED_ENTITIES.add("apos"); + } boolean namespaceAware; boolean ignoreWhitespace; @@ -293,7 +305,7 @@ public void characters(char[] c, int off, int len) throws SAXException { - if (interrupted) + if (interrupted || len < 1) { return; } @@ -329,11 +341,8 @@ { return; } - if (!inDTD) - { - Node pi = createProcessingInstruction(target, data); - ctx.appendChild(pi); - } + Node pi = createProcessingInstruction(target, data); + ctx.appendChild(pi); } protected Node createProcessingInstruction(String target, String data) @@ -382,6 +391,8 @@ public void startEntity(String name) throws SAXException { + if (interrupted) + return; DocumentType doctype = doc.getDoctype(); if (doctype == null) { @@ -389,19 +400,9 @@ "reference to entity in undeclared doctype"); } if ("[dtd]".equals(name) || name.charAt(0) == '%') - { - // Ignore DTD and parameter entities - ctx = doctype; - return; - } - if ("lt".equals(name) || - "gt".equals(name) || - "amp".equals(name) || - "apos".equals(name) || - "quot".equals(name)) - { - return; - } + return; + if (PREDEFINED_ENTITIES.contains(name)) + return; // Get entity NamedNodeMap entities = doctype.getEntities(); Entity entity = (Entity) entities.getNamedItem(name); @@ -410,61 +411,49 @@ throw new SAXException("SAX parser error: " + "reference to undeclared entity: " + name); } - pushEntity(entity); + EntityReference ref = doc.createEntityReference(name); + // DomDocument populates with the entity replacement text, remove this + Node child = ref.getFirstChild(); + while (child != null) + { + Node nextChild = child.getNextSibling(); + ref.removeChild(child); + child = nextChild; + } + ctx.appendChild(ref); + ctx = ref; } public void endEntity(String name) throws SAXException { + if (interrupted) + return; if ("[dtd]".equals(name) || name.charAt(0) == '%') - { - // Ignore DTD and parameter entities - return; - } - if ("lt".equals(name) || - "gt".equals(name) || - "amp".equals(name) || - "apos".equals(name) || - "quot".equals(name)) - { - return; - } - // Get entity - Entity entity = popEntity(); - // TODO resolve external entities to ensure that entity has content + return; + if (PREDEFINED_ENTITIES.contains(name)) + return; + // Get entity reference + EntityReference ref = (EntityReference) ctx; + if (!ref.getNodeName().equals(name)) + throw new SAXException("expecting end of "+ref.getNodeName()+" entity"); + ctx = ctx.getParentNode(); + if (ref instanceof DomNode) + ((DomNode) ref).makeReadonly(); if (expandEntityReferences) { - // Get entity content - for (Node child = entity.getFirstChild(); child != null; - child = child.getNextSibling()) + // Move entity content from reference node onto context + Node child = ref.getFirstChild(); + while (child != null) { + Node nextChild = child.getNextSibling(); ctx.appendChild(child); + child = nextChild; } - } - else - { - Node entityReference = doc.createEntityReference(name); - ctx.appendChild(entityReference); + ctx.removeChild(ref); } } - void pushEntity(Node entity) - { - if (entityCtx == null) - { - entityCtx = new LinkedList(); - } - entityCtx.addLast(ctx); - ctx = entity; - } - - Entity popEntity() - { - Entity ret = (Entity) ctx; - ctx = (Node) entityCtx.removeLast(); - return ret; - } - public void startCDATA() throws SAXException { @@ -484,11 +473,8 @@ { return; } - if (!inDTD) - { - Node comment = createComment(c, off, len); - ctx.appendChild(comment); - } + Node comment = createComment(c, off, len); + ctx.appendChild(comment); } protected Node createComment(char[] c, int off, int len) @@ -505,6 +491,8 @@ { return; } + if (!inDTD) + throw new SAXException("notation decl outside DTD"); DomDoctype doctype = (DomDoctype) ctx; doctype.declareNotation(name, publicId, systemId); } @@ -517,6 +505,8 @@ { return; } + if (!inDTD) + throw new SAXException("unparsed entity decl outside DTD"); DomDoctype doctype = (DomDoctype) ctx; Entity entity = doctype.declareEntity(name, publicId, systemId, notationName); @@ -531,6 +521,8 @@ { return; } + if (!inDTD) + throw new SAXException("element decl outside DTD"); // Ignore fake element declarations generated by ValidationConsumer. // If an element is not really declared in the DTD it will not be // declared in the document model. @@ -550,6 +542,8 @@ { return; } + if (!inDTD) + throw new SAXException("attribute decl outside DTD"); DomDoctype doctype = (DomDoctype) ctx; doctype.attributeDecl(eName, aName, type, mode, value); } @@ -561,6 +555,8 @@ { return; } + if (!inDTD) + throw new SAXException("internal entity decl outside DTD"); DomDoctype doctype = (DomDoctype) ctx; Entity entity = doctype.declareEntity(name, null, null, null); if (entity != null) @@ -577,6 +573,8 @@ { return; } + if (!inDTD) + throw new SAXException("external entity decl outside DTD"); DomDoctype doctype = (DomDoctype) ctx; Entity entity = doctype.declareEntity(name, publicId, systemId, null); } Index: gnu/xml/stream/SAXParser.java =================================================================== RCS file: /cvsroot/classpath/classpath/gnu/xml/stream/SAXParser.java,v retrieving revision 1.9 diff -u -r1.9 SAXParser.java --- gnu/xml/stream/SAXParser.java 29 Dec 2005 17:28:05 -0000 1.9 +++ gnu/xml/stream/SAXParser.java 31 Dec 2005 10:27:01 -0000 @@ -147,9 +147,12 @@ throw new IllegalStateException("parsing in progress"); final String FEATURES = "http://xml.org/sax/features/"; final String PROPERTIES = "http://xml.org/sax/properties/"; - if ((FEATURES + "namespaces").equals(name) || - (FEATURES + "namespace-prefixes").equals(name)) + if ((FEATURES + "namespaces").equals(name)) namespaceAware = Boolean.TRUE.equals(value); + else if ((FEATURES + "namespace-prefixes").equals(name)) + { + // NOOP + } else if ((FEATURES + "string-interning").equals(name)) stringInterning = Boolean.TRUE.equals(value); else if ((FEATURES + "use-attributes2").equals(name)) @@ -178,9 +181,10 @@ final String GNU_PROPERTIES = "http://gnu.org/sax/properties/"; if ((FEATURES + "is-standalone").equals(name)) return xmlStandalone ? Boolean.TRUE : Boolean.FALSE; - if ((FEATURES + "namespaces").equals(name) || - (FEATURES + "namespace-prefixes").equals(name)) + if ((FEATURES + "namespaces").equals(name)) return namespaceAware ? Boolean.TRUE : Boolean.FALSE; + if ((FEATURES + "namespace-prefixes").equals(name)) + return Boolean.TRUE; if ((FEATURES + "string-interning").equals(name)) return stringInterning ? Boolean.TRUE : Boolean.FALSE; if ((FEATURES + "use-attributes2").equals(name)) @@ -454,6 +458,20 @@ contentHandler.processingInstruction(target, data); } break; + case XMLStreamConstants.START_ENTITY: + if (lexicalHandler != null) + { + String name = reader.getText(); + lexicalHandler.startEntity(name); + } + break; + case XMLStreamConstants.END_ENTITY: + if (lexicalHandler != null) + { + String name = reader.getText(); + lexicalHandler.endEntity(name); + } + break; case XMLStreamConstants.START_DOCUMENT: encoding = reader.getEncoding(); xmlVersion = reader.getVersion(); Index: gnu/xml/stream/XMLParser.java =================================================================== RCS file: /cvsroot/classpath/classpath/gnu/xml/stream/XMLParser.java,v retrieving revision 1.14 diff -u -r1.14 XMLParser.java --- gnu/xml/stream/XMLParser.java 29 Dec 2005 17:28:05 -0000 1.14 +++ gnu/xml/stream/XMLParser.java 31 Dec 2005 10:27:01 -0000 @@ -212,7 +212,7 @@ ids = new HashSet(); idrefs = new HashSet(); } - pushInput(new Input(in, null, systemId, null)); + pushInput(new Input(in, null, null, systemId, null, null, false)); } public XMLParser(Reader reader, String systemId, @@ -243,7 +243,7 @@ ids = new HashSet(); idrefs = new HashSet(); } - pushInput(new Input(null, reader, null, systemId, null)); + pushInput(new Input(null, reader, null, systemId, null, null, false)); } // -- NamespaceContext -- @@ -1202,7 +1202,7 @@ /** * Push the specified text input source. */ - private void pushInput(String name, String text) + private void pushInput(String name, String text, boolean report) throws IOException, XMLStreamException { // Check for recursion @@ -1216,15 +1216,15 @@ } } else - startEntityStack.addFirst(name); + report = false; pushInput(new Input(null, new StringReader(text), input.publicId, - input.systemId, name, input.inputEncoding)); + input.systemId, name, input.inputEncoding, report)); } /** * Push the specified external input source. */ - private void pushInput(String name, ExternalIds ids) + private void pushInput(String name, ExternalIds ids, boolean report) throws IOException, XMLStreamException { if (!externalEntities) @@ -1250,8 +1250,8 @@ if (name != null && !"".equals(name) && name.equals(ctx.name)) error("entities may not be self-recursive", name); } - if (name != null && !"".equals(name)) - startEntityStack.addFirst(name); + if (name == null || "".equals(name)) + report = false; if (in == null && url != null && resolver != null) { if (resolver instanceof XMLResolver2) @@ -1270,7 +1270,7 @@ } else { - pushInput(new Input(in, ids.publicId, url, name, null)); + pushInput(new Input(in, null, ids.publicId, url, name, null, report)); input.init(); if (tryRead(TEST_XML_DECL)) readTextDecl(); @@ -1280,6 +1280,8 @@ private void pushInput(Input input) { + if (input.report) + startEntityStack.addFirst(input.name); inputStack.addLast(input); if (this.input != null) input.xml11 = this.input.xml11; @@ -1371,7 +1373,7 @@ private void popInput() { Input old = (Input) inputStack.removeLast(); - if (!"".equals(old.name)) + if (old.report) endEntityStack.addFirst(old.name); input = (Input) inputStack.getLast(); } @@ -1495,8 +1497,8 @@ // Parse external subset if (ids.systemId != null && externalEntities) { - pushInput("", ">"); - pushInput("[dtd]", ids); + pushInput("", ">", false); + pushInput("[dtd]", ids, true); // loop until we get back to ">" while (true) { @@ -2747,7 +2749,7 @@ // expandEntity(entityName, false); //report start-entity //else // reset(); // report reference - pushInput("", "&" + entityName + ";"); + pushInput("", "&" + entityName + ";", false); done = true; break; } @@ -2834,12 +2836,12 @@ String text = (String) value; if (inAttr && text.indexOf('<') != -1) error("< in attribute value"); - pushInput(name, text); + pushInput(name, text, !inAttr); } else if (inAttr) error("reference to external entity in attribute value", name); else - pushInput(name, (ExternalIds) value); + pushInput(name, (ExternalIds) value, !inAttr); return; } } @@ -2946,23 +2948,20 @@ else { 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; - } + //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 - error("parser is configured not to replace entity " + - "references"); + expandEntity(entityName, + (flags & LIT_ATTRIBUTE) != 0); + entities = true; + continue; + // } } } break; @@ -3063,13 +3062,13 @@ } if (entity instanceof String) { - pushInput(name, (String) entity); + pushInput(name, (String) entity, false); //pushInput(name, " " + (String) entity + " "); } else { //pushInput("", " "); - pushInput(name, (ExternalIds) entity); + pushInput(name, (ExternalIds) entity, false); //pushInput("", " "); } } @@ -4255,6 +4254,7 @@ int column, markColumn; int offset, markOffset; final String publicId, systemId, name; + final boolean report; // report start- and end-entity InputStream in; Reader reader; @@ -4263,25 +4263,8 @@ String inputEncoding; boolean xml11; - Input(InputStream in, String publicId, String systemId, String name) - { - this(in, null, publicId, systemId, name, null); - } - - Input(InputStream in, String publicId, String systemId, String name, - String inputEncoding) - { - this(in, null, publicId, systemId, name, inputEncoding); - } - - Input(InputStream in, Reader reader, String publicId, String systemId, - String name) - { - this(in, reader, publicId, systemId, name, null); - } - Input(InputStream in, Reader reader, String publicId, String systemId, - String name, String inputEncoding) + String name, String inputEncoding, boolean report) { if (inputEncoding == null) inputEncoding = "UTF-8"; @@ -4289,6 +4272,7 @@ this.publicId = publicId; this.systemId = systemId; this.name = name; + this.report = report; if (in != null) { if (reader != null)
pgpTg3AdkTbgz.pgp
Description: PGP signature
_______________________________________________ Classpath-patches mailing list Classpath-patches@gnu.org http://lists.gnu.org/mailman/listinfo/classpath-patches