Reviewers: metaweta,

Description:
DOMs created in non-namespace aware mode treat xmlns has yet another
attribute.
This change recognizes the xmlns attribute and creates a namespaced
element instead
of trying to create an attribute called xmlns.

Please review this at http://codereview.appspot.com/3791041/

Affected files:
  M     src/com/google/caja/plugin/PluginMessageType.java
  M     src/com/google/caja/plugin/stages/LegacyNamespaceFixupStage.java
M tests/com/google/caja/plugin/stages/LegacyNamespaceFixupStageTest.java


Index: tests/com/google/caja/plugin/stages/LegacyNamespaceFixupStageTest.java
===================================================================
--- tests/com/google/caja/plugin/stages/LegacyNamespaceFixupStageTest.java (revision 4337) +++ tests/com/google/caja/plugin/stages/LegacyNamespaceFixupStageTest.java (working copy)
@@ -17,6 +17,7 @@
 import com.google.caja.lexer.InputSource;
 import com.google.caja.parser.html.Dom;
 import com.google.caja.parser.html.DomParser;
+import com.google.caja.parser.html.Namespaces;
 import com.google.caja.plugin.Job;
 import com.google.caja.plugin.JobEnvelope;
 import com.google.caja.plugin.Jobs;
@@ -66,6 +67,37 @@
     assertTrue(mq.getMessages().isEmpty());
   }

+  public final void testNoXmlnsAttr() {
+    assertFixed(
+        ""
+        + "<a href=\"bar.html\">Foo</a>",
+        builder().open("a").attr("href", "bar.html")
+            .text("Foo").close().job());
+    assertTrue(mq.getMessages().isEmpty());
+  }
+
+  public final void testSameXmlnsAttr() {
+    assertFixed(
+        ""
+        + "<a href=\"bar.html\">Foo</a>",
+        builder().open("a").attr("href", "bar.html")
+        .attr("xmlns", Namespaces.HTML_NAMESPACE_URI).text("Foo")
+        .close().job());
+    assertTrue(mq.getMessages().isEmpty());
+  }
+
+  public final void testNewXmlnsAttr() {
+    assertFixed(
+        ""
+        + "<a href=\"bar.html\">Foo</a>",
+        builder().open("a").attr("href", "bar.html")
+            .attr("xmlns", "http://foo.com";).text("Foo").close().job());
+    assertMessage(
+ true, PluginMessageType.CONFLICTING_XML_NAMESPACE, MessageLevel.WARNING,
+        MessagePart.Factory.valueOf("a"));
+    assertTrue(mq.getMessages().isEmpty());
+  }
+
   public final void testPrefixedAttribWithUnknownPrefix() {
     assertFixed(
         ""
Index: src/com/google/caja/plugin/PluginMessageType.java
===================================================================
--- src/com/google/caja/plugin/PluginMessageType.java   (revision 4337)
+++ src/com/google/caja/plugin/PluginMessageType.java   (working copy)
@@ -101,6 +101,9 @@
       "%s: specialized CSS property %s to %s", MessageLevel.WARNING),
   MISSING_XML_NAMESPACE(
       "%s: XML %s has prefix but no namespace", MessageLevel.ERROR),
+  CONFLICTING_XML_NAMESPACE(
+          "%s: Overriding unexpected xmlns attr %s with %s in element %s",
+          MessageLevel.WARNING),
INVALID_PIPELINE("Cannot find plan from %s to %s", MessageLevel.FATAL_ERROR),
   ;

Index: src/com/google/caja/plugin/stages/LegacyNamespaceFixupStage.java
===================================================================
--- src/com/google/caja/plugin/stages/LegacyNamespaceFixupStage.java (revision 4337) +++ src/com/google/caja/plugin/stages/LegacyNamespaceFixupStage.java (working copy)
@@ -112,13 +112,26 @@
     private void fixAttr(String elNsUri, Attr a) {
       Element e = a.getOwnerElement();
       String ns = guessNamespaceAndWarn(elNsUri, a);
-      Attr newA = a.getOwnerDocument().createAttributeNS(ns, a.getName());
-      newA.setNodeValue(a.getValue());
-      Nodes.setFilePositionFor(newA, Nodes.getFilePositionFor(a));
- Nodes.setFilePositionForValue(newA, Nodes.getFilePositionForValue(a));
-      Nodes.setRawValue(newA, Nodes.getRawValue(a));
-      e.removeAttributeNode(a);
-      e.setAttributeNodeNS(newA);
+      if ("xmlns".equals(a.getName())) {
+        e.removeAttributeNode(a);
+        if (!a.getValue().equals(ns)) {
+          mq.addMessage(
+ PluginMessageType.CONFLICTING_XML_NAMESPACE, MessageLevel.WARNING,
+              Nodes.getFilePositionFor(a),
+              MessagePart.Factory.valueOf(a.getValue()),
+              MessagePart.Factory.valueOf(ns),
+              MessagePart.Factory.valueOf(e.getNodeName()));
+        }
+        e.getOwnerDocument().renameNode(e, ns, e.getNodeName());
+      } else {
+ Attr newA = a.getOwnerDocument().createAttributeNS(ns, a.getName());
+        newA.setNodeValue(a.getValue());
+        Nodes.setFilePositionFor(newA, Nodes.getFilePositionFor(a));
+ Nodes.setFilePositionForValue(newA, Nodes.getFilePositionForValue(a));
+        Nodes.setRawValue(newA, Nodes.getRawValue(a));
+        e.removeAttributeNode(a);
+        e.setAttributeNodeNS(newA);
+      }
     }

     private String guessNamespaceAndWarn(String defaultNsUri, Node n) {


Reply via email to