Uploaded image for project: 'Apache Freemarker'
  1. Apache Freemarker
  2. FREEMARKER-41

XPathSupport executeQuery doesn't handle text() in models that isn't normalized

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Open
    • Major
    • Resolution: Unresolved
    • 2.3.25-incubating
    • None
    • engine
    • None

    Description

      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.

      ...XPathSupport.java
       
      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);
        ...
      

      Sample code to reproduce

      Reproduce.java
          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 
      

      Attachments

        Activity

          People

            Unassigned Unassigned
            pero Peter Rossbach
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

              Created:
              Updated: