如何使用Jsoup选择只包含空格的元素?

3
我在选择只有空格的元素时遇到了问题。
给定以下html:<html><body><p> </p></body></html>,使用 :empty 无法选择p元素,我想是因为它包含一个文本节点 " "。
然而,:matchesOwn(^\\s+$) 也无法选择它,因为似乎 JSoup 在对文本进行正则表达式匹配之前会执行 trim() 操作。 :matchesOwn(^$) 可以选择它,但也会选择没有文本节点且不为空的元素。
也许我漏了什么? :matchesOwn 不应该进行 trim 操作,因为它使用的是正则表达式,整个文本应该被评估。

1
如果没有某种解决方法,这将无法正常工作(至少在当前版本中是这样)。就像你说的那样:空白被修剪了 - 可以通过 element.text().isEmpty() 进行检查,返回值为 true。最好的解决方案是在 Jsoup 的 Github 问题页面提交一个问题 - ollo
1
@ollo 这里有一个涉及 Jsoup API 的解决方法:https://dev59.com/C4rda4cB1Zd3GeqPTv9v#35012778。 - Stephan
谢谢提示。 - ollo
1个回答

0

CSS选择器只能匹配特定类型的节点:元素。选择器无法找到注释或文本节点。要查找仅包含空格的元素,我们必须依赖Jsoup API。

我们将寻找具有一个唯一文本节点子级的节点。此唯一文本节点必须与以下正则表达式匹配^\s+$。要获取(未修剪的)文本,我们将调用TextNode#getWholeText方法。

以下是如何执行此操作:

String html = "<html><body><div><p> </p><p> </p><span>\n\t\n   </span></div><span></span></body></html>";

Document doc = Jsoup.parse(html);

final Matcher onlyWhitespaceMatcher = Pattern.compile("^\\s+$").matcher("");
new NodeTraversor(new NodeVisitor() {

    @Override
    public void head(Node node, int depth) {
        List<Node> childNodes = node.childNodes();
        // * We're looking for nodes with one child only otherwise we move on
        if (childNodes.size() != 1) {
            return;
        }

        // * This unique child node must be a TextNode
        Node uniqueChildNode = childNodes.get(0);
        if (uniqueChildNode instanceof TextNode == false) {
            return;
        }

        // * This unique TextNode must be whitespace only
        if (onlyWhitespaceMatcher.reset(((TextNode) uniqueChildNode).getWholeText()).matches()) {
            System.out.println(node.nodeName());
        }
    }

    @Override
    public void tail(Node node, int depth) {
        // void
    }
}).traverse(doc);
// Instead of traversing the whole document,
// we could narrow down the search to its body only with doc.body()

输出

p
p
span

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接