如何在ruby中使用特殊字符在两个字符串之间获取文本?

时间:2012-10-01 00:16:47

标签: ruby regex xpath

我有一个包含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引用结束。

2 个答案:

答案 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网站搜索中找到许多示例。