YQL不按照文档顺序返回带有联合操作符(a|b)的xpath选择查询

YQL does not return an xpath select query with a union operator (a|b) in document order

本文关键字:查询 选择 xpath 操作符 文档 顺序 返回 YQL      更新时间:2023-09-26

我的第一次XPath尝试-我正在努力为YQL选择查询找到XPath条件,该查询按顺序从HTML页面中输出不同的兄弟元素。我可以获得所有单独的元素,每个元素都有自己的序列(例如<p1>, <p2>, <p3><ul1>, <ul2>, <ul3>等),但不是它们在源HTML文档中遇到的序列-例如<p1> <ul1> <ul2> <ul3> <p2> <p3>

我现在最适合的是:

select * from html WHERE url = "URL of web page" AND xpath = "//div[@class = ''div class'']/p | //div[@class = ''div class'']/ul"

转换成XPath:

//div[@class = 'div class']/p | //div[@class = 'div class']/ul

我可以很容易地获得像//div[@class = 'div class']/text()这样的文本,但然后我失去了格式。是否有某种方法可以让YQL维护选定的不同元素的序列?还是我完全误解了XPath的工作原理?

编辑:示例HTML结构:

<div class = "class">
  <p>Some text</p>
  <p>Following is a list:</p>
  <ul>
    <li>item1</li>
    <li>item2</li>
    <li>item3</li>
  </ul>
  <p>Still more text</p>
</div>

我当前的XPath代码(上面)分别返回<p>元素和<ul>元素,虽然<p>元素是按顺序排列的,但无法确定<ul>元素的确切位置(它可能因页而异)。因此,我无法从XPath重构HTML。如果我使用/text(),则返回全文,按照从上到下的顺序,但是没有格式化(<p><ul>标记被忽略)—只有一行文本,各个元素之间没有空格。如果<ul>标签在<p>标签中(后代而不是兄弟),就不会有问题。这个问题只存在于不同类型的兄弟元素中。

为了复制我所看到的行为,我使用了以下命令:

SELECT * FROM html 
   WHERE url = "http://www.smh.com.au/sport/soccer/matildas-fuming-after-ffa-rejects-paid-mater‌​nity-leave-proposal-20150911-gjkq81.html" 
   AND xpath = "//div[@class = 'articleBody']/*[self::ul or self::p]"

编辑您的评论:

您可能会将结果视为XML以外的东西。例如,如果将其视为JSON,则该格式没有预定义的映射顺序。如果将其视为XML,则顺序应该与预期一致。


原答案,留作参考:

我当前的XPath代码(上面)分别返回<p>元素和<ul>元素

我相信这是yql所使用的XPath引擎中的一个bug。XPath语言的任何版本都清楚地规定,在集合与联合运算符|组合之后,元素必须按照文档顺序返回,这通常与它们在XML1中出现的顺序相同。您可以尝试使用以下XPath来修复此错误行为,其中首先选择所有子节点,然后进行筛选:

//div[@class = 'div class']/*[self::p or self::ul]

我认为它也更容易阅读。

注意:如果你用双引号引用字符串,你不需要用''转义单引号。

1命名空间和属性节点没有顺序,但顺序必须是稳定的,即两次调用选择相同的节点将以相同的顺序返回