【问题标题】:HtmlAgilityPack with XPath - retrieve nodes that doesn't contain  带有 XPath 的 HtmlAgilityPack - 检索不包含的节点
【发布时间】:2011-04-30 07:08:13
【问题描述】:

我正在尝试使用 C# 中的 HtmlAgilityPack 检索一定数量的包含值  (空格)的元素。这是我的 XPath 表达式:

"(td)[(position() >= 10 and position() <= last()) and not(.='&nbsp;')]"

但它仍然给我这些节点,我尝试使用文字空间,&amp;#160; ALT + 1060 - 似乎没有任何效果。这是我正在解析的内容:

 <tr height=20 style='mso-height-source:userset;height:15.0pt'>
  <td height=20 class=xl96 style='height:15.0pt'>&nbsp;</td>
  <td class=xl97>&nbsp;</td>
  <td class=xl106 style='border-top:none'>JIM COCKS</td>
  <td class=xl107 style='border-top:none;border-left:none'>&nbsp;</td>
  <td class=xl107 style='border-top:none;border-left:none'>&nbsp;</td>
  <td class=xl107 style='border-top:none;border-left:none'>HOL</td>
  <td class=xl76>&nbsp;</td>
  <td class=xl103 style='border-left:none'>&nbsp;</td>
  <td class=xl97>&nbsp;</td>
  <td class=xl104 style='border-top:none'>&nbsp;</td>
  <td class=xl104 style='border-top:none;border-left:none'>&nbsp;</td>
  <td class=xl104 style='border-top:none;border-left:none'>&nbsp;</td>
  <td class=xl104 style='border-top:none;border-left:none'>&nbsp;</td>
  <td class=xl104 style='border-top:none;border-left:none'>&nbsp;</td>
  <td class=xl104 style='border-top:none;border-left:none'>&nbsp;</td>
  <td class=xl104 style='border-top:none;border-left:none'>&nbsp;</td>
  <td class=xl104 style='border-top:none;border-left:none'>&nbsp;</td>
  <td class=xl104 style='border-top:none;border-left:none'>09:30</td>
  <td class=xl104 style='border-top:none;border-left:none'>&nbsp;</td>
  <td class=xl104 style='border-top:none;border-left:none'>&nbsp;</td>
  <td class=xl104 style='border-top:none;border-left:none'>&nbsp;</td>
  <td class=xl104 style='border-top:none;border-left:none'>&nbsp;</td>
  <td class=xl104 style='border-top:none;border-left:none'>&nbsp;</td> 
  <td class=xl104 style='border-top:none;border-left:none'>&nbsp;</td>
  <td class=xl104 style='border-top:none;border-left:none'>&nbsp;</td>
  <td class=xl104 style='border-top:none;border-left:none'>&nbsp;</td>
  <td class=xl104 style='border-top:none;border-left:none'>&nbsp;</td>
  <td class=xl104 style='border-top:none;border-left:none'>&nbsp;</td>
  <td class=xl104 style='border-top:none;border-left:none'>&nbsp;</td>
  <td class=xl104 style='border-top:none;border-left:none'>&nbsp;</td>
  <td class=xl104 style='border-top:none;border-left:none'>&nbsp;</td>
  <td class=xl104 style='border-top:none;border-left:none'>&nbsp;</td>
  <td class=xl104 style='border-top:none;border-left:none'>&nbsp;</td>
  <td class=xl104 style='border-top:none;border-left:none'>&nbsp;</td>
  <td class=xl104 style='border-top:none;border-left:none'>&nbsp;</td>
  <td class=xl104 style='border-top:none;border-left:none'>&nbsp;</td>
  <td class=xl104 style='border-top:none;border-left:none'>&nbsp;</td>
  <td class=xl104 style='border-top:none;border-left:none'>&nbsp;</td>
  <td class=xl104 style='border-top:none;border-left:none'>&nbsp;</td>
  <td class=xl104 style='border-top:none;border-left:none'>&nbsp;</td>
  <td class=xl104 style='border-top:none;border-left:none'>17:00</td>
  <td class=xl104 style='border-top:none;border-left:none'>&nbsp;</td>
  <td class=xl104 style='border-top:none;border-left:none'>&nbsp;</td>
  <td class=xl104 style='border-top:none;border-left:none'>&nbsp;</td>
  <td class=xl104 style='border-top:none;border-left:none'>&nbsp;</td>
  <td class=xl76>&nbsp;</td>
 </tr>

“xl104”类的项目是我想要抓取的(我已经在它们的类发生变化时使用位置语句完成了此操作)但我只想要包含&amp;nbsp; 以外的其他内容的节点,例如您在上面看到的 09:30 和 17:00。

【问题讨论】:

  • 哎呀。该 HTML 非常无效。如果你正在生成它,你应该清理它。如果你因为没有生成它而被它卡住了,祝你好运!
  • @Stephen - HTML Agility Pack 可以很好地处理格式错误的 HTML。这个片段看起来不错,HTML 明智。
  • 我承认“HTML Agility Pack 可以很好地处理格式错误的 HTML”,因为我对此一无所知。但是,这个片段看起来不太好。缺少类属性值的引号,样式属性值的单引号,专有的“mso-height-source”Microsoft Office CSS 属性......至少该表似乎代表表格数据。
  • @Stephen - 不幸的是它是由 Excel 2007 生成的。虽然 Html Agility Pack 似乎处理得很好,但我仍然可以对属性执行 XPath 表达式。例如,我更进一步:"//tr[@height='20'][count(td)=46]")
  • @Stephen - 这些在早期的 HTML 标准中都很好。属性值不必加引号,单引号也可以,未知的CSS样式也可以。 HTML 是一个非常宽容的标准。

标签: c# html xpath


【解决方案1】:
"(td)[(position() >= 10 and position() <= last()) and not(.='&nbsp;')]" 

not(.='&amp;nbsp;')

测试整个 text() 节点不是字符串'&amp;nbsp;'

您想使用 XPath contains() 函数

not(contains(., '&#xA0;'))

【讨论】:

  • 是的,我也很想这么说。然而他的td 元素似乎有  作为他们的整个文本节点值......没有别的。所以如果这确实是问题,那将是令人费解的。
  • 成功了!我知道有一个 contains() fn,但我从来没有想过要使用它,因为正如 LarsH 所说,所有 td 元素 just 都有  在他们之中。不管怎么说,还是要谢谢你! :-)
  • @eth0,鉴于此,我怀疑您的输入 XML 不是您认为的那样(即不是您在上面显示的那样)。额外的空格可能已经进入。当您选择 string-length(td[10]) 时会发生什么?
【解决方案2】:

我正在尝试检索选定的金额 不包含的元素 值&amp;nbsp;

我相信@Dimitre 已经回答了该任务规范。

我只想要包含的节点 除了&amp;nbsp;

规格略有不同。 这行得通吗? (已编辑;感谢 Alejandro。)

"td[position() >= 10 and translate(., '&#xA0;', '') != '']" 

这是等效的并且更短,但可读性较差:

"td[position() >= 10 and translate(., '&#xA0;', '')]" 

不管怎样,你发现了问题,所以我们不会再进一步​​了。

但请注意,除非您定义它,否则在 XPath 中按字面意思使用 &amp;nbsp; 不会正常工作。这个字符实体是在 HTML 中预定义的,而不是在 XML 中。这就是为什么&amp;#160;&amp;#xA0; 更可靠的原因。但是,HtmlAgilityPack 可能会为您定义。

【讨论】:

  • fn:position() 结果应始终小于或等于 fn:last()。此外,如果字符串为空,则布尔值应为 false,否则为 true。所以,td[position() &gt;= 10 and translate(.,'&amp;#A0;','')]
  • @Alej:谢谢……老实说,我只看了谓词中与 nbsp 相关的部分。我将编辑我的答案。
猜你喜欢
  • 2021-06-09
  • 2011-07-24
  • 1970-01-01
  • 2014-07-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多