我找到了几个有类似问题和有价值答案的主题,但我仍然在努力解决这个问题:
我想用Jsoup解析一些html,所以我可以替换,例如
"changeme"
带
<changed>changeme</changed>
,但仅当它出现在html的文本部分时,否则,如果它是标记的一部分。所以,从这个html开始:
<body>
<p><a href="http://changeme.html">test changeme app</a></p>
</BODY>
</HTML>
我想谈谈这个问题:
<body>
<p><a href="http://changeme.html">test <changed>changeme</changed> app</a></p>
</BODY>
</HTML>
我尝试过几种方法,这种方法让我更接近理想的结果:
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);
但是通过这种方法,我发现了两个问题:
<body>
<p><a href="http://<changed>changeme</changed> .html">test
<changed>
changeme
</changed>
app</a></p>
</BODY>
</HTML>
在我介绍的新元素之前和之后插入换行符。这不是一个真正的问题,因为如果我使用#change#来进行替换并且在doc.toString()之后我将它们删除它们,我将它们再次替换为所需的值(使用&lt;&gt;)。
真正的问题:href中的网址已被修改,我不希望它发生。
想法? THX。
答案 0 :(得分:3)
我认为您的问题是您要更换元素html而不仅仅是文本,更改:
e.html(e.html().replaceAll("changeme","<changed>changeme</changed>"));
到
e.text(e.text().replaceAll("changeme","<changed>changeme</changed>"));
在执行doc.outputSettings().prettyPrint(false);
html = doc.toString();
来解决换行问题
答案 1 :(得分:1)
最后,我尝试了这个解决方案(在问题的最后),使用TextNodes:
How I can replace "text" in the each tag using Jsoup
这是结果代码:
Elements els = doc.body().getAllElements();
for (Element e : els) {
for (Node child : e.childNodes()){
if (child instanceof TextNode && !((TextNode) child).isBlank()) {
((TextNode)child).text(((TextNode)child).text().replaceAll("changeme","<changed>changeme</changed>"));
}
}
}
现在输出是预期的,甚至不会引入额外的断行。在这种情况下,prettyPrint必须设置为True。
唯一的问题是我并不真正理解使用TextNode
与Element.text()
的区别。如果有人想提供一些信息,将非常感激。
感谢。
答案 2 :(得分:1)
这是我的解决方案:
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);
TextNodes始终是叶节点,即它们不包含更多HTML元素。在您的原始方法中,使用替换为changme
字符串的新HTML替换元素的HTML。您只检查changeme是TextNodes内容的一部分,但是替换元素的HTML字符串中的每个匹配项,包括TextNodes之外的所有匹配项。
我的解决方案基本上与您的解决方案类似,但我使用JSoup方法textNodes()
。这样我就不需要进行类型转换。
P.S。
当然,我的解决方案和您的解决方案最终将包含<changed>changeme</changed>
而不是<changed>changeme</changed>
。这可能是也可能不是你想要的。如果您不想这样,那么您的结果就不再是有效的HTML,因为changed
不是有效的HTML标记。在这种情况下,Jsoup不会帮助你。但是,您当然可以再次在结果字符串中替换所有<changed>changeme</changed>
- 在JSoup之外。