仅在文本部分用jsoup替换字符串

Mar*_*dez 13 java jsoup

我发现了几个有类似问题和有价值答案的主题,但我仍然在努力解决这个问题:

我想用Jsoup解析一些html,所以我可以替换,例如,

"changeme"
Run Code Online (Sandbox Code Playgroud)

<changed>changeme</changed>
Run Code Online (Sandbox Code Playgroud)

,但只有当它出现在html的文本部分时,否则,如果它是标记的一部分.所以,从这个html开始:

<body>
<p><a href="http://changeme.html">test changeme app</a></p>
</BODY>
</HTML>
Run Code Online (Sandbox Code Playgroud)

我想谈谈这个:

<body>
<p><a href="http://changeme.html">test <changed>changeme</changed> app</a></p>
</BODY>
</HTML>
Run Code Online (Sandbox Code Playgroud)

我尝试了几种方法,这一方法让我更接近预期的结果:

Document doc = null;
try {
    doc = Jsoup.parse(new File("tmp1450348256397.txt"), "UTF-8");
} catch (Exception ex) {
}

Elements els = doc.body().getAllElements();
for (Element e : els) {
    if (e.text().contains("changeme")) {
        e.html(e.html().replaceAll("changeme","<changed>changeme</changed>"));
    }
}
html = doc.toString();
System.out.println(html);
Run Code Online (Sandbox Code Playgroud)

但是通过这种方法,我发现了两个问题:

<body>
<p><a href="http://<changed>changeme</changed> .html">test
    <changed>
        changeme
    </changed> 
app</a></p>
</BODY>
</HTML>
Run Code Online (Sandbox Code Playgroud)
  1. 在我引入的新元素之前和之后插入换行符.这不是一个真正的问题,因为如果我使用#change#来进行替换并且在doc.toString()之后我将它们删除它们,我将它们再次替换为所需的值(使用<>).

  2. 真正的问题:href中的URL已被修改,我不希望它发生.

想法?谢谢.

luk*_*sch 7

这是我的解决方案:

String html=""
    +"<p><a href=\"http://changeme.html\">"
    +   "test changeme "
    +   "<div class=\"changeme\">"
    +     "inner text changeme"
    +   "</div>"
    +   " app</a>"
    +"</p>";
Document doc = Jsoup.parse(html);
Elements els = doc.body().getAllElements();
for (Element e : els) {
    List<TextNode> tnList = e.textNodes();
    for (TextNode tn : tnList){
        String orig = tn.text();
        tn.text(orig.replaceAll("changeme","<changed>changeme</changed>")); 
    }
}

html = doc.toString();
System.out.println(html);
Run Code Online (Sandbox Code Playgroud)

TextNode 始终是叶节点,即它们不包含更多 HTML 元素。在原来的方法中,您将元素的 HTML 替换为带有替换changme字符串的新 HTML。您仅检查 Changeme 是否属于 TextNodes 内容的一部分,但替换该元素的 HTML 字符串中的每个匹配项,包括 TextNodes 之外的所有匹配项。

我的解决方案基本上和你的一样,但我使用 JSoup 方法textNodes()。这样我就不需要打字了。

PS 当然,我的解决方案和你的解决方案 最终都会包含&lt;changed&gt;changeme&lt;/changed&gt;而不是。<changed>changeme</changed>这可能是也可能不是您想要的。如果您不希望这样,那么您的结果将不再是有效的 HTML,因为changed没有有效的 HTML 标记。在这种情况下,Jsoup 不会帮助你。但是,您当然可以在结果字符串中&lt;changed&gt;changeme&lt;/changed&gt;再次替换 - 在 JSoup 之外。


jon*_*onk 5

我认为你的问题是你要替换元素 html 而不仅仅是它的文本,更改:

e.html(e.html().replaceAll("changeme","<changed>changeme</changed>"));
Run Code Online (Sandbox Code Playgroud)

e.text(e.text().replaceAll("changeme","<changed>changeme</changed>"));
Run Code Online (Sandbox Code Playgroud)

换行问题可能可以通过doc.outputSettings().prettyPrint(false);在做之前做来解决html = doc.toString();