You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@freemarker.apache.org by "Daniel Dekany (JIRA)" <ji...@apache.org> on 2016/12/09 00:32:59 UTC

[jira] [Comment Edited] (FREEMARKER-41) XPathSupport executeQuery doesn't handle text() in models that isn't normalized

    [ https://issues.apache.org/jira/browse/FREEMARKER-41?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15733835#comment-15733835 ] 

Daniel Dekany edited comment on FREEMARKER-41 at 12/9/16 12:32 AM:
-------------------------------------------------------------------

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".


was (Author: ddekany):
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)