【问题标题】:How to parse HTML/XML tags according to NOT conditions in [r]如何根据 [r] 中的 NOT 条件解析 HTML/XML 标记
【发布时间】:2015-05-31 11:35:16
【问题描述】:

最亲爱的 StackOverflow 兄弟们,

我正在使用 EverNote 输出的 HTML,需要解析以下内容:

  • 备注标题
  • 笔记锚点(笔记本身的超链接标识)
  • 笔记创建日期
  • 备注内容,以及
  • 笔记本内的超链接( 笔记内容中的链接到另一个笔记的锚点)

根据 [r] XML 包的作者和SO answer by @jdharrison 的作者examples by Duncan Temple Lang,我已经能够相对轻松地解析笔记标题、笔记锚点和笔记创建日期。对于那些可能感兴趣的人,这样做的命令是

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 导出示例的fiddle

我一直在解析1。注意内容2。笔记本内的超链接

仔细查看代码,很明显第一部分的解决方案是返回每个包含属性为 bgcolor="#D4DDE5" 的表的最上层* div。 这是如何实现的?

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

“它允许我们表达诸如“找到所有名为 a 的节点”或“找到所有名为 a 且没有名为 b 的属性的节点”或“节点 a >具有等于 'bob' 的属性" 或 "找到所有节点 a 有 c 作为>一个祖先节点"

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

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

<a href="#13178">

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

更新 1

最上面的 div 我想说的是最外面的 div。 EverNote HMTL 导出中每个笔记的内容都在 DOM 最外层的 div 中。因此,感兴趣的是返回不包含属性为 bgcolor="#D4DDE5" 的表的每个最外层 div。

【问题讨论】:

  • 您能否也将所需的结果添加到帖子中

标签: html r xpath xml-parsing


【解决方案1】:

"....返回不包含属性为 bgcolor="#D4DDE5" 的表的每个最上面的 div。这是如何完成的?"

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

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

XPath 上方显示:选择所有没有子元素 &lt;table&gt;bgcolor 属性等于 #D4DDE5&lt;div&gt;

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

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

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

更新:

考虑到“最外层”的 div:

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

旁注:我不确切知道 XPath not() 是如何定义的,但如果它通常像 negation 一样工作,(这已由 OP 确认在下面的评论中)您可以申请De Morgan's law 之一:

"not (A or B)" 与 "(not A) and (not B)" 相同。

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

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

【讨论】:

  • 您对xpathApply(doc, "//div[not(table[@bgcolor='#D4DDE5'])]", xmlValue) 的第二条建议很划算。我所说的 upper-most div 的意思是它们是最伟大的祖先 div。我没有称它们为 root div,因为这个词在 XML 包中的定义很窄,意思是 only the top of the DOM。也许我应该称它们为最外层的 div...我将编辑帖子
  • 如何继续获得最外层的 div? 我认为这涉及匹配每个 xmlParent() 操作返回 body 标签的 div 标签。跨度>
  • @zelusp 我不确定r 的具体解决方案,但是在没有祖先&lt;div&gt; 的情况下获取&lt;div&gt; 的xpath 表达式是这样的://div[not(ancestor::div)]
  • @zelusp 检查更新部分
  • &gt; identical(html.notesExpanded,html.notesSimplified) [1] TRUE
猜你喜欢
  • 2014-06-25
  • 2023-02-23
  • 2017-06-12
  • 1970-01-01
  • 2019-03-03
  • 1970-01-01
  • 1970-01-01
  • 2017-05-27
  • 2017-08-05
相关资源
最近更新 更多