在未包含在标签中的多行文本节点中用 <br> 标签替换换行符
Replacing line breaks with <br> tags in multi-line text nodes not enclosed in tags
我正在寻找 Java 解决方案,以在给定 HTML 字符串的所有多行文本字段中用 <br/>
标记替换换行符,即 不包含在任何标签中(虚根的子代)。
源数据是通过前端 HTML 编辑器(如 TinyMCE)创建的 HTML 格式的文本。所以它是一个任意的 HTML 片段 - 不存在的 <body>
.
的一部分
以下:
text11
text 21<p>tagged text1
tagged text2</p>
text 2
应该变成:
text11<br/>text 21<p>tagged text1
tagged text2</p></br>text 2
但是,以下内容完全不会受到影响:
<div>text11
text 21<p>tagged text1
tagged text2</p>
text 2</div>
我在想这样的事情(不工作):
private static String ReplaceLfWithBr(String source) {
// text - combination of words and line breaks
// should not be preceded by <tag> or followed by <\tag>
final String regex = "((?!<.+>)[\w(\r?\n)]+(?!<\s*/.+>))";
Pattern patern = Pattern.compile(regex, Pattern.MULTILINE);
Matcher matcher = patern.matcher(source);
StringBuffer sb = new StringBuffer(source.length());
while(matcher.find()){
matcher.appendReplacement(sb, "<br/>");
}
matcher.appendTail(sb);
return sb.toString();
}
所以它比我在评论中所说的要复杂一些,但我认为这样的事情可能会奏效:
public static void main (String[] args)
{
String text = "text11\n"
+ "text 21<p>tagged text1\n"
+ "tagged text2</p>\n"
+ "text 2";
StringBuilder sb = new StringBuilder("<body>");
sb.append(text);
sb.append("</body>");
Document doc = Jsoup.parseBodyFragment(sb.toString());
Element body = doc.select("body");
List<Node> children = body.childNodes();
StringBuilder sb2 = new StringBuilder();
for(Node n : children) {
if(n instanceof TextNode) {
n.text(n.getWholeText().replace("\n", "<br/>"));
}
sb2.append(n.toString());
}
System.out.println(sb2.toString());
}
基本上获取所有 Nodes
,对 TextNodes
进行替换,然后将它们放回原处。我不是 100% 确定这会按原样工作,因为我目前无法对其进行测试。但希望它能传达这个想法。
我在评论中所说的不起作用,因为您必须能够将子元素放回文本之间的位置。如果你只使用 getOwnText()
.
你就不能这样做
我自己Jsoup用得不多,欢迎大家改进。
我就是这样工作的(非常关闭)
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.nodes.Node;
import org.jsoup.nodes.TextNode;
import org.jsoup.parser.Parser;
public class HtmlText {
public static void main(String[] args) {
String test = "text1\ntext2<tag>tagged text \n tagged continue</tag> \ntext3";
System.out.println("-----=============----------");
System.out.println(test);
System.out.println("-----=============----------");
System.out.println(ReplaceWithSoup(test));
}
private static String ReplaceWithSoup(String source) {
StringBuilder sbResult = new StringBuilder();
Document doc = Jsoup.parseBodyFragment(source);
Element body = doc.body();
for(Node node: body.childNodes()) {
if(node instanceof TextNode) {
TextNode tn = (TextNode) node;
tn.text(tn.getWholeText().replace("\n","<br/>"));
}
sbResult.append(Parser.unescapeEntities(node.toString(), true));
}
return sbResult.toString();
}
}
我正在寻找 Java 解决方案,以在给定 HTML 字符串的所有多行文本字段中用 <br/>
标记替换换行符,即 不包含在任何标签中(虚根的子代)。
源数据是通过前端 HTML 编辑器(如 TinyMCE)创建的 HTML 格式的文本。所以它是一个任意的 HTML 片段 - 不存在的 <body>
.
以下:
text11
text 21<p>tagged text1
tagged text2</p>
text 2
应该变成:
text11<br/>text 21<p>tagged text1
tagged text2</p></br>text 2
但是,以下内容完全不会受到影响:
<div>text11
text 21<p>tagged text1
tagged text2</p>
text 2</div>
我在想这样的事情(不工作):
private static String ReplaceLfWithBr(String source) {
// text - combination of words and line breaks
// should not be preceded by <tag> or followed by <\tag>
final String regex = "((?!<.+>)[\w(\r?\n)]+(?!<\s*/.+>))";
Pattern patern = Pattern.compile(regex, Pattern.MULTILINE);
Matcher matcher = patern.matcher(source);
StringBuffer sb = new StringBuffer(source.length());
while(matcher.find()){
matcher.appendReplacement(sb, "<br/>");
}
matcher.appendTail(sb);
return sb.toString();
}
所以它比我在评论中所说的要复杂一些,但我认为这样的事情可能会奏效:
public static void main (String[] args)
{
String text = "text11\n"
+ "text 21<p>tagged text1\n"
+ "tagged text2</p>\n"
+ "text 2";
StringBuilder sb = new StringBuilder("<body>");
sb.append(text);
sb.append("</body>");
Document doc = Jsoup.parseBodyFragment(sb.toString());
Element body = doc.select("body");
List<Node> children = body.childNodes();
StringBuilder sb2 = new StringBuilder();
for(Node n : children) {
if(n instanceof TextNode) {
n.text(n.getWholeText().replace("\n", "<br/>"));
}
sb2.append(n.toString());
}
System.out.println(sb2.toString());
}
基本上获取所有 Nodes
,对 TextNodes
进行替换,然后将它们放回原处。我不是 100% 确定这会按原样工作,因为我目前无法对其进行测试。但希望它能传达这个想法。
我在评论中所说的不起作用,因为您必须能够将子元素放回文本之间的位置。如果你只使用 getOwnText()
.
我自己Jsoup用得不多,欢迎大家改进。
我就是这样工作的(非常关闭
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.nodes.Node;
import org.jsoup.nodes.TextNode;
import org.jsoup.parser.Parser;
public class HtmlText {
public static void main(String[] args) {
String test = "text1\ntext2<tag>tagged text \n tagged continue</tag> \ntext3";
System.out.println("-----=============----------");
System.out.println(test);
System.out.println("-----=============----------");
System.out.println(ReplaceWithSoup(test));
}
private static String ReplaceWithSoup(String source) {
StringBuilder sbResult = new StringBuilder();
Document doc = Jsoup.parseBodyFragment(source);
Element body = doc.body();
for(Node node: body.childNodes()) {
if(node instanceof TextNode) {
TextNode tn = (TextNode) node;
tn.text(tn.getWholeText().replace("\n","<br/>"));
}
sbResult.append(Parser.unescapeEntities(node.toString(), true));
}
return sbResult.toString();
}
}