【问题标题】:Replace template tags with velocity using regex in java在java中使用正则表达式用速度替换模板标签
【发布时间】:2016-08-17 11:33:46
【问题描述】:

我需要用 Velocity 代码替换 HTML 文档中的一些自定义模板标签,以便输出可以在另一个应用程序中使用。

我收到的代码如下所示:

<BG SWITCH>param
    <BG CASE>value1:
        text 1
    <BG /CASE>
    <BG CASE>value2:
        text 2
    <BG /CASE>
    <BG CASE>value3:
        text 3
    <BG /CASE>
    <BG CASE>value4:
        text 4
    <BG /CASE>
<BG /SWITCH>

结果应该是这样的:

#set ($param = $!user.data.param)
#if($!param == "value1")
    text 1
#end
#if($!param == "value2")
    text 2
#end
#if($!param == "value3")
    text 3
#end
#if($!param == "value4")
    text 4
#end

我到现在为止的Java代码是这样的:

Pattern pattern = Pattern.compile("<BG SWITCH>(.+?)<BG CASE>(.+?):(.+?)<BG /CASE>", Pattern.DOTALL);
Matcher matcher = pattern.matcher(newHtml);
newHtml = matcher.replaceAll("#set \\(\\$$1\\ = \\$!user.data.$1) #if(\\$$1 == \"$2\")$3 #end");

我得到的结果是这样的:

#set ($param = $!user.data.param)
    #if($param == "value1")
        text 1
    #end
    <BG CASE>value2:
        text 2
    <BG /CASE>
    <BG CASE>value3:
        text 3
    <BG /CASE>
    <BG CASE>value4:
        text 4
    <BG /CASE>
<BG /SWITCH>

所以“开关”和第一个“案例”被正确替换,但我不知道如何替换以下案例。

有什么想法吗?

在 svasa 回答后编辑:

建议的解决方案非常适合我提供的示例代码,但我应该提到这只是来自要处理的实际文件的一个 sn-p。实际文件可能包含多个这样的 switch-case 块。在这种情况下,建议的代码并没有完全涵盖它。

当“源”看起来像这样时:

<div>
    Some other content before
</div>

<div>
    <BG SWITCH>param1
        <BG CASE>value1:
            text 1
        <BG /CASE>
        <BG CASE>value2:
            text 2
        <BG /CASE>
        <BG CASE>value3:
            text 3
        <BG /CASE>
        <BG CASE>value4:
            text 4
        <BG /CASE>
    <BG /SWITCH>
</div>

<div>
    Some other content between
</div>

<div>
    <BG SWITCH>param2
        <BG CASE>value1:
            text 1
        <BG /CASE>
        <BG CASE>value2:
            text 2
        <BG /CASE>
        <BG CASE>value3:
            text 3
        <BG /CASE>
        <BG CASE>value4:
            text 4
        <BG /CASE>
    <BG /SWITCH>
</div>

<div>
    Some other content after
</div>

然后我得到以下结果:

#set ($param1 = $!user.data.param1)
#if($!param1== "value1")
    text 1
#end
#if($!param1== "value2")
    text 2
#end
#if($!param1== "value3")
    text 3
#end
#if($!param1== "value4")
    text 4
#end
#if($!param1== "value1")
    text 1
#end
#if($!param1== "value2")
    text 2
#end
#if($!param1== "value3")
    text 3
#end
#if($!param1== "value4")
    text 4
#end

因此,switch-case 块之前、之间和之后的任何其他内容都会丢失,第一个“param”用于第二个 switch-case 块。我将如何解决这个问题?

【问题讨论】:

    标签: regex templates tags velocity


    【解决方案1】:

    在继续研究我在下面写的解决方案之前 - 您的意见 字符串看起来更像是一个 xml 但它不是,因为字符串像 BG /SWITCH 不是有效的 xml。你知道这对你来说是正确的输入吗? 所有其他元素和字符串的结构看起来像 xml。 与来源确认它是否是 xml。如果是xml的话 使用 Java 的内置功能轻松提取您想要的任何内容 xpath.否则,使用正则表达式提取所需的字符串会非常痛苦,就像我在下面为您所做的那样。

    步骤:

    1. 首先使用正则表达式获取所需的&lt;div&gt;:

      (&lt;BG SWITCH&gt;(.*)\\n\\s*(\\s*&lt;BG CASE&gt;(.*):\\n\\s*(.*)\\n\\s*&lt;BG \\/CASE&gt;)+\\n\\s*&lt;BG \\/SWITCH&gt;)

    这个正则表达式的演示是here

    1. 将找到的字符串传递给我在之前的回答中使用的正则表达式:

    我会先获取第一行,即param,然后是剩余的字符串value1:、text 1等。

    对于param,正则表达式为:&lt;BG SWITCH&gt;(.*)

    对于value、text 字符串,您可以使用正则表达式:

    &lt;BG CASE&gt;(.*)\\n?(\\s+(.*))\\n?\\s+&lt;BG /CASE&gt; 这个正则表达式的演示是here

    代码如下所示:

    String mainRegex = "(<BG SWITCH>(.*)\\n\\s*(\\s*<BG CASE>(.*):\\n\\s*(.*)\\n\\s*<BG \\/CASE>)+\\n\\s*<BG \\/SWITCH>)";
    String result = "";
    Pattern p = Pattern.compile( mainRegex );
    Matcher m = p.matcher( sb.toString() );
    while ( m.find() )
    {
        String toSearch = m.group();
        result += updateResult( result, toSearch );
    }
    
    System.out.println(result);
    
    
    private static String updateResult( String replaced, String searchString )
    {
         Pattern firstPattern = Pattern.compile("<BG SWITCH>(.*)");
         Matcher matcher = firstPattern.matcher(searchString);
         if ( matcher.find() )
         {
             String paramtext = matcher.group(1);
    
              replaced = "#set ($" + paramtext + " = $!user.data." + paramtext + ")";
              replaced = replaced + "\n";
    
              Pattern pattern = Pattern.compile("<BG CASE>(.*):\\n?(\\s+(.*))\\n?\\s+<BG /CASE>");
              matcher = pattern.matcher(searchString);
              while ( matcher.find() )
              {
                 String valueString = matcher.group(1);
                 String textString = matcher.group(2);
                 replaced = replaced + "#if($!" + paramtext  + "== \"" + valueString + "\")" + "\n" + textString + "\n#end" + "\n";
              }
    
    
    
         }
    
         return replaced;
    }
    

    最后一个println 语句的输出:

        #set ($param1 = $!user.data.param1)
    #if($!param1== "value1")
                text 1
    #end
    #if($!param1== "value2")
                text 2
    #end
    #if($!param1== "value3")
                text 3
    #end
    #if($!param1== "value4")
                text 4
    #end
    #set ($param2 = $!user.data.param2)
    #if($!param2== "value1")
                text 1
    #end
    #if($!param2== "value2")
                text 2
    #end
    #if($!param2== "value3")
                text 3
    #end
    #if($!param2== "value4")
                text 4
    #end
    

    【讨论】:

    • 完美,就是这样,正是我想要的。非常感谢svasa!我自己不会得到那个解决方案。
    • 嗨@svasa,我编辑了我原来的问题。如果你能再看看它,那就太好了,因为事实证明我还没有到那里。
    • @David 你是在文件中还是在字符串中接收这个?
    • 嗨@svasa,将使用该应用程序的人将拥有一个 html 文件,现在他们只需在文本编辑器中打开它,将代码复制粘贴到表单中,然后我的JSP 应用程序将转换代码并返回它。一旦它工作,我会添加文件上传或其他东西,但现在我正在使用来自 HTML 文本区域的字符串。这会对如何使用正则表达式进行处理有影响吗?
    • @David 编辑了答案。看看
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-06
    • 2015-05-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多