2009-11-18 28 views
1

朋友正在写一个广告脚本,该脚本将选定短语的链接放在HTML代码中。检查短语不在<a>(或其他)元素

当然,如果这句话已经是一个<a>元素中(或其他元素不允许它 - 就像如果这句话是在元素的属性中找到),他不希望脚本写出一个链接,因为它会打破验证。

他问我我在想什么。经过一番混乱之后,我问你所有的想法。

只是为了澄清,输入是HTML中的整个博客文章。例如:

<p>This is a short blog post about ponies!</p> 
<p>I have <a href="/ponies">written about ponies before</a>.</p> 
<p><img src="/media/ponies.jpg" /></p> 

对于这个例子,说我想要替换ponies(任何情况下)与<a href="http://www.ponies.com">ponies</a>(但与原来的情况下)。

从上面的输出应为:

<p>This is a short blog post about <a href="http://www.ponies.com">ponies</a>!</p> 
<p>I have <a href="/ponies">written about ponies before</a>.</p> 
<p><img src="/media/ponies.jpg" /></p> 

我们并不需要完整的代码,但好的创意/正则表达式是非常受欢迎的。他正在用PHP写这篇文章,但语言无关紧要。

回答

3

我很抱歉,但我不得不说

Parsing Html The Cthulhu Way

+0

+1的吸住到的所有者回答(这是一个很好的答案btw) – Buggabill 2009-11-18 17:44:56

+2

不回答这个问题,只是指出一个错误的方式,人们有时会接近这个问题。 – 2009-11-18 21:17:24

+0

确实。我没有试图解析HTML,只是检查一个短语是呈现文本,不在无效元素内。当然,答案可能是解析HTML以找出答案,但告诉我们不该做什么,并没有让我们接近这个问题的最佳解决方案。 – Oli 2009-11-18 22:08:50

6

使用XPath表达式查找包含你想要的字符串文本节点,但前提是他们可以接受的元素的孩子:

//p/text()[contains(.,'ponies')] 

这将给你你知道你可以直接摆弄的文本节点。此时,您可以安全地使用正则表达式来查找关键字,但是最好直接进行搜索替换而不是模式匹配。

用于提供的示例输入,唯一的匹配是"This is a short blog post about ponies!"<a>元素中的“小马”不匹配,因为这仅适用于<p>元素的直接子元素。您可以对其进行细化以使其与其他元素(例如<div>)匹配,或仅匹配特定的<p>元素(例如具有特定类的元素)。

使用类似这样的XPath表达式的好处是它只会返回文本节点。这意味着“小马”将永远不会出现在任何HTML元素旁边,所以在XPath完成它的事情之后使用正则表达式是绝对安全的,而不会引起Cthulhu的愤怒。

XPath是处理XML和HTML的常用方法。 PHP有许多XPath库供您选择。赔率是你已经在使用一个与XPath兼容的库。


另一种方法是找到HTML文档中的所有文本节点,并通过父母的内容来筛选它们。其结果是完全一样的,但根据您的要求,这样可以更好的扩展:

//text()[parent::p and contains(.,'ponies')] 

这种表达内容是这样的:

//text()     # Find all text nodes in the document 
    [parent::p   # whose parent is a "p" element 
    and     # and 
    contains(.,'ponies')] # contains the string "ponies" 
+0

+1快乐的出生周日! – alex 2009-11-19 14:43:21