4

我将这个 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]

但我不明白。

4

3 回答 3

4

采用:

 (//table[@class='StandardTable']
     /tbody/tr)
         [position()>1]
                   /td[2]
                       [not(a/img)] 

|

 (//table[@class='StandardTable']
     /tbody/tr)
         [position()>1]
                   /td[2]
                      /a/img

一般来说,如果我们想$ns1在某个条件$cond为真时选择一个节点集($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
        )
于 2011-12-19T21:13:52.263 回答
2

您可以选择两个互斥表达式的并集(注意并|集运算符):

//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
于 2011-12-19T21:15:17.837 回答
0

这很丑陋,甚至可能不起作用,但原则应该:

//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 ) )]
于 2011-12-19T21:14:32.253 回答