0

我有一个包含一些值的字符串,如下所示。我想 用一些新文本替换包含特定 customerId 的 html img 标签。我尝试了没有给我预期输出的小型 java 程序。这是程序信息

我的输入字符串是

 String inputText = "Starting here.. <img src=\"getCustomers.do?custCode=2&customerId=3334&param1=123/></p>"
    + "<p>someText</p><img src=\"getCustomers.do?custCode=2&customerId=3340&param2=456/> ..Ending here";

正则表达式是

  String regex = "(?s)\\<img.*?customerId=3340.*?>";

我想放在输入字符串中的新文本

编辑开始:

String newText = "<img src=\"getCustomerNew.do\">";

编辑结束:

现在我在做

  String outputText = inputText.replaceAll(regex, newText);

输出是

 Starting here.. Replacing Text ..Ending here

但我的预期输出是

 Starting here.. <img src=\"getCustomers.do?custCode=2&customerId=3334&param1=123/></p><p>someText</p>Replacing Text ..Ending here

请注意,在我的预期输出中,只有包含 customerId=3340 的 img 标签被替换为替换文本。我不明白为什么在输出中我得到两个 img 标签都被替换了?

4

3 回答 3

4

你有“通配符”/“任何”模式(.*),这会将匹配扩展到可能的最长匹配字符串,并且模式中的最后一个固定文本是一个>字符,因此匹配>输入文本中的最后一个字符,即最后一个!

您应该能够通过将.*部分更改为类似的东西来解决这个问题,[^>]+这样匹配就不会超过第一个>字符。

用正则表达式解析 HTML 势必会带来痛苦。

于 2012-12-13T18:18:15.417 回答
1

正如其他人在评论中告诉你的那样,HTML 不是一种常规语言,因此使用正则表达式来操作它通常很痛苦。您最好的选择是使用 HTML 解析器。我以前没有使用过 Jsoup,但是用谷歌搜索一下似乎你需要类似的东西:

import org.jsoup.*;
import org.jsoup.nodes.*;
import org.jsoup.select.*;

public class MyJsoupExample {
    public static void main(String args[]) {
        String inputText = "<html><head></head><body><p><img src=\"getCustomers.do?custCode=2&customerId=3334&param1=123\"/></p>"
            + "<p>someText <img src=\"getCustomers.do?custCode=2&customerId=3340&param2=456\"/></p></body></html>";
        Document doc = Jsoup.parse(inputText);
        Elements myImgs = doc.select("img[src*=customerId=3340");
        for (Element element : myImgs) {
            element.replaceWith(new TextNode("my replaced text", ""));
        }
        System.out.println(doc.toString());
    }
}

基本上,代码获取具有包含给定字符串img的属性的节点列表src

Elements myImgs = doc.select("img[src*=customerId=3340");

然后遍历列表并用一些文本替换这些节点。

更新

如果您不想img用文本替换整个节点,而是需要为其src属性指定一个新值,那么您可以将for循环块替换为:

element.attr("src", "my new value"));

或者,如果您只想更改部分src值,则可以执行以下操作:

String srcValue = element.attr("src");
element.attr("src", srcValue.replace("getCustomers.do", "getCustonerNew.do"));

这与我在此线程中发布的内容非常相似。

于 2012-12-13T19:52:33.283 回答
0

发生的情况是,您的正则表达式开始匹配第一个img标签,然后消耗所有内容(无论是否贪婪),直到找到customerId=3340,然后继续消耗所有内容,直到找到>

如果您希望它仅使用customerId=3340的img ,请考虑是什么使该标签与它可能匹配的其他标签不同。

在这种特殊情况下,一种可能的解决方案是使用后视运算符(不消耗匹配项)查看该img标记背后的内容。此正则表达式将起作用:

String regex = "(?<=</p>)<img src=\".*?customerId=3340.*?>";
于 2012-12-15T15:47:35.660 回答