Fixing some of our XSLT implementation issues.

These changes move our XSLT code to passing 1898/3173 of the OASIS tests.
To contrast, the RI passes 2105/3173 tests.

Highlights:
  - Implementing getTextContent() for nodes
  - Removing validation during transforms. We don't support validation!
  - Fixing attribute constraints to match the spec
  - Fixing test suite to not confuse BaseURI from NamespaceURI
diff --git a/libcore/xml/src/main/java/org/apache/harmony/xml/dom/AttrImpl.java b/libcore/xml/src/main/java/org/apache/harmony/xml/dom/AttrImpl.java
index 9c19835..59a8b78 100644
--- a/libcore/xml/src/main/java/org/apache/harmony/xml/dom/AttrImpl.java
+++ b/libcore/xml/src/main/java/org/apache/harmony/xml/dom/AttrImpl.java
@@ -159,11 +159,12 @@
         }
         
         if (prefix != null) {
-            if (namespaceURI == null || !document.isXMLIdentifier(prefix) || "xmlns".equals(prefix)) {
-                throw new DOMException(DOMException.NAMESPACE_ERR, prefix);
-            }
-
-            if ("xml".equals(prefix) && !"http://www.w3.org/XML/1998/namespace".equals(namespaceURI)) {
+            if (namespaceURI == null
+                    || !DocumentImpl.isXMLIdentifier(prefix)
+                    || ("xmlns".equals(prefix)
+                            && !"http://www.w3.org/2000/xmlns/".equals(namespaceURI))
+                    || ("xml".equals(prefix)
+                            && !"http://www.w3.org/XML/1998/namespace".equals(namespaceURI))) {
                 throw new DOMException(DOMException.NAMESPACE_ERR, prefix);
             }
         }
diff --git a/libcore/xml/src/main/java/org/apache/harmony/xml/dom/DocumentImpl.java b/libcore/xml/src/main/java/org/apache/harmony/xml/dom/DocumentImpl.java
index 499f518..d6d412b 100644
--- a/libcore/xml/src/main/java/org/apache/harmony/xml/dom/DocumentImpl.java
+++ b/libcore/xml/src/main/java/org/apache/harmony/xml/dom/DocumentImpl.java
@@ -296,6 +296,10 @@
         return super.insertChildAt(newChild, index);
     }
 
+    @Override public String getTextContent() throws DOMException {
+        return null;
+    }
+
     public String getInputEncoding() {
         throw new UnsupportedOperationException(); // TODO
     }
diff --git a/libcore/xml/src/main/java/org/apache/harmony/xml/dom/DocumentTypeImpl.java b/libcore/xml/src/main/java/org/apache/harmony/xml/dom/DocumentTypeImpl.java
index df40d4b..67947b7 100644
--- a/libcore/xml/src/main/java/org/apache/harmony/xml/dom/DocumentTypeImpl.java
+++ b/libcore/xml/src/main/java/org/apache/harmony/xml/dom/DocumentTypeImpl.java
@@ -107,4 +107,7 @@
         return systemId;
     }
 
+    @Override public String getTextContent() throws DOMException {
+        return null;
+    }
 }
diff --git a/libcore/xml/src/main/java/org/apache/harmony/xml/dom/InnerNodeImpl.java b/libcore/xml/src/main/java/org/apache/harmony/xml/dom/InnerNodeImpl.java
index f8ed85e..82cd25e 100644
--- a/libcore/xml/src/main/java/org/apache/harmony/xml/dom/InnerNodeImpl.java
+++ b/libcore/xml/src/main/java/org/apache/harmony/xml/dom/InnerNodeImpl.java
@@ -218,4 +218,35 @@
         return oldChildImpl;
     }
 
+    public String getTextContent() throws DOMException {
+        Node child = getFirstChild();
+        if (child == null) {
+            return "";
+        }
+
+        Node next = child.getNextSibling();
+        if (next == null) {
+            return hasTextContent(child) ? child.getTextContent() : "";
+        }
+
+        StringBuilder buf = new StringBuilder();
+        getTextContent(buf);
+        return buf.toString();
+    }
+
+    void getTextContent(StringBuilder buf) throws DOMException {
+        Node child = getFirstChild();
+        while (child != null) {
+            if (hasTextContent(child)) {
+                ((NodeImpl) child).getTextContent(buf);
+            }
+            child = child.getNextSibling();
+        }
+    }
+
+    final boolean hasTextContent(Node child) {
+        // TODO: skip text nodes with ignorable whitespace?
+        return child.getNodeType() != Node.COMMENT_NODE
+                && child.getNodeType() != Node.PROCESSING_INSTRUCTION_NODE;
+    }
 }
diff --git a/libcore/xml/src/main/java/org/apache/harmony/xml/dom/NodeImpl.java b/libcore/xml/src/main/java/org/apache/harmony/xml/dom/NodeImpl.java
index bf4d791..b752506 100644
--- a/libcore/xml/src/main/java/org/apache/harmony/xml/dom/NodeImpl.java
+++ b/libcore/xml/src/main/java/org/apache/harmony/xml/dom/NodeImpl.java
@@ -190,7 +190,7 @@
     }
 
     public String getBaseURI() {
-        throw new UnsupportedOperationException(); // TODO
+        return null; // TODO
     }
 
     public short compareDocumentPosition(Node other)
@@ -199,7 +199,14 @@
     }
 
     public String getTextContent() throws DOMException {
-        throw new UnsupportedOperationException(); // TODO
+        return getNodeValue();
+    }
+
+    void getTextContent(StringBuilder buf) throws DOMException {
+        String content = getNodeValue();
+        if (content != null) {
+            buf.append(content);
+        }
     }
 
     public void setTextContent(String textContent) throws DOMException {
diff --git a/libcore/xml/src/main/java/org/apache/xml/utils/DOMHelper.java b/libcore/xml/src/main/java/org/apache/xml/utils/DOMHelper.java
index 76721d0..53d0adc 100644
--- a/libcore/xml/src/main/java/org/apache/xml/utils/DOMHelper.java
+++ b/libcore/xml/src/main/java/org/apache/xml/utils/DOMHelper.java
@@ -85,16 +85,23 @@
       DocumentBuilderFactory dfactory = DocumentBuilderFactory.newInstance();
 
       dfactory.setNamespaceAware(true);
-      dfactory.setValidating(true);
-      
-      if (isSecureProcessing)
-      {
-        try
-        {
-          dfactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
-        }
-        catch (ParserConfigurationException pce) {}
-      }
+      // BEGIN android-removed
+      //     If set, DocumentBuilderFactoryImpl.newDocumentBuilder() fails
+      //     because we haven't implemented validation
+      // dfactory.setValidating(true);
+      // BEGIN android-removed
+
+      // BEGIN android-removed
+      //     We haven't implemented secure processing
+      // if (isSecureProcessing)
+      // {
+      //   try
+      //   {
+      //     dfactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
+      //   }
+      //   catch (ParserConfigurationException pce) {}
+      // }
+      // END android-removed
       
       DocumentBuilder docBuilder = dfactory.newDocumentBuilder();
       Document outNode = docBuilder.newDocument();
diff --git a/libcore/xml/src/test/java/org/apache/harmony/xml/XsltXPathConformanceTestSuite.java b/libcore/xml/src/test/java/org/apache/harmony/xml/XsltXPathConformanceTestSuite.java
index 7773814..443e415 100644
--- a/libcore/xml/src/test/java/org/apache/harmony/xml/XsltXPathConformanceTestSuite.java
+++ b/libcore/xml/src/test/java/org/apache/harmony/xml/XsltXPathConformanceTestSuite.java
@@ -78,7 +78,7 @@
     /** Orders element attributes by optional URI and name. */
     private static final Comparator<Attr> orderByName = new Comparator<Attr>() {
         public int compare(Attr a, Attr b) {
-            int result = compareNullsFirst(a.getBaseURI(), b.getBaseURI());
+            int result = compareNullsFirst(a.getNamespaceURI(), b.getNamespaceURI());
             return result == 0 ? result
                     : compareNullsFirst(a.getName(), b.getName());
         }
@@ -322,6 +322,11 @@
             this.compareAs = compareAs;
         }
 
+        XsltTest(File principalData, File principalStylesheet, File principal) {
+            this("standalone", "test", "", "",
+                    principalData, principalStylesheet, principal, "standard", "XML");
+        }
+
         public void test() throws Exception {
             if (purpose != null) {
                 System.out.println("Purpose: " + purpose);
@@ -336,8 +341,8 @@
             Transformer transformer;
             try {
                 transformer = transformerFactory.newTransformer(xslt);
-                assertEquals("Expected transformer creation to fail",
-                        "standard", operation);
+                assertEquals("Transformer creation completed normally.",
+                        operation, "standard");
             } catch (TransformerConfigurationException e) {
                 if (operation.equals("execution-error")) {
                     return; // expected, such as in XSLT-Result-Tree.Attributes__78369
@@ -396,14 +401,17 @@
     }
 
     private void emitNode(XmlSerializer serializer, Node node) throws IOException {
-        if (node instanceof Element) {
+        if (node == null) {
+            throw new UnsupportedOperationException("Cannot emit null nodes");
+
+        } else if (node.getNodeType() == Node.ELEMENT_NODE) {
             Element element = (Element) node;
-            serializer.startTag(element.getBaseURI(), element.getLocalName());
+            serializer.startTag(element.getNamespaceURI(), element.getLocalName());
             emitAttributes(serializer, element);
             emitChildren(serializer, element);
-            serializer.endTag(element.getBaseURI(), element.getLocalName());
+            serializer.endTag(element.getNamespaceURI(), element.getLocalName());
 
-        } else if (node instanceof Text) {
+        } else if (node.getNodeType() == Node.TEXT_NODE) {
             // TODO: is it okay to trim whitespace in general? This may cause
             //     false positives for elements like HTML's <pre> tag
             String trimmed = node.getTextContent().trim();
@@ -411,25 +419,24 @@
                 serializer.text(trimmed);
             }
 
-        } else if (node instanceof Document) {
+        } else if (node.getNodeType() == Node.DOCUMENT_NODE) {
             Document document = (Document) node;
             serializer.startDocument("UTF-8", true);
             emitNode(serializer, document.getDocumentElement());
             serializer.endDocument();
 
-        } else if (node instanceof ProcessingInstruction) {
+        } else if (node.getNodeType() == Node.PROCESSING_INSTRUCTION_NODE) {
             ProcessingInstruction processingInstruction = (ProcessingInstruction) node;
             String data = processingInstruction.getData();
             String target = processingInstruction.getTarget();
             serializer.processingInstruction(target + " " + data);
 
-        } else if (node instanceof Comment) {
+        } else if (node.getNodeType() == Node.COMMENT_NODE) {
             // ignore!
 
         } else {
-            Object nodeClass = node != null ? node.getClass() : null;
             throw new UnsupportedOperationException(
-                    "Cannot serialize nodes of type " + nodeClass);
+                    "Cannot emit " + node + " of type " + node.getNodeType());
         }
     }
 
@@ -458,7 +465,7 @@
                  * generate one for us, using a predictable pattern.
                  */
             } else {
-                serializer.attribute(attr.getBaseURI(), attr.getLocalName(), attr.getValue());
+                serializer.attribute(attr.getNamespaceURI(), attr.getLocalName(), attr.getValue());
             }
         }
     }