将 Freemarker DocumentModel 与命名空间一起使用

Using Freemarker DocumentModel with namespaces

我收到了一份 XML 文档,其中包含我需要处理的命名空间信息。根据我在文档中阅读的所有内容,我应该能够将 XML 文档传递给模板并在模板中使用 XPath 来访问文档元素。

我能够在不包含名称空间的文档上成功执行此操作。但是,一旦我引入名称空间,我就会遇到异常。这是一些示例 XML:

<?xml version="1.0" encoding="UTF-8" ?>
<ns:a xmlns:ns="http://whosebug.com/">
  <ns:b>
    <ns:c>Element c</ns:c>
    <ns:d>
      <ns:e>Element e</ns:e>
    </ns:d>
  </ns:b>
</ns:a>

这是我的模板:

<#ftl ns_prefixes={
  "ns":"http://whosebug.com/"}
>

${doc.@@markup}
${doc["/ns:a/ns:b/ns:c"]}
${doc["/ns:a/ns:b/ns:d/ns:e"]}

当我将此模板应用于 XML 时,出现以下错误:

Nov 08, 2015 6:31:41 PM freemarker.log._JULLoggerFactory$JULLogger error
SEVERE: Error executing FreeMarker template
FreeMarker template error:
For "${...}" content: Expected a string or something automatically convertible to string (number, date or boolean), but this has evaluated to a sequence+hash (wrapper: f.e.dom.NodeListModel):
==> doc["/ns:a/ns:b/ns:c"]  [in template "freemarker.ftl" at line 6, column 3]

----
Tip: This XML query result can't be used as string because for that it had to contain exactly 1 XML node, but it contains 0 nodes. That is, the constructing XML query has found no matches.
----

----
FTL stack trace ("~" means nesting-related):
    - Failed at: ${doc["/ns:a/ns:b/ns:c"]}  [in template "freemarker.ftl" at line 6, column 1]
----

我最初没有考虑这个,但这是我应用模板的代码。

public static void main(String[] args) {
    try {
        File f = new File("c:/temp/freemarker.xml");
        Configuration c = new Configuration();
        c.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
        c.setDefaultEncoding("UTF-8");
        c.setDirectoryForTemplateLoading(new File("c:/temp"));

        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = factory.newDocumentBuilder();
        Document doc = builder.parse(f);
        Element note = doc.getDocumentElement();
        NodeModel.simplify(note);
        NodeModel.useJaxenXPathSupport();
        Map<String, Object> root = new HashMap<String, Object>();
        root.put("doc", note);
        Template template = c.getTemplate("freemarker.ftl");

        Writer out = new StringWriter();
        template.process(root, out);

        System.out.println(out);
    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

正如我所说,没有名称空间也能正常工作。不幸的是,我无法删除名称空间信息,因为可能会发生名称冲突,需要名称空间来确定引用的是哪个元素。

谁能告诉我我做错了什么?或者这可能是一个错误?

谢谢!

您的示例 XML 中缺少 xmlns:ns="http://whosebug.com/"。如果我添加它,那么它对我有用。