Velocity模板:从Velocity上下文中转义XML

7

我有一个velocity模板,它代表一个XML文件。我正在使用传递给VelocityContext对象的数据填充标签之间的文本。然后可以在模板内访问这些数据。

下面是一个示例,我们称之为myTemplate.vm:

<text>$myDocument.text</text>

这是我如何将数据传递到Velocity文件中并构建为字符串输出的过程:

private String buildXml(Document pIncomingXml)
  {
    // setup environment
    Properties lProperties = new Properties();
    lProperties.put("file.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");

    VelocityContext lVelocityContext = new VelocityContext();
    lVelocityContext.put("myDocument" , pIncomingXml.getRootElement());

    StringWriter lOutput = new StringWriter();

    try
    {
      Velocity.init(lProperties);
      Velocity.mergeTemplate("myTemplate.vm", "ISO-8859-1", lVelocityContext, lOutput);
    }
    catch (Exception lEx)
    {
      throw new RuntimeException("Problems running velocity template, underlying error is " + lEx.getMessage(), lEx);
    }
    return lOutput.toString();
}

问题在于当我在模板文件中访问myDocument.text时,输出的文本没有为XML转义。我已找到一种解决方法,即添加VelocityContext来使用转义工具:

lVelocityContext.put("esc", new EscapeTool());

然后在模板中使用它来包装我的标签:

<text>$esc.xml($myDocument.text)</text>

事实上,我有一个非常庞大的模板,手动将每个元素包装在$esc.xml上下文中对我来说将是耗时的。是否有一种方法可以告诉Velocity在访问myDocument时自动进行XML转义而不需要编辑模板文件呢?


显然,你提了两个不同的问题(可能还混淆了关于它们的需求)。第一个问题是:“在访问myDocument时,是否有可能告诉XML要逃逸速度,而且完全不修改模板文件?”第二个问题没有直接提出,但你感觉到了一些麻烦。这个问题是:“EscapeTool.xml()对我来说速度太慢了。如何提高XML转义速度?”就第一个问题而言,我的猜测是“不行”。你可以尝试使用类似这样的东西:https://commons.apache.org/proper/commons-lang/javadocs/api-2.6/org/apache/commons/lang/StringEscapeUtils.html#escapeXml(java.lang.String)吗? - rsutormin
嗯,看起来这个StringEscapeUtils正是EscapeTool.xml()中使用的:http://grepcode.com/file/repository.springsource.com/org.apache.velocity/com.springsource.org.apache.velocity.tools.view/2.0.0/org/apache/velocity/tools/generic/EscapeTool.java#347。那么你唯一可以改进的就是检查一下你传入的Document的toString()方法中发生了什么。你能测量一下`pIncomingXml.toString()`所需的时间吗? - rsutormin
速度不是问题。只是手动逐个转义每个元素及其潜在错误的努力。 - Suipaste
1个回答

8

是的,这是可能的。

你需要做的是使用EscapeXMLReference,它实现了引用插入处理程序接口:

lProperties.put("eventhandler.referenceinsertion.class",
                 "org.apache.velocity.app.event.implement.EscapeXmlReference");

1
您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - Suipaste
这是解决我需要使用可能包含'&'的变量字符串填充XML属性值的方法。我只想补充一下,我需要包括'velocity-engine-core'依赖项而不是'velocity'。这样就避免了需要单独引入已停用的apached jakarta oro依赖项的问题。 - Spence7

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接