如何使用java smooks和freemarker获取具有命名空间的xml元素

时间:2015-07-07 10:14:34

标签: freemarker smooks

我是“smooks和freemarker”的新手。我想要访问xml文档中的元素。我在访问xml元素时遇到此异常。我正在发送我的代码。

Exception:-
------------

 For "${...}" content: Expected a string or something automatically convertible to string (number, date or boolean), but this evaluated to a sequence+hash (wrapper: f.e.dom.NodeListModel):
    ==> employee["first_name"]  [in template "free-marker-template" at line 1, column 84]

----
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: ${employee["first_name"]}  [in template "free-marker-template" at line 1, column 82]

----
Java stack trace (for programmers):
----
freemarker.core.NonStringException: [... Exception message was already printed; see it above ...]
    at freemarker.core.EvalUtil.coerceModelToString(EvalUtil.java:381)
    at freemarker.core.Expression.evalAndCoerceToString(Expression.java:82)
    at freemarker.core.DollarVariable.accept(DollarVariable.java:40)
    at freemarker.core.Environment.visit(Environment.java:312)

The following are versions
java version : "1.7.0_45"
freemarker   : 2.3.22
smooks       : 1.6


javacode:-
-----------
package test;

import java.io.BufferedInputStream;
import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.net.URI;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

import org.milyn.Smooks;
import org.milyn.SmooksException;
import org.milyn.container.ExecutionContext;
import org.milyn.event.report.HtmlReportGenerator;
import org.milyn.io.StreamUtils;
import org.milyn.payload.StringResult;
import org.xml.sax.SAXException;


public class SmooksExample {
    public SmooksExample() {
        // TODO Auto-generated constructor stub
    }
    protected static void runSmooksNew() throws IOException, SAXException, SmooksException {

        try {
            Long stTime = System.currentTimeMillis();
            System.out.println(stTime + "==" + new Date());
            Writer xmlResultWriter = new BufferedWriter(new FileWriter(new File("C:\\Files\\SmookExample\\output_sax.dat")));
            transCustomerCSV(new File("C:\\Files\\emp_namespace.xml"), xmlResultWriter);
            Long edTime = System.currentTimeMillis();
            System.out.println(edTime + "==" + (edTime-stTime) + "===="+ new Date());
            String times = String.format("%d min, %d sec", 
                    TimeUnit.MILLISECONDS.toMinutes(edTime-stTime),
                    TimeUnit.MILLISECONDS.toSeconds(edTime-stTime) - 
                    TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(edTime-stTime))
                );
            System.out.println(times);
        } finally {
            //smooks.close();
        }
    }
    public static void transCustomerCSV(File csvSourceReader, Writer xmlResultWriter) throws IOException, SAXException {
        File f = new File("C:/TEMPLATES/smooks-config.xml");
        URI u = f.toURI();
        Smooks smooks = new Smooks(u.getPath());
        ExecutionContext ec = smooks.createExecutionContext();
        smooks.filterSource(ec, new StreamSource(csvSourceReader), new StreamResult(xmlResultWriter));
    }
    /**
     * @param args
     */
    public static void main(String[] args) throws IOException, SAXException, SmooksException {
        System.out.println("\n\n");
        System.out.println("==============Message In==============");
        SmooksExample.runSmooksNew();
        System.out.println("======================================\n");
    }
}


Smooks-config.xml
--------------------
<smooks-resource-list xmlns:ftl="http://www.milyn.org/xsd/smooks/freemarker-1.1.xsd" xmlns:core="http://www.milyn.org/xsd/smooks/smooks-core-1.3.xsd" xmlns:jb="http://www.milyn.org/xsd/smooks/javabean-1.2.xsd" xmlns="http://www.milyn.org/xsd/smooks-1.1.xsd">
  <params>
    <param name="stream.filter.type">SAX</param>
    <param name="default.serialization.on">false</param>
  </params>
  <core:namespaces>
    <core:namespace prefix="empl" uri="http://www.example.com/employees"/>
  </core:namespaces>
  <resource-config selector="employee,first_name">
    <resource>org.milyn.delivery.DomModelCreator</resource>
  </resource-config>
  <ftl:freemarker applyOnElement="first_name">
    <ftl:template><!--<#ftl ns_prefixes={"empl":"http://www.example.com/employees"}>${employee["@id"]},${employee["first_name"]}-->
    </ftl:template>
  </ftl:freemarker>
</smooks-resource-list>

sample data xml file name:  emp_namespace.xml:-
--------------------------------------------------
<?xml version="1.0" encoding="UTF-8"?>
<empl:employees xmlns:empl="http://www.example.com/employees">
     <empl:employee id="1">
         <empl:first_name>Bill</empl:first_name>
         <empl:last_name>Adams</empl:last_name>
         <empl:age>25</empl:age>
         <empl:hire_date>12-06-1995</empl:hire_date>
         <empl:title>Java programmer</empl:title>
        <empl:DateCreated>
            <empl:Year>1980</empl:Year>
            <empl:Month>01</empl:Month>
            <empl:Day>01</empl:Day>
        </empl:DateCreated>
        <empl:DateCompleted>
            <empl:Year>1981</empl:Year>
            <empl:Month>02</empl:Month>
            <empl:Day>02</empl:Day>
        </empl:DateCompleted>
     </empl:employee>
     <empl:employee id="2">
         <empl:first_name>Mary</empl:first_name>
         <empl:last_name>Jones</empl:last_name>
         <empl:age>32</empl:age>
         <empl:hire_date>22-09-2001</empl:hire_date>
         <empl:title>Sales manager</empl:title>
         <empl:DateCreated>
            <empl:Year>1982</empl:Year>
            <empl:Month>03</empl:Month>
            <empl:Day>03</empl:Day>
        </empl:DateCreated>
        <empl:DateCompleted>
            <empl:Year>1983</empl:Year>
            <empl:Month>04</empl:Month>
            <empl:Day>04</empl:Day>
        </empl:DateCompleted>
     </empl:employee>
</empl:employees>

1 个答案:

答案 0 :(得分:0)

ns_prefixes中,您指定FTL中使用的名称空间前缀,该名称空间前缀与XML中使用的名称空间前缀无关。 FreeMarker并不关心XML中的实际前缀是什么,它只关心命名空间URL。因此,既然你已经声明了empl前缀,那么你也必须使用FTL(比如empl\:employee.empl\:first_name - 有点尴尬,因为:必须被转义)。但由于您主要访问该单个命名空间,因此我建议将该命名空间URL声明为默认值:

<#ftl ns_prefixes={"D": "http://www.example.com/employees"}>

然后您不必添加前缀:

${employee.first_name}

(注意,在这里我假设在Smooks中数据模型根是文档元素。我不知道这是否属实,但无论如何,就XML名称空间而言,这就是它的工作原理。此外,你在XML中有多个employee - s,因此上面的多个匹配不起作用,但这是另一个主题。)