Вопрос

I've got a strange problem using the Castle NVelocity...

If the template string ends with a $ character, it throws the following and exception:

Lexical error: NVelocity.Runtime.Parser.TokenMgrError: Lexical error at line 1, column 94. Encountered: after : ""

If i add a space, or any other character, to the end of the string it works as expected.

Does anybody have a workaround for this?

Here's some sample code that reproduces the problem:

class Program
{
    static void Main(string[] args)
    {
        var result = Merge("The quick brown ${Animal} jumps over the lazy dog$", new List<KeyValuePair<string, string>>() { new KeyValuePair<string, string>("Animal", "fox") });

        Console.WriteLine("Success: {0}", result.Key);
        Console.WriteLine("Message: {0}", result.Value);
        Console.Read();
    }

    public static KeyValuePair<bool, string> Merge(string template, IList<KeyValuePair<string, string>> data)
    {
        var ret = new KeyValuePair<bool, string>(false, null);
        try
        {
            if (data != null)
            {
                var engine = new VelocityEngine();
                engine.Init();

                var context = new VelocityContext();
                foreach (var tokenData in data)
                {
                    context.Put(tokenData.Key, tokenData.Value);
                }

                var templateContent = template;

                var sb = new StringBuilder();
                var textWriter = new StringWriter(sb);

                engine.Evaluate(context, textWriter, String.Empty, templateContent);

                ret = new KeyValuePair<bool, string>(true, sb.ToString());
            }
        }
        catch (Exception ex)
        {
            ret = new KeyValuePair<bool, string>(false, ex.Message);
        }
        return ret;
    }
}
Это было полезно?

Решение

You have a couple of options:

If you have no influence over the input string to be merged, make sure that they don't have a trailing dollar character, at least not for the merge process:

Example:

bool dollarAtEnd = false;

if (input.EndsWith('$'))
{
   input += " "; 
   dollarAtEnd = true;
}

var result = Merge(input, ...);

if (dollarAtEnd)
{
   result = result.Substring(1, result.Length - 1);
}

If you can control the input string, but only have the requirement that some of them should end with a dollar character, you can do as follows:

Example:

"#set($dollar='$')The quick brown ${Animal} jumps over the lazy dog$dollar"

Or pass "dollar" as variable to the VelocityContext, rather than specifying it inline.

Другие советы

$ denotes the start of a variable name, if you want to use a $ literal, you need to escape it to \$.

http://velocity.apache.org/engine/devel/user-guide.html#Getting_literal

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top