You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@freemarker.apache.org by dd...@apache.org on 2017/05/21 21:34:57 UTC

[2/6] incubator-freemarker git commit: Factored out freemarker-dom from freemarker-core. Also added mechanism to "inject" DOM wrapping capability into DefaultObjectWrapper on configuration time. See details below.

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/be556897/freemarker-dom/src/main/java/org/apache/freemarker/dom/package.html
----------------------------------------------------------------------
diff --git a/freemarker-dom/src/main/java/org/apache/freemarker/dom/package.html b/freemarker-dom/src/main/java/org/apache/freemarker/dom/package.html
new file mode 100644
index 0000000..61b1737
--- /dev/null
+++ b/freemarker-dom/src/main/java/org/apache/freemarker/dom/package.html
@@ -0,0 +1,30 @@
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+<html>
+<head>
+<title></title>
+</head>
+<body>
+
+<p>Exposes DOM XML nodes to templates as easily traversable trees;
+see <a href="http://freemarker.org/docs/xgui.html" target="_blank">in the Manual</a>.
+The default object wrapper of FreeMarker can automatically wraps W3C nodes with this.
+
+</body>
+</html>

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/be556897/freemarker-dom/src/test/java/org/apache/freemarker/dom/DOMSiblingTest.java
----------------------------------------------------------------------
diff --git a/freemarker-dom/src/test/java/org/apache/freemarker/dom/DOMSiblingTest.java b/freemarker-dom/src/test/java/org/apache/freemarker/dom/DOMSiblingTest.java
new file mode 100644
index 0000000..ed6d7bb
--- /dev/null
+++ b/freemarker-dom/src/test/java/org/apache/freemarker/dom/DOMSiblingTest.java
@@ -0,0 +1,97 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.freemarker.dom;
+
+import java.io.IOException;
+
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.apache.freemarker.core.TemplateException;
+import org.apache.freemarker.dom.test.DOMLoader;
+import org.apache.freemarker.test.TemplateTest;
+import org.junit.Before;
+import org.junit.Test;
+import org.xml.sax.SAXException;
+
+public class DOMSiblingTest extends TemplateTest {
+
+    @Before
+    public void setUp() throws SAXException, IOException, ParserConfigurationException {
+        addToDataModel("doc", DOMLoader.toModel(getClass(),"DOMSiblingTest.xml"));
+    }
+
+    @Test
+    public void testBlankPreviousSibling() throws IOException, TemplateException {
+        assertOutput("${doc.person.name?previousSibling}", "\n    ");
+        assertOutput("${doc.person.name?previous_sibling}", "\n    ");
+    }
+
+    @Test
+    public void testNonBlankPreviousSibling() throws IOException, TemplateException {
+        assertOutput("${doc.person.address?previousSibling}", "12th August");
+    }
+
+    @Test
+    public void testBlankNextSibling() throws IOException, TemplateException {
+        assertOutput("${doc.person.name?nextSibling}", "\n    ");
+        assertOutput("${doc.person.name?next_sibling}", "\n    ");
+    }
+
+    @Test
+    public void testNonBlankNextSibling() throws IOException, TemplateException {
+        assertOutput("${doc.person.dob?nextSibling}", "Chennai, India");
+    }
+
+    @Test
+    public void testNullPreviousSibling() throws IOException, TemplateException {
+        assertOutput("${doc.person?previousSibling?? ?c}", "false");
+    }
+
+    @Test
+    public void testSignificantPreviousSibling() throws IOException, TemplateException {
+        assertOutput("${doc.person.name.@@previous_sibling_element}", "male");
+    }
+
+    @Test
+    public void testSignificantNextSibling() throws IOException, TemplateException {
+        assertOutput("${doc.person.name.@@next_sibling_element}", "12th August");
+    }
+
+    @Test
+    public void testNullSignificantPreviousSibling() throws IOException, TemplateException {
+        assertOutput("${doc.person.phone.@@next_sibling_element?size}", "0");
+    }
+
+    @Test
+    public void testSkippingCommentNode() throws IOException, TemplateException {
+        assertOutput("${doc.person.profession.@@previous_sibling_element}", "Chennai, India");
+    }
+
+    @Test
+    public void testSkippingEmptyCDataNode() throws IOException, TemplateException {
+        assertOutput("${doc.person.hobby.@@previous_sibling_element}", "Software Engineer");
+    }
+
+    @Test
+    public void testValidCDataNode() throws IOException, TemplateException {
+        assertOutput("${doc.person.phone.@@previous_sibling_element?size}", "0");
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/be556897/freemarker-dom/src/test/java/org/apache/freemarker/dom/DOMSimplifiersTest.java
----------------------------------------------------------------------
diff --git a/freemarker-dom/src/test/java/org/apache/freemarker/dom/DOMSimplifiersTest.java b/freemarker-dom/src/test/java/org/apache/freemarker/dom/DOMSimplifiersTest.java
new file mode 100644
index 0000000..d8004fb
--- /dev/null
+++ b/freemarker-dom/src/test/java/org/apache/freemarker/dom/DOMSimplifiersTest.java
@@ -0,0 +1,201 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.freemarker.dom;
+
+import static org.junit.Assert.*;
+
+import java.io.IOException;
+
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.apache.freemarker.dom.test.DOMLoader;
+import org.junit.Test;
+import org.w3c.dom.CDATASection;
+import org.w3c.dom.Comment;
+import org.w3c.dom.Document;
+import org.w3c.dom.DocumentType;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.ProcessingInstruction;
+import org.w3c.dom.Text;
+import org.xml.sax.SAXException;
+
+public class DOMSimplifiersTest {
+
+    private static final String COMMON_TEST_XML
+            = "<!DOCTYPE a []><?p?><a>x<![CDATA[y]]><!--c--><?p?>z<?p?><b><!--c--></b><c></c>"
+              + "<d>a<e>c</e>b<!--c--><!--c--><!--c--><?p?><?p?><?p?></d>"
+              + "<f><![CDATA[1]]>2</f></a><!--c-->";
+
+    private static final String TEXT_MERGE_CONTENT =
+            "<a>"
+            + "a<!--c--><s/>"
+            + "<!--c-->a<s/>"
+            + "a<!--c-->b<s/>"
+            + "<!--c-->a<!--c-->b<!--c--><s/>"
+            + "a<b>b</b>c<s/>"
+            + "a<b>b</b><!--c-->c<s/>"
+            + "a<!--c-->1<b>b<!--c--></b>c<!--c-->1<s/>"
+            + "a<!--c-->1<b>b<!--c-->c</b>d<!--c-->1<s/>"
+            + "a<!--c-->1<b>b<!--c-->c</b>d<!--c-->1<s/>"
+            + "a<!--c-->1<b>b<!--c-->1<e>c<!--c-->1</e>d<!--c-->1</b>e<!--c-->1<s/>"
+            + "</a>";
+    private static final String TEXT_MERGE_EXPECTED =
+            "<a>"
+            + "%a<s/>"
+            + "%a<s/>"
+            + "%ab<s/>"
+            + "%ab<s/>"
+            + "%a<b>%b</b>%c<s/>"
+            + "%a<b>%b</b>%c<s/>"
+            + "%a1<b>%b</b>%c1<s/>"
+            + "%a1<b>%bc</b>%d1<s/>"
+            + "%a1<b>%bc</b>%d1<s/>"
+            + "%a1<b>%b1<e>%c1</e>%d1</b>%e1<s/>"
+            + "</a>";
+    
+    @Test
+    public void testTest() throws Exception {
+        String expected = "<!DOCTYPE ...><?p?><a>%x<![CDATA[y]]><!--c--><?p?>%z<?p?><b><!--c--></b><c/>"
+                   + "<d>%a<e>%c</e>%b<!--c--><!--c--><!--c--><?p?><?p?><?p?></d>"
+                   + "<f><![CDATA[1]]>%2</f></a><!--c-->";
+        assertEquals(expected, toString(DOMLoader.toDOM(COMMON_TEST_XML)));
+    }
+
+    @Test
+    public void testMergeAdjacentText() throws Exception {
+        Document dom = DOMLoader.toDOM(COMMON_TEST_XML);
+        NodeModel.mergeAdjacentText(dom);
+        assertEquals(
+                "<!DOCTYPE ...><?p?><a>%xy<!--c--><?p?>%z<?p?><b><!--c--></b><c/>"
+                + "<d>%a<e>%c</e>%b<!--c--><!--c--><!--c--><?p?><?p?><?p?></d>"
+                + "<f><![CDATA[12]]></f></a><!--c-->",
+                toString(dom));
+    }
+
+    @Test
+    public void testRemoveComments() throws Exception {
+        Document dom = DOMLoader.toDOM(COMMON_TEST_XML);
+        NodeModel.removeComments(dom);
+        assertEquals(
+                "<!DOCTYPE ...><?p?><a>%x<![CDATA[y]]><?p?>%z<?p?><b/><c/>"
+                + "<d>%a<e>%c</e>%b<?p?><?p?><?p?></d>"
+                + "<f><![CDATA[1]]>%2</f></a>",
+                toString(dom));
+    }
+
+    @Test
+    public void testRemovePIs() throws Exception {
+        Document dom = DOMLoader.toDOM(COMMON_TEST_XML);
+        NodeModel.removePIs(dom);
+        assertEquals(
+                "<!DOCTYPE ...><a>%x<![CDATA[y]]><!--c-->%z<b><!--c--></b><c/>"
+                + "<d>%a<e>%c</e>%b<!--c--><!--c--><!--c--></d>"
+                + "<f><![CDATA[1]]>%2</f></a><!--c-->",
+                toString(dom));
+    }
+    
+    @Test
+    public void testSimplify() throws Exception {
+        testSimplify(
+                "<!DOCTYPE ...><a>%xyz<b/><c/>"
+                + "<d>%a<e>%c</e>%b</d><f><![CDATA[12]]></f></a>",
+                COMMON_TEST_XML);
+    }
+
+    @Test
+    public void testSimplify2() throws Exception {
+        testSimplify(TEXT_MERGE_EXPECTED, TEXT_MERGE_CONTENT);
+    }
+
+    @Test
+    public void testSimplify3() throws Exception {
+        testSimplify("<a/>", "<a/>");
+    }
+    
+    private void testSimplify(String expected, String content)
+            throws SAXException, IOException, ParserConfigurationException {
+        {
+            Document dom = DOMLoader.toDOM(content);
+            NodeModel.simplify(dom);
+            assertEquals(expected, toString(dom));
+        }
+        
+        // Must be equivalent:
+        {
+            Document dom = DOMLoader.toDOM(content);
+            NodeModel.removeComments(dom);
+            NodeModel.removePIs(dom);
+            NodeModel.mergeAdjacentText(dom);
+            assertEquals(expected, toString(dom));
+        }
+        
+        // Must be equivalent:
+        {
+            Document dom = DOMLoader.toDOM(content);
+            NodeModel.removeComments(dom);
+            NodeModel.removePIs(dom);
+            NodeModel.simplify(dom);
+            assertEquals(expected, toString(dom));
+        }
+    }
+
+    private String toString(Document doc) {
+        StringBuilder sb = new StringBuilder();
+        toString(doc, sb);
+        return sb.toString();
+    }
+
+    private void toString(Node node, StringBuilder sb) {
+        if (node instanceof Document) {
+            childrenToString(node, sb);
+        } else if (node instanceof Element) {
+            if (node.hasChildNodes()) {
+                sb.append("<").append(node.getNodeName()).append(">");
+                childrenToString(node, sb);
+                sb.append("</").append(node.getNodeName()).append(">");
+            } else {
+                sb.append("<").append(node.getNodeName()).append("/>");
+            }
+        } else if (node instanceof Text) {
+            if (node instanceof CDATASection) {
+                sb.append("<![CDATA[").append(node.getNodeValue()).append("]]>");
+            } else {
+                sb.append("%").append(node.getNodeValue());
+            }
+        } else if (node instanceof Comment) {
+            sb.append("<!--").append(node.getNodeValue()).append("-->");
+        } else if (node instanceof ProcessingInstruction) {
+            sb.append("<?").append(node.getNodeName()).append("?>");
+        } else if (node instanceof DocumentType) {
+            sb.append("<!DOCTYPE ...>");
+        } else {
+            throw new IllegalStateException("Unhandled node type: " + node.getClass().getName());
+        }
+    }
+
+    private void childrenToString(Node node, StringBuilder sb) {
+        Node child = node.getFirstChild();
+        while (child != null) {
+            toString(child, sb);
+            child = child.getNextSibling();
+        }
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/be556897/freemarker-dom/src/test/java/org/apache/freemarker/dom/DOMTest.java
----------------------------------------------------------------------
diff --git a/freemarker-dom/src/test/java/org/apache/freemarker/dom/DOMTest.java b/freemarker-dom/src/test/java/org/apache/freemarker/dom/DOMTest.java
new file mode 100644
index 0000000..0d03dbe
--- /dev/null
+++ b/freemarker-dom/src/test/java/org/apache/freemarker/dom/DOMTest.java
@@ -0,0 +1,159 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.freemarker.dom;
+
+import static org.hamcrest.Matchers.*;
+import static org.junit.Assert.*;
+
+import java.io.IOException;
+import java.io.StringReader;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.apache.freemarker.core.TemplateException;
+import org.apache.freemarker.dom.test.DOMLoader;
+import org.apache.freemarker.test.TemplateTest;
+import org.junit.Test;
+import org.w3c.dom.Document;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+public class DOMTest extends TemplateTest {
+
+    @Test
+    public void xpathDetectionBugfix() throws Exception {
+        addDocToDataModel("<root><a>A</a><b>B</b><c>C</c></root>");
+        assertOutput("${doc.root.b['following-sibling::c']}", "C");
+        assertOutput("${doc.root.b['following-sibling::*']}", "C");
+    }
+
+    @Test
+    public void xmlnsPrefixes() throws Exception {
+        addDocToDataModel("<root xmlns='http://example.com/ns1' xmlns:ns2='http://example.com/ns2'>"
+                + "<a>A</a><ns2:b>B</ns2:b><c a1='1' ns2:a2='2'/></root>");
+
+        String ftlHeader = "<#ftl ns_prefixes={'D':'http://example.com/ns1', 'n2':'http://example.com/ns2'}>";
+        
+        // @@markup:
+        assertOutput("${doc.@@markup}",
+                "<a:root xmlns:a=\"http://example.com/ns1\" xmlns:b=\"http://example.com/ns2\">"
+                + "<a:a>A</a:a><b:b>B</b:b><a:c a1=\"1\" b:a2=\"2\" />"
+                + "</a:root>");
+        assertOutput(ftlHeader
+                + "${doc.@@markup}",
+                "<root xmlns=\"http://example.com/ns1\" xmlns:n2=\"http://example.com/ns2\">"
+                + "<a>A</a><n2:b>B</n2:b><c a1=\"1\" n2:a2=\"2\" /></root>");
+        assertOutput("<#ftl ns_prefixes={'D':'http://example.com/ns1'}>"
+                + "${doc.@@markup}",
+                "<root xmlns=\"http://example.com/ns1\" xmlns:a=\"http://example.com/ns2\">"
+                + "<a>A</a><a:b>B</a:b><c a1=\"1\" a:a2=\"2\" /></root>");
+        
+        // When there's no matching prefix declared via the #ftl header, return null for qname:
+        assertOutput("${doc?children[0].@@qname!'null'}", "null");
+        assertOutput("${doc?children[0]?children[1].@@qname!'null'}", "null");
+        assertOutput("${doc?children[0]?children[2]['@*'][1].@@qname!'null'}", "null");
+        
+        // When we have prefix declared in the #ftl header:
+        assertOutput(ftlHeader + "${doc?children[0].@@qname}", "root");
+        assertOutput(ftlHeader + "${doc?children[0]?children[1].@@qname}", "n2:b");
+        assertOutput(ftlHeader + "${doc?children[0]?children[2].@@qname}", "c");
+        assertOutput(ftlHeader + "${doc?children[0]?children[2]['@*'][0].@@qname}", "a1");
+        assertOutput(ftlHeader + "${doc?children[0]?children[2]['@*'][1].@@qname}", "n2:a2");
+        // Unfortunately these include the xmlns attributes, but that would be non-BC to fix now:
+        assertThat(getOutput(ftlHeader + "${doc?children[0].@@start_tag}"), startsWith("<root"));
+        assertThat(getOutput(ftlHeader + "${doc?children[0]?children[1].@@start_tag}"), startsWith("<n2:b"));
+    }
+    
+    @Test
+    public void namespaceUnaware() throws Exception {
+        addNSUnawareDocToDataModel("<root><x:a>A</x:a><:>B</:><xyz::c>C</xyz::c></root>");
+        assertOutput("${doc.root['x:a']}", "A");
+        assertOutput("${doc.root[':']}", "B");
+        try {
+            assertOutput("${doc.root['xyz::c']}", "C");
+            fail();
+        } catch (TemplateException e) {
+            assertThat(e.getMessage(), containsString("xyz"));
+        }
+    }
+    
+    private void addDocToDataModel(String xml) throws SAXException, IOException, ParserConfigurationException {
+        addToDataModel("doc", DOMLoader.toModel(new InputSource(new StringReader(xml))));
+    }
+
+    private void addDocToDataModelNoSimplification(String xml) throws SAXException, IOException, ParserConfigurationException {
+        addToDataModel("doc", DOMLoader.toModel(new InputSource(new StringReader(xml)), false));
+    }
+    
+    private void addNSUnawareDocToDataModel(String xml) throws ParserConfigurationException, SAXException, IOException {
+        DocumentBuilderFactory newFactory = DocumentBuilderFactory.newInstance();
+        newFactory.setNamespaceAware(false);
+        DocumentBuilder builder = newFactory.newDocumentBuilder();
+        Document doc = builder.parse(new InputSource(new StringReader(xml)));
+        addToDataModel("doc", NodeModel.wrap(doc));
+    }
+
+    @Test
+    public void testInvalidAtAtKeyErrors() throws Exception {
+        addDocToDataModel("<r><multipleMatches /><multipleMatches /></r>");
+        assertErrorContains("${doc.r.@@invalid_key}", "Unsupported @@ key", "@invalid_key");
+        assertErrorContains("${doc.@@start_tag}", "@@start_tag", "not supported", "document");
+        assertErrorContains("${doc.@@}", "\"@@\"", "not supported", "document");
+        assertErrorContains("${doc.r.noMatch.@@invalid_key}", "Unsupported @@ key", "@invalid_key");
+        assertErrorContains("${doc.r.multipleMatches.@@invalid_key}", "Unsupported @@ key", "@invalid_key");
+        assertErrorContains("${doc.r.noMatch.@@attributes_markup}", "single XML node", "@@attributes_markup");
+        assertErrorContains("${doc.r.multipleMatches.@@attributes_markup}", "single XML node", "@@attributes_markup");
+    }
+    
+    @Test
+    public void testAtAtSiblingElement() throws Exception {
+        addDocToDataModel("<r><a/><b/></r>");
+        assertOutput("${doc.r.@@previous_sibling_element?size}", "0");
+        assertOutput("${doc.r.@@next_sibling_element?size}", "0");
+        assertOutput("${doc.r.a.@@previous_sibling_element?size}", "0");
+        assertOutput("${doc.r.a.@@next_sibling_element.@@qname}", "b");
+        assertOutput("${doc.r.b.@@previous_sibling_element.@@qname}", "a");
+        assertOutput("${doc.r.b.@@next_sibling_element?size}", "0");
+        
+        addDocToDataModel("<r>\r\n\t <a/>\r\n\t <b/>\r\n\t </r>");
+        assertOutput("${doc.r.@@previous_sibling_element?size}", "0");
+        assertOutput("${doc.r.@@next_sibling_element?size}", "0");
+        assertOutput("${doc.r.a.@@previous_sibling_element?size}", "0");
+        assertOutput("${doc.r.a.@@next_sibling_element.@@qname}", "b");
+        assertOutput("${doc.r.b.@@previous_sibling_element.@@qname}", "a");
+        assertOutput("${doc.r.b.@@next_sibling_element?size}", "0");
+        
+        addDocToDataModel("<r>t<a/>t<b/>t</r>");
+        assertOutput("${doc.r.a.@@previous_sibling_element?size}", "0");
+        assertOutput("${doc.r.a.@@next_sibling_element?size}", "0");
+        assertOutput("${doc.r.b.@@previous_sibling_element?size}", "0");
+        assertOutput("${doc.r.b.@@next_sibling_element?size}", "0");
+        
+        addDocToDataModelNoSimplification("<r><a/> <!-- --><?pi?>&#x20;<b/></r>");
+        assertOutput("${doc.r.a.@@next_sibling_element.@@qname}", "b");
+        assertOutput("${doc.r.b.@@previous_sibling_element.@@qname}", "a");
+        
+        addDocToDataModelNoSimplification("<r><a/> <!-- -->t<!-- --> <b/></r>");
+        assertOutput("${doc.r.a.@@next_sibling_element?size}", "0");
+        assertOutput("${doc.r.b.@@previous_sibling_element?size}", "0");
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/be556897/freemarker-dom/src/test/java/org/apache/freemarker/dom/DefaultObjectWrapperExtensionTest.java
----------------------------------------------------------------------
diff --git a/freemarker-dom/src/test/java/org/apache/freemarker/dom/DefaultObjectWrapperExtensionTest.java b/freemarker-dom/src/test/java/org/apache/freemarker/dom/DefaultObjectWrapperExtensionTest.java
new file mode 100644
index 0000000..347980d
--- /dev/null
+++ b/freemarker-dom/src/test/java/org/apache/freemarker/dom/DefaultObjectWrapperExtensionTest.java
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.freemarker.dom;
+
+import static org.junit.Assert.*;
+
+import java.io.IOException;
+
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.apache.freemarker.core.Configuration;
+import org.apache.freemarker.core.TemplateException;
+import org.apache.freemarker.core.model.impl.DefaultObjectWrapper;
+import org.apache.freemarker.dom.test.DOMLoader;
+import org.apache.freemarker.test.TemplateTest;
+import org.apache.freemarker.test.TestConfigurationBuilder;
+import org.junit.Before;
+import org.junit.Test;
+import org.xml.sax.SAXException;
+
+public class DefaultObjectWrapperExtensionTest extends TemplateTest {
+
+    @Before
+    public void setup() throws ParserConfigurationException, SAXException, IOException {
+        addToDataModel("doc", DOMLoader.toDOM("<doc><title>test</title></doc>").getDocumentElement());
+    }
+
+    @Test
+    public void testWithExtensions() throws IOException, TemplateException {
+        setConfiguration(new TestConfigurationBuilder()
+                .objectWrapper(
+                        new DefaultObjectWrapper.Builder(Configuration.VERSION_3_0_0)
+                                .extensions(DOMDefaultObjectWrapperExtension.INSTANCE)
+                                .build()
+                )
+                .build());
+        assertOutput("${doc.title}", "test");
+    }
+
+    @Test
+    public void testWithoutExtensions() throws IOException, TemplateException {
+        try {
+            assertOutput("${doc.title}", "test");
+            fail();
+        } catch (TemplateException e) {
+            // Expected
+        }
+
+        assertOutput("${doc.getElementsByTagName('title').item(0).textContent}", "test");
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/be556897/freemarker-dom/src/test/java/org/apache/freemarker/dom/TypeErrorMessagesTest.java
----------------------------------------------------------------------
diff --git a/freemarker-dom/src/test/java/org/apache/freemarker/dom/TypeErrorMessagesTest.java b/freemarker-dom/src/test/java/org/apache/freemarker/dom/TypeErrorMessagesTest.java
new file mode 100644
index 0000000..b2f1304
--- /dev/null
+++ b/freemarker-dom/src/test/java/org/apache/freemarker/dom/TypeErrorMessagesTest.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.freemarker.dom;
+
+import org.apache.freemarker.dom.test.DOMLoader;
+import org.apache.freemarker.test.TemplateTest;
+import org.junit.Test;
+
+public class TypeErrorMessagesTest extends TemplateTest {
+
+    @Test
+    public void test() throws Exception {
+        addToDataModel("doc", DOMLoader.toModel("<a><b>123</b><c a='true'>1</c><c a='false'>2</c></a>"));
+
+        assertErrorContains("${doc.a.c}",
+                "used as string", "query result", "2", "multiple matches");
+        assertErrorContains("${doc.a.c?boolean}",
+                "used as string", "query result", "2", "multiple matches");
+        assertErrorContains("${doc.a.d}",
+                "used as string", "query result", "0", "no matches");
+        assertErrorContains("${doc.a.d?boolean}",
+                "used as string", "query result", "0", "no matches");
+
+        assertErrorContains("${doc.a.c.@a}",
+                "used as string", "query result", "2", "multiple matches");
+        assertErrorContains("${doc.a.d.@b}",
+                "used as string", "query result", "x", "no matches");
+
+        assertErrorContains("${doc.a.b * 2}",
+                "used as number", "text", "explicit conversion");
+        assertErrorContains("<#if doc.a.b></#if>",
+                "used as number", "text", "explicit conversion");
+
+        assertErrorContains("${doc.a.d?nodeName}",
+                "used as node", "query result", "0", "no matches");
+        assertErrorContains("${doc.a.c?nodeName}",
+                "used as node", "query result", "2", "multiple matches");
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/be556897/freemarker-dom/src/test/java/org/apache/freemarker/dom/templatesuite/DomTemplateTestSuite.java
----------------------------------------------------------------------
diff --git a/freemarker-dom/src/test/java/org/apache/freemarker/dom/templatesuite/DomTemplateTestSuite.java b/freemarker-dom/src/test/java/org/apache/freemarker/dom/templatesuite/DomTemplateTestSuite.java
new file mode 100644
index 0000000..e3a91e1
--- /dev/null
+++ b/freemarker-dom/src/test/java/org/apache/freemarker/dom/templatesuite/DomTemplateTestSuite.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.freemarker.dom.templatesuite;
+
+import java.util.Map;
+
+import org.apache.freemarker.core.Configuration;
+import org.apache.freemarker.dom.NodeModel;
+import org.apache.freemarker.dom.test.DOMLoader;
+import org.apache.freemarker.test.TemplateTestSuite;
+import org.w3c.dom.Document;
+
+import junit.framework.TestSuite;
+
+public class DomTemplateTestSuite extends TemplateTestSuite {
+
+    @Override
+    protected void setUpTestCase(String simpleTestName, Map<String, Object> dataModel,
+            Configuration.ExtendableBuilder<?> confB) throws Exception {
+        NodeModel.useJaxenXPathSupport();
+
+        if (simpleTestName.equals("default-xmlns")) {
+            dataModel.put("doc", DOMLoader.toModel(getClass(), "models/defaultxmlns1.xml"));
+        } else if (simpleTestName.equals("xml-fragment")) {
+            Document doc = DOMLoader.toDOM(getClass(), "models/xmlfragment.xml");
+            NodeModel.simplify(doc);
+            dataModel.put("node", NodeModel.wrap(doc.getDocumentElement().getFirstChild().getFirstChild()));
+        } else if (simpleTestName.equals("xmlns1")) {
+            dataModel.put("doc", DOMLoader.toModel(getClass(), "models/xmlns.xml"));
+        } else if (simpleTestName.equals("xmlns2")) {
+            dataModel.put("doc", DOMLoader.toModel(getClass(), "models/xmlns2.xml"));
+        } else if (simpleTestName.equals("xmlns3") || simpleTestName.equals("xmlns4")) {
+            dataModel.put("doc", DOMLoader.toModel(getClass(), "models/xmlns3.xml"));
+        } else if (simpleTestName.equals("xmlns5")) {
+            dataModel.put("doc", DOMLoader.toModel(getClass(), "models/defaultxmlns1.xml"));
+        } else if (simpleTestName.equals("xml-ns_prefix-scope")) {
+            dataModel.put("doc", DOMLoader.toModel(getClass(), "models/xml-ns_prefix-scope.xml"));
+        }
+    }
+
+    public static TestSuite suite() {
+        return new DomTemplateTestSuite();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/be556897/freemarker-dom/src/test/java/org/apache/freemarker/dom/test/DOMLoader.java
----------------------------------------------------------------------
diff --git a/freemarker-dom/src/test/java/org/apache/freemarker/dom/test/DOMLoader.java b/freemarker-dom/src/test/java/org/apache/freemarker/dom/test/DOMLoader.java
new file mode 100644
index 0000000..bc957c5
--- /dev/null
+++ b/freemarker-dom/src/test/java/org/apache/freemarker/dom/test/DOMLoader.java
@@ -0,0 +1,145 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.freemarker.dom.test;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.StringReader;
+import java.net.MalformedURLException;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.apache.freemarker.core.util._StringUtil;
+import org.apache.freemarker.dom.NodeModel;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+/**
+ * Utility to load XML resources into {@link Node}-s or {@link NodeModel}-s.
+ */
+public final class DOMLoader {
+
+    private static final Object STATIC_LOCK = new Object();
+    
+    static private DocumentBuilderFactory docBuilderFactory;
+    
+    private DOMLoader() {
+        //
+    }
+    
+    /**
+     * Convenience method to invoke a {@link NodeModel} from a SAX {@link InputSource}.
+     */
+    static public NodeModel toModel(InputSource is, boolean simplify)
+        throws SAXException, IOException, ParserConfigurationException {
+        DocumentBuilder builder = getDocumentBuilderFactory().newDocumentBuilder();
+        final Document doc;
+        try {
+            doc = builder.parse(is);
+        } catch (MalformedURLException e) {
+            // This typical error has an error message that is hard to understand, so let's translate it:
+            if (is.getSystemId() == null && is.getCharacterStream() == null && is.getByteStream() == null) {
+                throw new MalformedURLException(
+                        "The SAX InputSource has systemId == null && characterStream == null && byteStream == null. "
+                        + "This is often because it was created with a null InputStream or Reader, which is often because "
+                        + "the XML file it should point to was not found. "
+                        + "(The original exception was: " + e + ")");
+            } else {
+                throw e;
+            }
+        }
+        if (simplify) {
+            NodeModel.simplify(doc);
+        }
+        return NodeModel.wrap(doc);
+    }
+    
+    /**
+     * Same as {@link #toModel(InputSource, boolean) parse(is, true)}.
+     */
+    static public NodeModel toModel(InputSource is) throws SAXException, IOException, ParserConfigurationException {
+        return toModel(is, true);
+    }
+
+    static public NodeModel toModel(Class<?> baseClass, String resourcePath)
+            throws ParserConfigurationException, SAXException, IOException {
+        InputStream in = baseClass.getResourceAsStream(resourcePath);
+        if (in == null) {
+            throw new FileNotFoundException("Class loader resource not found: baseClass=" + baseClass.getName()
+                    + "; path=" + _StringUtil.jQuote(resourcePath));
+        }
+        return toModel(new InputSource(in));
+    }
+
+    /**
+     * Same as {@link #toModel(InputSource, boolean)}, but loads from a {@link File}; don't miss the security
+     * warnings documented there.
+     */
+    static public NodeModel toModel(String content, boolean simplify) 
+    throws SAXException, IOException, ParserConfigurationException {
+        return toModel(toInputSource(content));
+    }
+    
+    /**
+     * Same as {@link #toModel(InputSource, boolean) parse(source, true)}, but loads from a {@link String}.
+     */
+    static public NodeModel toModel(String content) throws SAXException, IOException, ParserConfigurationException {
+        return toModel(content, true);
+    }
+    
+    public static Document toDOM(String content) throws SAXException, IOException, ParserConfigurationException {
+        DocumentBuilder builder =  getDocumentBuilderFactory().newDocumentBuilder();
+        return builder.parse(toInputSource(content));
+    }
+
+    public static Document toDOM(Class<?> baseClass, String resourcePath) throws SAXException, IOException,
+            ParserConfigurationException {
+        DocumentBuilder builder =  getDocumentBuilderFactory().newDocumentBuilder();
+        InputStream in = baseClass.getResourceAsStream(resourcePath);
+        if (in == null) {
+            throw new FileNotFoundException("Class loader resource not found: baseClass="
+                    + baseClass.getName() + "; " + "path=" + _StringUtil.jQuote(resourcePath));
+        }
+        return builder.parse(new InputSource(in));
+    }
+
+    static private DocumentBuilderFactory getDocumentBuilderFactory() {
+        synchronized (STATIC_LOCK) {
+            if (docBuilderFactory == null) {
+                DocumentBuilderFactory newFactory = DocumentBuilderFactory.newInstance();
+                newFactory.setNamespaceAware(true);
+                newFactory.setIgnoringElementContentWhitespace(true);
+                docBuilderFactory = newFactory;  // We only write it out when the initialization was full 
+            }
+            return docBuilderFactory;
+        }
+    }
+
+    private static InputSource toInputSource(String content) {
+        return new InputSource(new StringReader(content));
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/be556897/freemarker-dom/src/test/resources/org/apache/freemarker/dom/DOMSiblingTest.xml
----------------------------------------------------------------------
diff --git a/freemarker-dom/src/test/resources/org/apache/freemarker/dom/DOMSiblingTest.xml b/freemarker-dom/src/test/resources/org/apache/freemarker/dom/DOMSiblingTest.xml
new file mode 100644
index 0000000..d1fe3dc
--- /dev/null
+++ b/freemarker-dom/src/test/resources/org/apache/freemarker/dom/DOMSiblingTest.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+<person>
+    <gender>male</gender>
+    <name>pradeep</name>
+    <dob>12th August</dob><address>Chennai, India</address>
+    <!--This is a comment Node -->
+    <?xml-stylesheet type="text/css" href="style.css"?>
+    <profession>Software Engineer</profession>
+    <![CDATA[    ]]>
+    <hobby>gardening</hobby>
+    <![CDATA[this is a valid cdata]]>
+    <phone>12345678</phone>
+</person>

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/be556897/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/expected/default-xmlns.txt
----------------------------------------------------------------------
diff --git a/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/expected/default-xmlns.txt b/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/expected/default-xmlns.txt
new file mode 100644
index 0000000..3a52c46
--- /dev/null
+++ b/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/expected/default-xmlns.txt
@@ -0,0 +1,25 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+No NS = No NS
+x NS = x NS
+y NS = y NS
+x NS = x NS
+
+true
+

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/be556897/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/expected/xml-fragment.txt
----------------------------------------------------------------------
diff --git a/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/expected/xml-fragment.txt b/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/expected/xml-fragment.txt
new file mode 100644
index 0000000..cb0da5f
--- /dev/null
+++ b/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/expected/xml-fragment.txt
@@ -0,0 +1,25 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+b = b
+@document = @document
+@document = @document
+
+C<>&"']]> = C<>&"']]>
+
+<root xmlns:n="http://x"><a><b><n:c>C&lt;>&amp;"']]&gt;</n:c></b></a></root>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/be556897/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/expected/xml-ns_prefix-scope.txt
----------------------------------------------------------------------
diff --git a/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/expected/xml-ns_prefix-scope.txt b/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/expected/xml-ns_prefix-scope.txt
new file mode 100644
index 0000000..bf8e6bd
--- /dev/null
+++ b/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/expected/xml-ns_prefix-scope.txt
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+//e: e in NS namespace-test, e in NS namespace-test
+//n:e: e in NS foo, e in NS foo
+//bar:e: e in NS bar, e in NS bar
+
+Included:
+//n:e: e in NS foo, e in NS foo
+//n:e: e in NS foo, e in NS foo
+
+Imported:
+//n:e: e in NS bar, e in NS bar
+//n:e: e in NS bar, e in NS bar

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/be556897/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/expected/xml.txt
----------------------------------------------------------------------
diff --git a/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/expected/xml.txt b/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/expected/xml.txt
new file mode 100644
index 0000000..718bba1
--- /dev/null
+++ b/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/expected/xml.txt
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+  <?firstPi customKey="something"?>
+  firstPi
+  customKey="something"
+  <?secondPi secondPiData?>
+  secondPi
+  secondPiData
+2
+p
+ customKey="something"
+
+<ns1:e11 xmlns:ns1="http://www.foo.com/ns1/">text1</ns1:e11><ns1:e11 xmlns:ns1="http://www.foo.com/ns1/">text2</ns1:e11>
+<ns1:e12 xmlns:ns1="http://www.foo.com/ns1/"><![CDATA[cdata-section1]]></ns1:e12><ns1:e12 xmlns:ns1="http://www.foo.com/ns1/"><![CDATA[cdata-section2<&]]></ns1:e12>
+<ns1:e1 xmlns:ns1="http://www.foo.com/ns1/" a1="v1" a2="v2">
+    <ns1:e11>text1</ns1:e11>
+    <ns1:e12><![CDATA[cdata-section1]]></ns1:e12>
+  </ns1:e1>
+<ns1:e11 xmlns:ns1="http://www.foo.com/ns1/">text1</ns1:e11><ns1:e11 xmlns:ns1="http://www.foo.com/ns1/">text2</ns1:e11>
+a1
+v2
+rootroot
+root
+  root
+  e1
+  e11
+  e12
+  e2
+  e11
+  e12
+  root
+  root
+  e1
+  root
+  e1
+  e11
+  root
+  e1
+  e12
+  root
+  e2
+  root
+  e2
+  e11
+  root
+  e2
+  e12
+cdata-section2&lt;&amp;
+cdata-section2<&

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/be556897/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/expected/xmlns1.txt
----------------------------------------------------------------------
diff --git a/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/expected/xmlns1.txt b/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/expected/xmlns1.txt
new file mode 100644
index 0000000..69af553
--- /dev/null
+++ b/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/expected/xmlns1.txt
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+<book xmlns="http://example.com/eBook">
+  <title>Test Book</title>
+  <chapter>
+    <title>Ch1</title>
+    <para>p1.1</para>
+    <para>p1.2</para>
+    <para>p1.3</para>
+  </chapter>
+  <chapter>
+    <title>Ch2</title>
+    <para>p2.1</para>
+    <para>p2.2</para>
+  </chapter>
+</book>
+
+  <html>
+    <head>
+      <title>Test Book</title>
+    </head>
+    <body>
+      <h1>Test Book</h1>
+
+  
+    <h2>Ch1</h2>
+
+    
+      <p>p1.1
+
+      <p>p1.2
+
+      <p>p1.3
+
+  
+    <h2>Ch2</h2>
+
+    
+      <p>p2.1
+
+      <p>p2.2
+
+  
+    </body>
+  </html>
+

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/be556897/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/expected/xmlns3.txt
----------------------------------------------------------------------
diff --git a/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/expected/xmlns3.txt b/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/expected/xmlns3.txt
new file mode 100644
index 0000000..f028f0a
--- /dev/null
+++ b/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/expected/xmlns3.txt
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+  <html>
+    <head>
+      <title>Test Book</title>
+    </head>
+    <body>
+      <h1>Test Book</h1>
+
+  
+    <h2>Ch1</h2>
+
+    
+      <p>p1.1
+
+      <p>p1.2
+
+      <p>p1.3
+
+  
+    <h2>Ch2</h2>
+
+    
+      <p>p2.1
+
+      <p>p2.2
+
+  
+    </body>
+  </html>
+

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/be556897/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/expected/xmlns4.txt
----------------------------------------------------------------------
diff --git a/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/expected/xmlns4.txt b/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/expected/xmlns4.txt
new file mode 100644
index 0000000..f028f0a
--- /dev/null
+++ b/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/expected/xmlns4.txt
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+  <html>
+    <head>
+      <title>Test Book</title>
+    </head>
+    <body>
+      <h1>Test Book</h1>
+
+  
+    <h2>Ch1</h2>
+
+    
+      <p>p1.1
+
+      <p>p1.2
+
+      <p>p1.3
+
+  
+    <h2>Ch2</h2>
+
+    
+      <p>p2.1
+
+      <p>p2.2
+
+  
+    </body>
+  </html>
+

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/be556897/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/expected/xmlns5.txt
----------------------------------------------------------------------
diff --git a/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/expected/xmlns5.txt b/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/expected/xmlns5.txt
new file mode 100644
index 0000000..6e42b09
--- /dev/null
+++ b/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/expected/xmlns5.txt
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+No NS = No NS
+x NS = x NS
+y NS = y NS
+x NS = x NS
+No NS = No NS
+- = -
+- = -
+- = -

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/be556897/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/models/defaultxmlns1.xml
----------------------------------------------------------------------
diff --git a/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/models/defaultxmlns1.xml b/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/models/defaultxmlns1.xml
new file mode 100644
index 0000000..ed289bb
--- /dev/null
+++ b/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/models/defaultxmlns1.xml
@@ -0,0 +1,24 @@
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+<root xmlns:x="http://x.com" xmlns:y="http://y.com">
+  <t1>No NS</t1>
+  <x:t2>x NS</x:t2>
+  <y:t3>y NS</y:t3>
+  <t4 xmlns="http://x.com">x NS</t4>
+</root>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/be556897/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/models/xml-ns_prefix-scope.xml
----------------------------------------------------------------------
diff --git a/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/models/xml-ns_prefix-scope.xml b/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/models/xml-ns_prefix-scope.xml
new file mode 100644
index 0000000..934acac
--- /dev/null
+++ b/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/models/xml-ns_prefix-scope.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+<root xmlns="http://freemarker.org/test/namespace-test"
+    xmlns:foo="http://freemarker.org/test/foo"
+    xmlns:bar="http://freemarker.org/test/bar">
+  <e>e in NS namespace-test</e>
+  <foo:e>e in NS foo</foo:e>
+  <bar:e>e in NS bar</bar:e>
+</root>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/be556897/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/models/xml.xml
----------------------------------------------------------------------
diff --git a/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/models/xml.xml b/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/models/xml.xml
new file mode 100644
index 0000000..abf7e96
--- /dev/null
+++ b/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/models/xml.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+<?firstPi customKey="something"?>
+<?secondPi secondPiData?>
+<ns1:root xmlns:ns1="http://www.foo.com/ns1/">
+  <ns1:e1 a1="v1" a2="v2">
+    <ns1:e11>text1</ns1:e11>
+    <ns1:e12><![CDATA[cdata-section1]]></ns1:e12>
+  </ns1:e1>
+  <ns1:e2>
+    <ns1:e11>text2</ns1:e11>
+    <ns1:e12><![CDATA[cdata-section2<&]]></ns1:e12>
+  </ns1:e2>
+</ns1:root>

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/be556897/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/models/xmlfragment.xml
----------------------------------------------------------------------
diff --git a/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/models/xmlfragment.xml b/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/models/xmlfragment.xml
new file mode 100644
index 0000000..b5578b6
--- /dev/null
+++ b/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/models/xmlfragment.xml
@@ -0,0 +1,19 @@
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+<root><a><b><c xmlns="http://x">C&lt;&gt;&amp;"']]&gt;</c></b></a></root>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/be556897/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/models/xmlns.xml
----------------------------------------------------------------------
diff --git a/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/models/xmlns.xml b/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/models/xmlns.xml
new file mode 100644
index 0000000..6f6453e
--- /dev/null
+++ b/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/models/xmlns.xml
@@ -0,0 +1,32 @@
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+<book xmlns="http://example.com/eBook">
+  <title>Test Book</title>
+  <chapter>
+    <title>Ch1</title>
+    <para>p1.1</para>
+    <para>p1.2</para>
+    <para>p1.3</para>
+  </chapter>
+  <chapter>
+    <title>Ch2</title>
+    <para>p2.1</para>
+    <para>p2.2</para>
+  </chapter>
+</book>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/be556897/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/models/xmlns2.xml
----------------------------------------------------------------------
diff --git a/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/models/xmlns2.xml b/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/models/xmlns2.xml
new file mode 100644
index 0000000..c8bfc9f
--- /dev/null
+++ b/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/models/xmlns2.xml
@@ -0,0 +1,32 @@
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+<eb:book xmlns:eb="http://example.com/eBook">
+  <eb:title>Test Book</eb:title>
+  <eb:chapter>
+    <eb:title>Ch1</eb:title>
+    <eb:para>p1.1</eb:para>
+    <eb:para>p1.2</eb:para>
+    <eb:para>p1.3</eb:para>
+  </eb:chapter>
+  <eb:chapter>
+    <eb:title>Ch2</eb:title>
+    <eb:para>p2.1</eb:para>
+    <eb:para>p2.2</eb:para>
+  </eb:chapter>
+</eb:book>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/be556897/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/models/xmlns3.xml
----------------------------------------------------------------------
diff --git a/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/models/xmlns3.xml b/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/models/xmlns3.xml
new file mode 100644
index 0000000..8502ead
--- /dev/null
+++ b/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/models/xmlns3.xml
@@ -0,0 +1,32 @@
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+<book xmlns:x="http://x" xmlns:y="http://y">
+  <x:title>Test Book</x:title>
+  <chapter>
+    <y:title>Ch1</y:title>
+    <para>p1.1</para>
+    <para>p1.2</para>
+    <para>p1.3</para>
+  </chapter>
+  <x:chapter>
+    <y:title>Ch2</y:title>
+    <x:para>p2.1</x:para>
+    <y:para>p2.2</y:para>
+  </x:chapter>
+</book>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/be556897/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/templates/default-xmlns.ftl
----------------------------------------------------------------------
diff --git a/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/templates/default-xmlns.ftl b/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/templates/default-xmlns.ftl
new file mode 100644
index 0000000..4f01835
--- /dev/null
+++ b/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/templates/default-xmlns.ftl
@@ -0,0 +1,28 @@
+<#ftl ns_prefixes={"D" : "http://x.com", "y" : "http://y.com"}>
+<#--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+<#assign r = doc.*[0]>
+${r["N:t1"]?default('-')} = No NS
+${r["t2"]?default('-')} = x NS
+${r["y:t3"]?default('-')} = y NS
+${r["./D:t4"]?default('-')} = x NS
+
+<#assign bool = doc["true()"]>
+${bool?string}
+

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/be556897/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/templates/xml-fragment.ftl
----------------------------------------------------------------------
diff --git a/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/templates/xml-fragment.ftl b/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/templates/xml-fragment.ftl
new file mode 100644
index 0000000..226215b
--- /dev/null
+++ b/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/templates/xml-fragment.ftl
@@ -0,0 +1,26 @@
+<#ftl ns_prefixes = {"n" : "http://x"}>
+<#--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+${node?node_name} = b
+${node?root?node_name} = @document
+${node['/']?node_name} = @document
+
+${node['n:c']} = C<>&"']]>
+
+${node?root.@@markup}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/be556897/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/templates/xml-ns_prefix-scope-lib.ftl
----------------------------------------------------------------------
diff --git a/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/templates/xml-ns_prefix-scope-lib.ftl b/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/templates/xml-ns_prefix-scope-lib.ftl
new file mode 100644
index 0000000..0f0bde2
--- /dev/null
+++ b/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/templates/xml-ns_prefix-scope-lib.ftl
@@ -0,0 +1,23 @@
+<#ftl ns_prefixes={ "n": "http://freemarker.org/test/bar", "D": "http://freemarker.org/test/namespace-test" }>
+<#--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+<#global libResult>//n:e: ${doc['//n:e']}, ${doc.root['n:e']}</#global>
+<#macro m>
+//n:e: ${doc['//n:e']}, ${doc.root['n:e']}
+</#macro>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/be556897/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/templates/xml-ns_prefix-scope-main.ftl
----------------------------------------------------------------------
diff --git a/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/templates/xml-ns_prefix-scope-main.ftl b/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/templates/xml-ns_prefix-scope-main.ftl
new file mode 100644
index 0000000..5b7ce24
--- /dev/null
+++ b/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/templates/xml-ns_prefix-scope-main.ftl
@@ -0,0 +1,36 @@
+<#ftl ns_prefixes={
+    "D": "http://freemarker.org/test/namespace-test",
+    "n": "http://freemarker.org/test/foo",
+    "bar": "http://freemarker.org/test/bar"
+}>
+<#--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+//e: ${doc['//D:e']}, ${doc.root.e}
+//n:e: ${doc['//n:e']}, ${doc.root['n:e']}
+//bar:e: ${doc['//bar:e']}, ${doc.root['bar:e']}
+
+Included:
+<#include "xml-ns_prefix-scope-lib.ftl">
+${libResult}
+<@m />
+
+Imported:
+<#import "xml-ns_prefix-scope-lib.ftl" as lib>
+${libResult}
+<@lib.m />

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/be556897/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/templates/xml.ftl
----------------------------------------------------------------------
diff --git a/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/templates/xml.ftl b/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/templates/xml.ftl
new file mode 100644
index 0000000..b85fc03
--- /dev/null
+++ b/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/templates/xml.ftl
@@ -0,0 +1,47 @@
+<#--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+<#-- test processing instructions -->
+<#global PIs = doc._content._ftype("p")>
+<#list PIs as pi>
+  ${pi}
+  ${pi["@target"]._text}
+  ${pi["@data"]._text}
+</#list>
+${PIs?size}
+<#global firstPi = PIs[0]>
+${firstPi._type}
+${firstPi["@customKey"]}
+${doc._registerNamespace("ns", "http://www.foo.com/ns1/")}
+${doc._descendant["ns:e11"]}
+${doc._descendant["ns:e12"]}
+<#global docRoot = doc["ns:root"]>
+${docRoot["ns:e1"]}
+${doc("//ns:e11")}
+${docRoot["ns:e1"]["@a1"]._name}
+${docRoot["ns:e1"]["@a2"]._text}
+${docRoot._children._parent._name}
+${docRoot._children._parent._unique._name}
+<#list doc._descendant as d>
+  ${d._name}
+</#list>
+<#list doc._descendant._ancestorOrSelf as d>
+  ${d._name}
+</#list>
+${docRoot["ns:e2"]["ns:e12"]._text}
+${docRoot["ns:e2"]["ns:e12"]._plaintext}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/be556897/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/templates/xmlns1.ftl
----------------------------------------------------------------------
diff --git a/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/templates/xmlns1.ftl b/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/templates/xmlns1.ftl
new file mode 100644
index 0000000..8aa893e
--- /dev/null
+++ b/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/templates/xmlns1.ftl
@@ -0,0 +1,53 @@
+<#ftl ns_prefixes = {"D" : "http://example.com/eBook"}>
+<#--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+
+${doc.@@markup}
+
+<#recurse doc >
+
+<#macro book>
+  <html>
+    <head>
+      <title><#recurse .node.title></title>
+    </head>
+    <body>
+      <h1><#recurse .node.title></h1>
+      <#recurse>
+    </body>
+  </html>
+</#macro>
+
+<#macro chapter>
+  <h2><#recurse .node.title></h2>
+  <#recurse>
+</#macro>
+
+<#macro para>
+  <p><#recurse>
+</#macro>
+
+<#macro title>
+  <#--
+    We have handled this element imperatively,
+    so we do nothing here.
+  -->
+</#macro>
+
+<#macro @text>${.node?html}</#macro>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/be556897/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/templates/xmlns3.ftl
----------------------------------------------------------------------
diff --git a/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/templates/xmlns3.ftl b/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/templates/xmlns3.ftl
new file mode 100644
index 0000000..c84ec69
--- /dev/null
+++ b/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/templates/xmlns3.ftl
@@ -0,0 +1,70 @@
+<#ftl ns_prefixes = {"x" : "http://x", "y" : "http://y"}>
+<#--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+<#recurse doc >
+
+<#macro book>
+  <html>
+    <head>
+      <title><#recurse .node["x:title"]></title>
+    </head>
+    <body>
+      <h1><#recurse .node["x:title"]></h1>
+      <#recurse>
+    </body>
+  </html>
+</#macro>
+
+<#macro chapter>
+  <h2><#recurse .node["y:title"]></h2>
+  <#recurse>
+</#macro>
+
+<#macro "x:chapter">
+  <h2><#recurse .node["y:title"]></h2>
+  <#recurse>
+</#macro>
+
+<#macro para>
+  <p><#recurse>
+</#macro>
+
+<#macro "x:para">
+  <p><#recurse>
+</#macro>
+
+<#macro "y:para">
+  <p><#recurse>
+</#macro>
+
+<#macro "x:title">
+  <#--
+    We have handled this element imperatively,
+    so we do nothing here.
+  -->
+</#macro>
+
+<#macro "y:title">
+  <#--
+    We have handled this element imperatively,
+    so we do nothing here.
+  -->
+</#macro>
+
+<#macro @text>${.node?html}</#macro>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/be556897/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/templates/xmlns4.ftl
----------------------------------------------------------------------
diff --git a/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/templates/xmlns4.ftl b/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/templates/xmlns4.ftl
new file mode 100644
index 0000000..e97bfc0
--- /dev/null
+++ b/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/templates/xmlns4.ftl
@@ -0,0 +1,70 @@
+<#ftl ns_prefixes = {"x" : "http://x", "y" : "http://y"}>
+<#--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+<#recurse doc >
+
+<#macro book>
+  <html>
+    <head>
+      <title><#recurse .node["x:title"]></title>
+    </head>
+    <body>
+      <h1><#recurse .node["x:title"]></h1>
+      <#recurse>
+    </body>
+  </html>
+</#macro>
+
+<#macro chapter>
+  <h2><#recurse .node["y:title"]></h2>
+  <#recurse>
+</#macro>
+
+<#macro 'x:chapter'>
+  <h2><#recurse .node["y:title"]></h2>
+  <#recurse>
+</#macro>
+
+<#macro para>
+  <p><#recurse>
+</#macro>
+
+<#macro 'x:para'>
+  <p><#recurse>
+</#macro>
+
+<#macro 'y:para'>
+  <p><#recurse>
+</#macro>
+
+<#macro "x:title">
+  <#--
+    We have handled this element imperatively,
+    so we do nothing here.
+  -->
+</#macro>
+
+<#macro "y:title">
+  <#--
+    We have handled this element imperatively,
+    so we do nothing here.
+  -->
+</#macro>
+
+<#macro @text>${.node?html}</#macro>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/be556897/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/templates/xmlns5.ftl
----------------------------------------------------------------------
diff --git a/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/templates/xmlns5.ftl b/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/templates/xmlns5.ftl
new file mode 100644
index 0000000..edc3b4a
--- /dev/null
+++ b/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/templates/xmlns5.ftl
@@ -0,0 +1,28 @@
+<#ftl ns_prefixes = {"D": "http://y.com", "xx" : "http://x.com"}>
+<#--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+<#assign r = doc["N:root"]>
+${r["N:t1"][0]?default('-')} = No NS
+${r["xx:t2"][0]?default('-')} = x NS
+${r["t3"][0]?default('-')} = y NS
+${r["xx:t4"][0]?default('-')} = x NS
+${r["//t1"][0]?default('-')} = No NS
+${r["//t2"][0]?default('-')} = -
+${r["//t3"][0]?default('-')} = -
+${r["//t4"][0]?default('-')} = -

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/be556897/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/testcases.xml
----------------------------------------------------------------------
diff --git a/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/testcases.xml b/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/testcases.xml
new file mode 100644
index 0000000..ffb42c3
--- /dev/null
+++ b/freemarker-dom/src/test/resources/org/apache/freemarker/dom/templatesuite/testcases.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" ?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+
+<!DOCTYPE testCases [
+  <!ELEMENT testCases (setting?, testCase*)>
+  <!ELEMENT testCase (setting?)>
+     <!ATTLIST testCase 
+               name CDATA #REQUIRED
+               template CDATA #IMPLIED
+               expected CDATA #IMPLIED
+               noOutput CDATA #IMPLIED
+     >
+     <!-- The default of `template` is "${name?keep_before('[#endTN]')}.ftl" -->
+     <!-- The default of `expected` is "${name}.txt" -->
+     <!-- The default of `noOutput` is false -->
+     
+ <!ELEMENT setting EMPTY>
+     <!ATTLIST setting 
+            auto_import CDATA #IMPLIED
+            source_encoding CDATA #IMPLIED
+            locale CDATA #IMPLIED
+            object_wrapper CDATA #IMPLIED
+            output_encoding CDATA #IMPLIED
+            output_dir CDATA #IMPLIED
+            new_builtin_class_resolver CDATA #IMPLIED
+            url_escaping_charset CDATA #IMPLIED
+            incompatible_improvements CDATA #IMPLIED
+            time_zone CDATA #IMPLIED
+            api_builtin_enabled CDATA #IMPLIED
+      >
+]>
+<!--
+Note that for the incompatible_improvements setting you can specify a list of versions, for example:
+<setting incompatible_improvements="min, 3.0.5, max" /> 
+-->
+
+<testCases>
+   <setting source_encoding="UTF-8" output_encoding="UTF-8" />
+
+   <testCase name="default-xmlns" />
+   <testCase name="xml-fragment" />
+   <testCase name="xmlns1" />
+   <testCase name="xmlns2" template="xmlns1.ftl"  expected="xmlns1.txt" />
+   <testCase name="xmlns3" />
+   <testCase name="xmlns4" />
+   <testCase name="xmlns5" />
+   <testCase name="xml-ns_prefix-scope" template="xml-ns_prefix-scope-main.ftl" />
+</testCases>

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/be556897/freemarker-servlet/build.gradle
----------------------------------------------------------------------
diff --git a/freemarker-servlet/build.gradle b/freemarker-servlet/build.gradle
index 41a8302..c0710b9 100644
--- a/freemarker-servlet/build.gradle
+++ b/freemarker-servlet/build.gradle
@@ -1,3 +1,22 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
 title = "Apache FreeMarker Servlet and JSP support"
 description = """\
 FreeMarker template engine, Servlet and JSP support. \