在未包含在标签中的多行文本节点中用 <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();
    }
}