如何使用单个XPath查询选择节点集?

时间:2011-02-25 13:40:54

标签: xpath

我正在尝试从我最喜欢的航空公司提取旅程和价格信息。

我的搜索结果页面如下所示:

MASwings search results http://img28.imagevenue.com/aAfkjfp01fo1i-2846/loc29/42467_dayview_oneway_122_29lo.jpg

编辑:图片主机可能已阻止热链接。请参阅此页面上的图片:http://img28.imagevenue.com/img.php?image=42467_dayview_oneway_122_29lo.jpg

Repro URL for booking query

我可以使用此XPath选择器选择代表航班的每一行:

//*[@class="servicecode "]/ancestor::tr[1]

但每个航班都不是一个独立的旅程;这些航班确实分为两条腿,这些都是我想要选择的。

每个新分支的行类交替:第一个分支的行具有“datarow”类,而下一个分支的行具有“datarow alt”。在Python中,我可以使用itertools.groupby对上面表达式选择的节点进行分组,但是如果有一种方法可以在XPath中实现这一点,我更喜欢它。

此问题的扩展名:我的选择器会选择所有行,无论航班是否已售罄。我可以使用此选择器选择每个可预订旅程的第一个航班:

//*[contains(@class, "datarow")][.//input]

但是如果腿有多个航班,那么我将不得不使用另一个XPath查询来查找同一个班级的兄弟姐妹。

是否有一个XPath查询会将每个可预订的部分作为节点集返回给我?

注意:我正在使用Python lxml库,以防万一。

2 个答案:

答案 0 :(得分:1)

I can select each row that represents a flight using this XPath selector:

     //*[@class="servicecode "]/ancestor::tr[1] 

But each flight row is not an independent journey; the flights are really grouped into legs, and these are what I want to select.

The row class alternates for each new leg: the rows of the first leg have class "datarow",

使用

//tr[@class='datarow'][.//*[@class='servicecode']]
  

这个问题的延伸:我的   选择器选择所有行,无论是   航班售罄与否。我可以   选择每个航班的第一个航班   使用此选择器的可预订旅程:

//*[contains(@class, "datarow")][.//input]
     

但如果腿有多个   飞行,然后我将不得不寻找   跟随同一个班级的兄弟姐妹   使用另一个XPath查询。

     

是否有单个XPath查询   将每个可预订的腿归还给我   节点集?

  (//tr[@class='datarow'])[1]//input 
| 
  (//tr[@class='datarow'])[1]
         //following-sibling::tr[@class='datarow altrow']
                   [count(preceding-sibling::tr[@class='datarow'])=1]
                         //input

此XPath表达式选择代表第一次旅程中每条可预订腿(在本例中为3条腿)的所有tr个元素。

要获得第二次旅程的所有支路,请使用1替换上述表达式中的2

要获得第k次旅程的所有支路,请将上述表达式中的1替换为k的实际值。

答案 1 :(得分:0)

这就是我想要的。但是有更优雅的解决方案吗?

//*[contains(@class, "columns")]//tr[contains(@class, "datarow")][1]
|
//*[contains(@class, "columns")]//tr[not(contains(@class, "altrow"))]
       [preceding-sibling::tr[1]
           [contains(@class, "altrow")]]
|
//*[contains(@class, "columns")]//tr[contains(@class,"altrow")]
       [preceding-sibling::tr[1]
           [not(contains(@class, "altrow"))]]

第二部分选择每组连续行,其中类不包含“altrow”作为单个节点集。

第三部分选择每组连续行,其中包含“altrow”的类作为单个节点集。

第一部分选择第一组连续行,类不包含“altrow”,因为第二部分没有选择它。