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 2015/12/30 19:11:44 UTC
[24/35] incubator-freemarker git commit: Two freemarker.ext.dom xmlns
prefix outputting bugs fixed:
Two freemarker.ext.dom xmlns prefix outputting bugs fixed:
- Bug fixed: The @@qname of elements that belong to the XML namespace declared as the default via <#ftl ns_prefixes={'D':'...', ... }> no longer starts with D:, instead they just start with no name space prefix.
- Bug fixed: In the markup returned by the @@markup key, when there were multiple namespaces for which there was no prefix associated with via <#ftl ns_prefixes=...>, all those namespaces were assigned to the same auto-generated xmlns prefix (usually a). Now they will get a, b, c, etc. prefixes.
Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/02459623
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/02459623
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/02459623
Branch: refs/heads/2.3
Commit: 02459623e11efc5ddce66e6a8310c8f628272102
Parents: 33ba278
Author: ddekany <dd...@apache.org>
Authored: Mon Dec 28 22:35:43 2015 +0100
Committer: ddekany <dd...@apache.org>
Committed: Mon Dec 28 22:35:43 2015 +0100
----------------------------------------------------------------------
.../java/freemarker/ext/dom/ElementModel.java | 2 +-
.../java/freemarker/ext/dom/NodeOutputter.java | 39 +++---
src/manual/en_US/book.xml | 118 ++++++++++++++-----
src/test/java/freemarker/ext/dom/DOMTest.java | 31 +++++
src/test/java/freemarker/test/TemplateTest.java | 21 +++-
5 files changed, 153 insertions(+), 58 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/02459623/src/main/java/freemarker/ext/dom/ElementModel.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/ext/dom/ElementModel.java b/src/main/java/freemarker/ext/dom/ElementModel.java
index a0f13fa..fb6fccd 100644
--- a/src/main/java/freemarker/ext/dom/ElementModel.java
+++ b/src/main/java/freemarker/ext/dom/ElementModel.java
@@ -145,7 +145,7 @@ class ElementModel extends NodeModel implements TemplateScalarModel {
String defaultNS = env.getDefaultNS();
String prefix;
if (defaultNS != null && defaultNS.equals(nsURI)) {
- prefix = Template.DEFAULT_NAMESPACE_PREFIX;
+ prefix = "";
} else {
prefix = env.getPrefixForNamespace(nsURI);
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/02459623/src/main/java/freemarker/ext/dom/NodeOutputter.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/ext/dom/NodeOutputter.java b/src/main/java/freemarker/ext/dom/NodeOutputter.java
index cd59f2b..e4417a2 100644
--- a/src/main/java/freemarker/ext/dom/NodeOutputter.java
+++ b/src/main/java/freemarker/ext/dom/NodeOutputter.java
@@ -19,8 +19,8 @@
package freemarker.ext.dom;
-import java.util.HashMap;
import java.util.Iterator;
+import java.util.LinkedHashMap;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
@@ -30,6 +30,7 @@ import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
+import freemarker.core.BugException;
import freemarker.core.Environment;
import freemarker.template.Template;
import freemarker.template.utility.StringUtil;
@@ -41,8 +42,9 @@ class NodeOutputter {
private String defaultNS;
private boolean hasDefaultNS;
private boolean explicitDefaultNSPrefix;
- private HashMap namespacesToPrefixLookup = new HashMap();
+ private LinkedHashMap<String, String> namespacesToPrefixLookup = new LinkedHashMap<String, String>();
private String namespaceDecl;
+ int nextGeneratedPrefixNumber = 1;
NodeOutputter(Node node) {
if (node instanceof Element) {
@@ -72,6 +74,15 @@ class NodeOutputter {
String nsURI = n.getNamespaceURI();
if (nsURI != null && nsURI.length() > 0) {
String prefix = env.getPrefixForNamespace(nsURI);
+ if (prefix == null) {
+ prefix = namespacesToPrefixLookup.get(nsURI);
+ if (prefix == null) {
+ // Assign a generated prefix:
+ do {
+ prefix = StringUtil.toLowerABC(nextGeneratedPrefixNumber++);
+ } while (env.getNamespaceForPrefix(prefix) != null);
+ }
+ }
namespacesToPrefixLookup.put(nsURI, prefix);
} else if (hasDefaultNS && n.getNodeType() == Node.ELEMENT_NODE) {
namespacesToPrefixLookup.put(defaultNS, Template.DEFAULT_NAMESPACE_PREFIX);
@@ -93,28 +104,14 @@ class NodeOutputter {
buf.append(defaultNS);
buf.append("\"");
}
- for (Iterator it = namespacesToPrefixLookup.keySet().iterator(); it.hasNext(); ) {
- String nsURI = (String) it.next();
+ for (Iterator<String> it = namespacesToPrefixLookup.keySet().iterator(); it.hasNext(); ) {
+ String nsURI = it.next();
if (nsURI == null || nsURI.length() == 0) {
continue;
}
- String prefix = (String) namespacesToPrefixLookup.get(nsURI);
+ String prefix = namespacesToPrefixLookup.get(nsURI);
if (prefix == null) {
- // Okay, let's auto-assign a prefix.
- // Should we do this??? (REVISIT)
- for (int i = 0; i < 26; i++) {
- char[] cc = new char[1];
- cc[0] = (char) ('a' + i);
- prefix = new String(cc);
- if (env.getNamespaceForPrefix(prefix) == null) {
- break;
- }
- prefix = null;
- }
- if (prefix == null) {
- throw new RuntimeException("This will almost never happen!");
- }
- namespacesToPrefixLookup.put(nsURI, prefix);
+ throw new BugException("No xmlns prefix was associated to URI: " + nsURI);
}
buf.append(" xmlns");
if (prefix.length() > 0) {
@@ -133,7 +130,7 @@ class NodeOutputter {
if (nsURI == null || nsURI.length() == 0) {
buf.append(n.getNodeName());
} else {
- String prefix = (String) namespacesToPrefixLookup.get(nsURI);
+ String prefix = namespacesToPrefixLookup.get(nsURI);
if (prefix == null) {
//REVISIT!
buf.append(n.getNodeName());
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/02459623/src/manual/en_US/book.xml
----------------------------------------------------------------------
diff --git a/src/manual/en_US/book.xml b/src/manual/en_US/book.xml
index ba8c1b1..6318f75 100644
--- a/src/manual/en_US/book.xml
+++ b/src/manual/en_US/book.xml
@@ -26928,22 +26928,49 @@ TemplateModel x = env.getVariable("x"); // get variable x</programlisting>
</listitem>
<listitem>
- <para>Bug fixed: XPath queries that has only contained
- characters that are valid in XML element names and has also
- contained <literal>::</literal> (which is valid in names in
- namespace-unware documents), like
- <literal>e['following-sibling::foo']</literal>, were interpreted
- as literal element names (giving 0 hits) rather than as XPath
- expressions. Note that there were no such problem with
- <literal>e['following-sibling::*']</literal> for example, as
- it's not a valid XML element name according the XML
- specification. This fix can actually break applications that has
- processed namespace unaware XML that use <literal>::</literal>
- as part of element or attribute names, but such an application
- is highly unlikely, unlike running into the fixed problem.
- (Unfortunately, using
- <literal>incompatible_improvements</literal> wasn't technically
- possible here.)</para>
+ <para>Fixes in the XML processing feature
+ (<literal>freemarker.ext.dom</literal>):</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>Bug fixed: XPath queries that has only contained
+ characters that are valid in XML element names and has also
+ contained <literal>::</literal> (which is valid in names in
+ namespace-unware documents), like
+ <literal>e['following-sibling::foo']</literal>, were
+ interpreted as literal element names (giving 0 hits) rather
+ than as XPath expressions. Note that there were no such
+ problem with <literal>e['following-sibling::*']</literal>
+ for example, as it's not a valid XML element name according
+ the XML specification. This fix can actually break
+ applications that has processed namespace unaware XML that
+ use <literal>::</literal> as part of element or attribute
+ names, but such an application is highly unlikely, unlike
+ running into the fixed problem. (Unfortunately, using
+ <literal>incompatible_improvements</literal> wasn't
+ technically possible here.)</para>
+ </listitem>
+
+ <listitem>
+ <para>Bug fixed: The <literal>@@qname</literal> of elements
+ that belong to the XML namespace declared as the default via
+ <literal><#ftl ns_prefixes={'D':'...', ...
+ }></literal> no longer starts with <literal>D:</literal>,
+ instead they just start with no name space prefix.</para>
+ </listitem>
+
+ <listitem>
+ <para>Bug fixed: In the markup returned by the
+ <literal>@@markup</literal> key, when there were multiple
+ namespaces for which there was no prefix associated with via
+ <literal><#ftl
+ ns_prefixes=<replaceable>...</replaceable>></literal>,
+ all those namespaces were assigned to the same
+ auto-generated <literal>xmlns</literal> prefix (usually
+ <quote>a</quote>). Now they will get <quote>a</quote>,
+ <quote>b</quote>, <quote>c</quote>, etc. prefixes.</para>
+ </listitem>
+ </itemizedlist>
</listitem>
<listitem>
@@ -27285,22 +27312,49 @@ TemplateModel x = env.getVariable("x"); // get variable x</programlisting>
</listitem>
<listitem>
- <para>Bug fixed: XPath queries that has only contained
- characters that are valid in XML element names and has also
- contained <literal>::</literal> (which is valid in names in
- namespace-unware documents), like
- <literal>e['following-sibling::foo']</literal>, were interpreted
- as literal element names (giving 0 hits) rather than as XPath
- expressions. Note that there were no such problem with
- <literal>e['following-sibling::*']</literal> for example, as
- it's not a valid XML element name according the XML
- specification. This fix can actually break applications that has
- processed namespace unaware XML that use <literal>::</literal>
- as part of element or attribute names, but such an application
- is highly unlikely, unlike running into the fixed problem.
- (Unfortunately, using
- <literal>incompatible_improvements</literal> wasn't technically
- possible here.)</para>
+ <para>Fixes in the XML processing feature
+ (<literal>freemarker.ext.dom</literal>):</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>Bug fixed: XPath queries that has only contained
+ characters that are valid in XML element names and has also
+ contained <literal>::</literal> (which is valid in names in
+ namespace-unware documents), like
+ <literal>e['following-sibling::foo']</literal>, were
+ interpreted as literal element names (giving 0 hits) rather
+ than as XPath expressions. Note that there were no such
+ problem with <literal>e['following-sibling::*']</literal>
+ for example, as it's not a valid XML element name according
+ the XML specification. This fix can actually break
+ applications that has processed namespace unaware XML that
+ use <literal>::</literal> as part of element or attribute
+ names, but such an application is highly unlikely, unlike
+ running into the fixed problem. (Unfortunately, using
+ <literal>incompatible_improvements</literal> wasn't
+ technically possible here.)</para>
+ </listitem>
+
+ <listitem>
+ <para>Bug fixed: The <literal>@@qname</literal> of elements
+ that belong to the XML namespace declared as the default via
+ <literal><#ftl ns_prefixes={'D':'...', ...
+ }></literal> no longer starts with <literal>D:</literal>,
+ instead they just start with no name space prefix.</para>
+ </listitem>
+
+ <listitem>
+ <para>Bug fixed: In the markup returned by the
+ <literal>@@markup</literal> key, when there were multiple
+ namespaces for which there was no prefix associated with via
+ <literal><#ftl
+ ns_prefixes=<replaceable>...</replaceable>></literal>,
+ all those namespaces were assigned to the same
+ auto-generated <literal>xmlns</literal> prefix (usually
+ <quote>a</quote>). Now they will get <quote>a</quote>,
+ <quote>b</quote>, <quote>c</quote>, etc. prefixes.</para>
+ </listitem>
+ </itemizedlist>
</listitem>
</itemizedlist>
</section>
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/02459623/src/test/java/freemarker/ext/dom/DOMTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/ext/dom/DOMTest.java b/src/test/java/freemarker/ext/dom/DOMTest.java
index 182ac31..59f1392 100644
--- a/src/test/java/freemarker/ext/dom/DOMTest.java
+++ b/src/test/java/freemarker/ext/dom/DOMTest.java
@@ -28,6 +28,37 @@ public class DOMTest extends TemplateTest {
}
@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>");
+
+ //
+ assertOutput("${doc?children[0].@@qname!'null'}", "null");
+ assertOutput("${doc?children[0]?children[1].@@qname!'null'}", "null");
+ assertOutput(ftlHeader + "${doc?children[0].@@qname}", "root");
+ assertOutput(ftlHeader + "${doc?children[0]?children[1].@@qname}", "n2:b");
+ // 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");
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/02459623/src/test/java/freemarker/test/TemplateTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/test/TemplateTest.java b/src/test/java/freemarker/test/TemplateTest.java
index 6047e2e..719ca7c 100644
--- a/src/test/java/freemarker/test/TemplateTest.java
+++ b/src/test/java/freemarker/test/TemplateTest.java
@@ -69,8 +69,12 @@ public abstract class TemplateTest {
}
protected void assertOutput(String ftl, String expectedOut) throws IOException, TemplateException {
+ assertOutput(createTemplate(ftl), expectedOut, false);
+ }
+
+ private Template createTemplate(String ftl) throws IOException {
Template t = new Template(null, ftl, getConfiguration());
- assertOutput(t, expectedOut, false);
+ return t;
}
protected void assertOutputForNamed(String name, String expectedOut) throws IOException, TemplateException {
@@ -101,9 +105,7 @@ public abstract class TemplateTest {
protected void assertOutput(Template t, String expectedOut, boolean normalizeNewlines)
throws TemplateException, IOException {
- StringWriter out = new StringWriter();
- t.process(getDataModel(), out);
- String actualOut = out.toString();
+ String actualOut = getOutput(t);
if (normalizeNewlines) {
expectedOut = normalizeNewLines(expectedOut);
@@ -111,6 +113,17 @@ public abstract class TemplateTest {
}
assertEquals(expectedOut, actualOut);
}
+
+ protected String getOutput(String ftl) throws IOException, TemplateException {
+ return getOutput(createTemplate(ftl));
+ }
+
+ protected String getOutput(Template t) throws TemplateException, IOException {
+ StringWriter out = new StringWriter();
+ t.process(getDataModel(), out);
+ String actualOut = out.toString();
+ return actualOut;
+ }
protected Configuration createConfiguration() throws Exception {
return new Configuration(Configuration.VERSION_2_3_0);