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 [email protected] http://lists.gnu.org/mailman/listinfo/classpath-patches
