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)

Attachment: pgpTg3AdkTbgz.pgp
Description: PGP signature

_______________________________________________
Classpath-patches mailing list
Classpath-patches@gnu.org
http://lists.gnu.org/mailman/listinfo/classpath-patches

Reply via email to