我有一个包含HTML代码的字符串(@description),我想在两个元素之间提取内容。它看起来像这样
<b>Content title<b><br/>
*All the content I want to extract*
<a href="javascript:print()">
我设法做了这样的事情
@want = @description.match(/Content title(.*?)javascript:print()/m)[1].strip
但显然这个解决方案远非完美,因为我在@want字符串中收到了一些不需要的字符。
感谢您的帮助
编辑:
根据评论中的要求,这里是完整的代码:
我已经在解析HTML文档,其中包含以下代码:
@description = @doc.at_css(".entry-content").to_s
puts @description
返回:
<div class="post-body entry-content">
<a href="http://www.photourl"><img alt="Photo title" height="333" src="http://photourl.com" width="500"></a><br><br><div style="text-align: justify;">
Some text</div>
<b>More text</b><br><b>More text</b><br><br><ul>
<li>Numered item</li>
<li>Numered item</li>
<li>Numered item</li>
</ul>
<br><b>Content Title</b><br>
Some text<br><br>
Some text(with links and images)<br>
Some text(with links and images)<br>
Some text(with links and images)<br>
<br><br><a href="javascript:print()"><img src="http://url.com/photo.jpg"></a>
<div style="clear: both;"></div>
</div>
文本可以包含更多段落,链接,图片等,但它始终以“内容标题”部分开头,以javascript引用结束。
答案 0 :(得分:1)
此XPath表达式选择节点$vStart
和$vEnd
之间的所有(兄弟)节点:
$vStart/following-sibling::node()
[count(.|$vEnd/preceding-sibling::node())
=
count($vEnd/preceding-sibling::node())
]
要获取在特定情况下使用的完整XPath表达式,只需将$vStart
替换为:
/*/b[. = 'Content Title']
并将$vEnd
替换为:
/*/a[@href = 'javascript:print()']
替换后的最终XPath表达式是:
/*/b[. = 'Content Title']/following-sibling::node()
[count(.|/*/a[@href = 'javascript:print()']/preceding-sibling::node())
=
count(/*/a[@href = 'javascript:print()']/preceding-sibling::node())
]
<强>解释强>:
这是两个节点集$ns1
和$ns2
交叉的Kayessian公式的简单推论:
$ns1[count(.|$ns2) = count($ns2)]
在我们的例子中,节点$vStart
和$vEnd
之间的所有节点的集合是两个节点集的交集:$vStart
的所有后续兄弟节点和{的所有前面的兄弟节点{1}}。
基于XSLT的验证:
$vEnd
将此转换应用于提供的XML文档(转换为格式良好的XML文档):
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:variable name="vStart" select="/*/b[. = 'Content Title']"/>
<xsl:variable name="vEnd" select="/*/a[@href = 'javascript:print()']"/>
<xsl:template match="/">
<xsl:copy-of select=
"$vStart/following-sibling::node()
[count(.|$vEnd/preceding-sibling::node())
=
count($vEnd/preceding-sibling::node())
]
"/>
==============
<xsl:copy-of select=
"/*/b[. = 'Content Title']/following-sibling::node()
[count(.|/*/a[@href = 'javascript:print()']/preceding-sibling::node())
=
count(/*/a[@href = 'javascript:print()']/preceding-sibling::node())
]
"/>
</xsl:template>
</xsl:stylesheet>
评估两个XPath表达式(带和不带变量引用),并将每种情况下选择的节点(方便分隔)复制到输出:
<div class="post-body entry-content">
<a href="http://www.photourl">
<img alt="Photo title" height="333" src="http://photourl.com" width="500"/>
</a>
<br />
<br />
<div style="text-align: justify;">
Some text</div>
<b>More text</b>
<br />
<b>More text</b>
<br />
<br />
<ul>
<li>Numered item</li>
<li>Numered item</li>
<li>Numered item</li>
</ul>
<br />
<b>Content Title</b>
<br />
Some text
<br />
<br />
Some text(with links and images)
<br />
Some text(with links and images)
<br />
Some text(with links and images)
<br />
<br />
<br />
<a href="javascript:print()">
<img src="http://url.com/photo.jpg"/>
</a>
<div style="clear: both;"></div>
</div>
答案 1 :(得分:0)
为了测试您的HTML,我在您的代码周围添加了标签,然后将其粘贴到file
xmllint --html --xpath '/html/body/div/text()' /tmp/l.html
输出:
Some text
Some text
Some text
Some text
现在,您可以在ruby
中使用Xpath模块并重新使用Xpath表达式
您将在stackoverflow网站搜索中找到许多示例。