按标签将字符串拆分为不同的变量

时间:2017-01-18 21:34:39

标签: java regex

我需要拆分包含带标签的部分的字符串。例如:

String str = "This text is not highlighted <hlTag>but this is</hlTag> this"
           + " isn't again <hlTag>and this is</hlTag>";

问题是应该将所有部分保存到不同的变量中(在本例中我只是将它们打印出来),所以我的解析器应该知道哪些部分在标签内部而哪些部分没有。

我已经有了解决方案并且它可以正常工作,但我在这两种情况下使用了两个正则表达式,我认为它可以简化,所以我请求你的帮助。

EDITED

我意识到我的解决方案是错误的 - 我放松了部件的顺序,我需要它得到尊重。我需要解析一次字符串并将部分保存到标记和非标记部分的不同对象中,如下所示 - 如果突出显示,则为list.add(new HighlPart(text)),否则为list.add(new NonHighlPart(text))。< / p>

有人可以帮我吗?

String preTag = "<hlTag>";
String postTag = "</hlTag>";

Matcher insideTagsMatcher = Pattern.compile(preTag + "(.+?)" + postTag).matcher(str);
Matcher outsideTagsMatcher = Pattern.compile("^(.*?)" + preTag +
    "|" + postTag + "(.*?)" + preTag +
    "|" + "</hlTag>(.*?)$").matcher(str);

System.out.println("Highlighted:");
while (insideTagsMatcher.find()) {
    System.out.println(insideTagsMatcher.group(1));
}

System.out.println("\nNot highlighted:");
while (outsideTagsMatcher.find()) {
    for (int i = 1; i <= outsideTagsMatcher.groupCount(); i++) {
        // each pattern group returns two nulls except of string we need
        if (outsideTagsMatcher.group(i) != null)
            System.out.println(outsideTagsMatcher.group(i));
    }
}

结果是:

Highlighted:
but this is
and this is

Not highlighted:
This text is not highlighted
this isn't again

1 个答案:

答案 0 :(得分:1)

更简洁,更安全的方法是使用Jsoup

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.TextNode;
import java.util.List;
import java.util.stream.Collectors;

public class Test {
public static void main(String[] args) {
    Document document = Jsoup.parse("This text is not highlighted <hlTag>but this is</hlTag> this isn't again <hlTag>and this is</hlTag>");

    List<String> highlighted = document.select("hlTag")
            .stream()
            .map(element -> element.html())
            .collect(Collectors.toList());

    List<String> nonHighlighted = document.body().childNodes().stream()
            .filter(node -> node instanceof TextNode)
            .map(node -> node.toString().replaceAll("\n",""))
            .collect(Collectors.toList());

    highlighted.forEach(System.out::println);
    nonHighlighted.forEach(System.out::println);
}
}

输出:

but this is
and this is
This text is not highlighted 
 this isn't again 
有问题的更改后

更新

List保持插入元素的顺序。您不能向List添加不同类型的对象。如果我正确理解您的新需求,您可以执行以下操作:

List<Node> nodes = document.body().childNodes(); 
nodes.forEach(System.out::println);

节点是节点元素列表。每个节点(在该示例中)可以是TextNodeElement类型。在您的示例中,TextNode对应于从body中解析时未包含在标记中的内容,而Element对象对应于带有标记的内容。这样,您将拥有一个包含所有元素的唯一List,您可以使用它的对象类型(instanceof)来区分它们。

您想要打印突出显示的部分吗?然后:

nodes.stream().filter(node -> node instanceof TextNode).forEach(System.out::println);

想要打印非高亮部分吗?然后:

nodes.stream().filter(node -> node instanceof Element).forEach(System.out::println);