如何根据[r]中的NOT条件解析HTML / XML标记

时间:2015-03-27 07:44:39

标签: html r xpath xml-parsing

Dearest StackOverflow homies,

我正在玩EverNote输出的HTML并需要解析以下内容:

  • 注意标题
  • 注意锚(笔记本身的超链接标识)
  • 注意创建日期
  • 注意内容和
  • 笔记本内部超链接( 注释内容中的链接到另一个注释的锚点

根据[{3}},[r] XML包的作者和examples by Duncan Temple Lang,我已经能够相对容易地解析Note Title,Note anchor和Note Creation Dates。对于那些可能感兴趣的人来说,这样做的命令是

require("XML")
rawHTML <- paste(readLines("EverNotebook.html"), collapse="\n") #Yes... this is noob code
doc = htmlTreeParse(rawHTML,useInternalNodes=T)
#Get Note Titles
html.titles<-xpathApply(doc, "//h1", xmlValue)
#Get Note Title Anchors
html.tAnchors<-xpathApply(doc, "//a[@name]", xmlGetAttr, "name")
#Get Note Creation Date
html.Dates<-xpathApply(doc, "//table[@bgcolor]/tr/td/i", xmlValue)

这是一个示例HTML EverNote导出的SO answer by @jdharrison

我坚持解析 1。注意内容 2。笔记本内部超链接

仔细看一下代码,显然第一部分的解决方案是返回包含属性为bgcolor =&#34的表的每个最高* div;# D4DDE5&#34。 这是如何完成的?

Duncan说可以使用XPath根据NOT条件解析XML:

  

&#34;它允许我们表达诸如&#34之类的东西;找到所有名为a&#34;或者&#34;找到所有名为a的节点,它们没有名为b&#34的属性;或者&#34;节点a>&gt;属性b等于&#39; bob&#39;&#34;或者&#34;找到所有节点a,其中c为&gt;祖先节点&#34;

然而,他没有继续描述XML包如何解析排除...所以我被困在那里。

解决第二部分,考虑同一笔记本中其他笔记的锚点格式:

<a href="#13178">

这些的目标是获取他们的号码,但这很困难,因为它们仅通过#前缀与www链接区分开来。有关如何通过部分匹配它们的值(在这种情况下为#)来解析这些特定锚点的信息很稀疏 - 甚至可能需要grep()。 如何使用XML包来解析这些特殊的href?我在这里描述了这两个问题,因为第一部分的解决方案可能有助于第二部分......但也许我&# 39;我错了。 有什么建议吗?

更新1

通过最上层的div我打算说最外面的div。 EverNote HMTL导出中每个音符的内容都在DOM最外层的div中。因此,兴趣是返回每个最外层的div,它不包含具有属性bgcolor =&#34;#D4DDE5的表格。&#34;

1 个答案:

答案 0 :(得分:1)

  

“....返回不包含属性为bgcolor =”#D4DDE5的表格的最上层div。“这是如何完成的?

忽略“最上层”的一种可能方式,因为我不知道你将如何定义它:

//div[not(table[@bgcolor='#D4DDE5'])]

上面的XPath读取:选择所有<div>没有子元素<table>bgcolor属性等于#D4DDE5

我不确定你在问题的第二部分“解析”是什么意思。如果您只是希望获得具有特殊href的所有链接,则可以使用hrefstarts-with()部分匹配contains()属性:

//a[starts-with(@href, '#')]

//a[contains(@href, '#')]

更新:

考虑“最外层”的div:

//div[not(table[@bgcolor='#D4DDE5']) and not(ancestor::div)]

旁注:我不知道XPath not()究竟是如何定义的,但如果它的工作方式与否定一样,那么(这就像确认的一样)通过以下评论中的OP,您可以应用De Morgan's law之一:

  

“not(A或B)”与“(不是A)和(不是B)”相同。

这样更新后的XPath可以稍微简化为:

//div[not(table[@bgcolor='#D4DDE5'] or ancestor::div)]