[
https://issues.apache.org/jira/browse/FREEMARKER-41?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15733835#comment-15733835
]
Daniel Dekany commented on FREEMARKER-41:
-----------------------------------------
I'm not sure how to solve this. The Xalan XPath query result set simply only
contains the first text node, instead of two nodes. I could work that around
when I convert a text node to text, as I could check if the {{nextSibling}} DOM
node is text too, and then append it to the result. But I'm not sure if I break
something with that. Like if {{text()\[1]}} returns "SA" and {{text()\[2]}}
returns "PLE" on some implementations (Xalan 2.7.0 returns empty set for the
last), even maybe on a future version of Xalan, then {{${text()\[1]}}} should
really only print "SA".
> XPathSupport executeQuery doesn't handle text() in models that isn't
> normalized
> -------------------------------------------------------------------------------
>
> Key: FREEMARKER-41
> URL: https://issues.apache.org/jira/browse/FREEMARKER-41
> Project: Apache Freemarker
> Issue Type: Bug
> Components: engine
> Affects Versions: 2.3.25-incubating
> Reporter: Per Olsson
>
> XPath expressions that contains text() doesn't evaluate to the correct value
> when the model isn't normalized and includes multiple text nodes. This will
> happen when the xml-parser creates multiple text nodes due to performance or
> memory reasons and is a fully normal behaviour.
> The solution in the function executeQuery with the NodeIterator (files:
> freemarker/ext/dom/SunInternalXalanXPathSupport.java and
> freemarker/ext/dom/XalanXPathSupport.java) doesn't handle adjacent(siblings)
> textnodes. The problem probably also exists for CDATA nodes. I don't know if
> the jaxen solution behaves in the same manner.
> {code:title=...XPathSupport.java|borderStyle=solid}
> synchronized public TemplateModel executeQuery(Object context, String
> xpathQuery) throws TemplateModelException {
> ...
> NodeIterator nodeIterator = xresult.nodeset();
> Node n;
> do {
> n = nodeIterator.nextNode();
> if (n != null) {
> result.add(n);
> }
> } while (n != null);
> ...
> {code}
> Sample code to reproduce
> {code:title=Reproduce.java|borderStyle=solid}
> Configuration cfg = new Configuration(Configuration.VERSION_2_3_25);
> cfg.setDefaultEncoding("UTF-8");
> ClassTemplateLoader ctl = new ClassTemplateLoader(App.class, "/");
> cfg.setTemplateLoader(ctl);
> // --- sample.ftl ---
> // <#ftl>
> // Text:${model["//root/text()"]}
> // Node:${model["//root"]}
> Template temp = cfg.getTemplate("sample.ftl");
> // --- Model ---
> // Element:root
> // |- TextNode:SA
> // |- TextNode:MPLE
> DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
> DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
> Document doc = docBuilder.newDocument();
> Element rootElement = doc.createElement("root");
> doc.appendChild(rootElement);
> Text text = doc.createTextNode("SA");
> rootElement.appendChild(text);
> text = doc.createTextNode("MPLE");
> rootElement.appendChild(text);
> Map<String, Object> model = new HashMap<String, Object>();
> model.put("model", doc);
> StringWriter sw = new StringWriter();
> temp.process(model, sw);
> System.out.println(sw.toString());
> // --- Actual output ---
> // Text:SA
> // Node:SAMPLE
> // --- Expected output ---
> // Text:SAMPLE
> // Node:SAMPLE
> {code}
--
This message was sent by Atlassian JIRA
(v6.3.4#6332)