Xpath 问题选择 <spans> 嵌套在 <td>
Xpath issues selecting <spans> nested in <td>
我正在尝试使用一个程序从大量 XHTML 文档中提取文本,该程序使用 Xpath 查询将文本映射到结构化 table。 XHTML 文档看起来像这样
<td class="td-3 c12" valign="top">
<p class="pa-4">
<span class="ca-5">text I would like to select </span>
</p>
</td>
<td class="td-3 c13" valign="top">
<p class="pa-2">
<span class="ca-0">some more text I want to select </span>
</p>
<p class="pa-2">
<span class="ca-0">
<br>
</br>
</span>
</p>
<p class="pa-2">
<span class="ca-5">text and values I don't want to select.</span>
</p>
<p class="pa-2">
<span class="ca-5"> also text and values I don't want to </span>
</p>
</td>
我可以 select 按 class 的跨度并检索 text/values,但是它们不够独特,我需要按 table classes。例如,只有来自 span class ca-0 的文本是 td class td-3 c13 的子项
这将是 <span class="ca-0">some more text I want to select </span>
我已经尝试了所有这些组合
//xhtml:td[@class="td-3 c13"]/xhtml:span[@class = "ca-0"]
//xhtml:span[@class = "ca-0"] //ancestor::xhtml:td[@class= "td-3 c13"]
//xhtml:td[@class="td-3 c6"]//xhtml:span[@class = "ca-0"]
我不确定你的样本 xml 在多大程度上反映了你的实际 xml,但严格基于你的样本 xml(并忽略你可能会遇到的命名空间问题) ,以下 xpath 表达式:
//td[contains(@class,"td-3")]/p[1]/span/text()
选择
text I would like to select
some more text I want to select
根据 doc,为了支持名称空间,您应该这样写 (fn:...) :
//*:td[fn:contains(@class,"td-3")]/*:p[1]/*:span
或使用绑定命名空间:
node.xpath("//xhtml:td[fn:contains(@class,'td-3')]/xhtml:p[1]/xhtml:span", {"xhtml":"http://example.com/ns"})
这个表达式也应该有效(select 每个 td 元素的第一个 p 的第一个跨度):
//*:td/*:p[1]/*:span[1]
旁注:
您的 XPath 表达式可能已修复。 Span 不是 child 而是后代,所以我们使用 //
。我们使用 ()
只保留第一个结果。
(//xhtml:td[@class="td-3 c13"]//xhtml:span[@class = "ca-0"])[1]
(//xhtml:td[@class="td-3 c6"]//xhtml:span[@class = "ca-0"])[1]
用谓词 []
替换 //
:
(//xhtml:span[@class = "ca-0"][ancestor::xhtml:td[@class= "td-3 c13"]])[1]
使用以下命令测试您的 XPath:https://docs.marklogic.com/cts.validIndexPath
解决方法是
//td[(@class ="td-3") and (@class = "c13)]/p/span
出于某种原因,它看到
<td class="td-3 c13">
作为单独的 类 例如
<td class = "td-3" and class = "c13"
所以你需要这样对待它们
感谢@E.Wiest 和@JackFleeting 的验证并为我指明了正确的方向。
我正在尝试使用一个程序从大量 XHTML 文档中提取文本,该程序使用 Xpath 查询将文本映射到结构化 table。 XHTML 文档看起来像这样
<td class="td-3 c12" valign="top">
<p class="pa-4">
<span class="ca-5">text I would like to select </span>
</p>
</td>
<td class="td-3 c13" valign="top">
<p class="pa-2">
<span class="ca-0">some more text I want to select </span>
</p>
<p class="pa-2">
<span class="ca-0">
<br>
</br>
</span>
</p>
<p class="pa-2">
<span class="ca-5">text and values I don't want to select.</span>
</p>
<p class="pa-2">
<span class="ca-5"> also text and values I don't want to </span>
</p>
</td>
我可以 select 按 class 的跨度并检索 text/values,但是它们不够独特,我需要按 table classes。例如,只有来自 span class ca-0 的文本是 td class td-3 c13 的子项
这将是 <span class="ca-0">some more text I want to select </span>
我已经尝试了所有这些组合
//xhtml:td[@class="td-3 c13"]/xhtml:span[@class = "ca-0"]
//xhtml:span[@class = "ca-0"] //ancestor::xhtml:td[@class= "td-3 c13"]
//xhtml:td[@class="td-3 c6"]//xhtml:span[@class = "ca-0"]
我不确定你的样本 xml 在多大程度上反映了你的实际 xml,但严格基于你的样本 xml(并忽略你可能会遇到的命名空间问题) ,以下 xpath 表达式:
//td[contains(@class,"td-3")]/p[1]/span/text()
选择
text I would like to select
some more text I want to select
根据 doc,为了支持名称空间,您应该这样写 (fn:...) :
//*:td[fn:contains(@class,"td-3")]/*:p[1]/*:span
或使用绑定命名空间:
node.xpath("//xhtml:td[fn:contains(@class,'td-3')]/xhtml:p[1]/xhtml:span", {"xhtml":"http://example.com/ns"})
这个表达式也应该有效(select 每个 td 元素的第一个 p 的第一个跨度):
//*:td/*:p[1]/*:span[1]
旁注:
您的 XPath 表达式可能已修复。 Span 不是 child 而是后代,所以我们使用 //
。我们使用 ()
只保留第一个结果。
(//xhtml:td[@class="td-3 c13"]//xhtml:span[@class = "ca-0"])[1]
(//xhtml:td[@class="td-3 c6"]//xhtml:span[@class = "ca-0"])[1]
用谓词 []
替换 //
:
(//xhtml:span[@class = "ca-0"][ancestor::xhtml:td[@class= "td-3 c13"]])[1]
使用以下命令测试您的 XPath:https://docs.marklogic.com/cts.validIndexPath
解决方法是
//td[(@class ="td-3") and (@class = "c13)]/p/span
出于某种原因,它看到
<td class="td-3 c13">
作为单独的 类 例如
<td class = "td-3" and class = "c13"
所以你需要这样对待它们
感谢@E.Wiest 和@JackFleeting 的验证并为我指明了正确的方向。