我将这个xPath表达式放入htmlCleaner:
//table[@class='StandardTable']/tbody/tr[position()>1]/td[2]/a/img
现在,我的问题是,它的变化,有时/a/img元素不存在。所以我想要一个表达式包含所有元素
//table[@class='StandardTable']/tbody/tr[position()>1]/td[2]/a/img
当/a/img存在时,
//table[@class='StandardTable']/tbody/tr[position()>1]/td[2]
当/a/img不存在时。
有人知道怎么做吗?我在另一个问题中发现了一些看起来可能对我有帮助的东西
descendant-or-self::*[self::body or self::span/parent::body]
使用说明:
(//table[@class='StandardTable']
/tbody/tr)
[position()>1]
/td[2]
[not(a/img)]
|
(//table[@class='StandardTable']
/tbody/tr)
[position()>1]
/td[2]
/a/img
通常,如果我们希望在某些条件$cond
为真时选择一个节点集($ns1
),否则选择另一个节点集($ns2
),则可以使用以下单个XPath表达式指定:
$ns1[$cond] | $ns2[not($cond)]
在本例中,ns1
为:
(//table[@class='StandardTable']
/tbody/tr)
[position()>1]
/td[2]
/a/img
和ns2
是:
(//table[@class='StandardTable']
/tbody/tr)
[position()>1]
/td[2]
和$cond
是:
boolean( (//table[@class='StandardTable']
/tbody/tr)
[position()>1]
/td[2]
/a/img
)
您可以选择两个互斥表达式的并集(注意|
联合运算符):
//table[@class='StandardTable']/tbody/tr[position()>1]/td[2]/a/img|
//table[@class='StandardTable']/tbody/tr[position()>1]/td[2][not(a/img)]
当第一个表达式返回节点时,第二个表达式将不返回(反之亦然),这意味着您将始终只得到所需的节点。
从你对@Dimitre的回答的评论中,我看到HTMLCleaner并不完全支持XPath 1.0。你真的不需要它。你只需要HTMLCleaner来解析格式不正确的输入。完成该工作后,将其输出转换为标准org.w3c.dom.Document
并将其作为XML处理。
下面是一个转换的例子:
TagNode tagNode = new HtmlCleaner().clean("<html><div><p>test");
Document doc = new DomSerializer(new CleanerProperties()).createDOM(tagNode);
从这里开始,只需使用JAXP和您想要的任何实现:
XPath xpath = XPathFactory.newInstance().newXPath();
Node node = (Node) xpath.evaluate("/html/body/div/p[not(child::*)]",
doc, XPathConstants.NODE);
System.out.println(node.getTextContent());
输出:test
这很难看,甚至可能不工作,但原则应该:
//table[@class='StandardTable']/tbody/tr[position()>1]/td[2][exists( /a/img )]/a/img | //table[@class='StandardTable']/tbody/tr[position()>1]/td[2][not( exists( /a/img ) )]