我在选择只有空格的元素时遇到问题。
鉴于 html:<html><body><p> </p></body></html>
使用 :empty 不会选择我假设的 p,因为其中有一个文本节点 ""
然而,:matchesOwn(^\\s+$)
也不会选择它,因为 JSoup 似乎做了一个 trim()
在根据正则表达式模式测试文本之前。
:matchesOwn(^$)
将选择它,但也会选择没有非空文本节点的元素
也许我遗漏了什么?
:matchesOwn
根本不应该修剪,因为它使用的是正则表达式,并且应该评估整个文本
请您参考如下方法:
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