我有一个HTML片段,它在HTML的各个部分包含两个锚标记。
<span id="ctl00_PlaceHolderTitleBreadcrumb_ContentMap">
<span><a class="ms-sitemapdirectional" href="/">My Site</a></span>
<span> > </span>
<span><a class="ms-sitemapdirectional" href="/Lists/Announcements/AllItems.aspx">Announcements</a></span>
<span> > </span>
<span class="ms-sitemapdirectional">Settings</span>
</span>
我正在寻找一个正则表达式,它将返回第二个锚标记,其中包含'Announcements'作为文本。在尝试编写表达式时,我不断返回两个锚标记 - 但我只对第二个标记感兴趣。
是否可以仅匹配第二个标签?
修改
我将永远知道我正在寻找一个锚标签,如果有帮助的话,它的文字中有'公告'。
答案 0 :(得分:7)
将片段解析为DOM。使用XPath发出:
(//a)[2]
完成。
答案 1 :(得分:1)
像
/<a.+?>[^<>]*Announcements[^<>]*</a>/
PS。正则表达式是解析html的错误工具
答案 2 :(得分:1)
/(<a.*?<\/a>).*?(<a.*?<\/a>)/
$ 1匹配第一个标签,$ 2匹配第二个
答案 3 :(得分:0)
如果您不想这样做,则不必使用复杂的正则表达式。因为你想获得锚点,并且通常锚点有结束标记</a>
,你可以使用你喜欢的语言,并在</a>
上为每一行进行拆分。
例如伪代码
for each line in htmlfile
do
var=split line on </a>
for each item in var
do
if item has "Announcement" then
print "found"
end if
done
done
答案 4 :(得分:0)
<?php
$string = '<span id="ctl00_PlaceHolderTitleBreadcrumb_ContentMap"><span><a class="ms-sitemapdirectional" href="/">My Site</a></span><span> > </span><span><a class="ms-sitemapdirectional" href="/Lists/Announcements/AllItems.aspx">Announcements</a></span><span> > </span><span class="ms-sitemapdirectional">Settings</span></span>';
$dom = new DOMDocument();
$dom->loadHTML($string);
$anchors = $dom->getElementsByTagName('a');
if ( $anchors->length ) {
$secondAnchor = $anchors->item(1);
echo innerHTML($secondAnchor->parentNode);
}
function innerHTML($node){
$doc = new DOMDocument();
foreach ($node->childNodes as $child)
$doc->appendChild($doc->importNode($child, true));
return $doc->saveHTML();
}
答案 5 :(得分:0)
如果您知道元素的确切文本,并且您知道它是片段中此类元素的最后一个元素,那么您有足够的信息可以将它与正则表达式相匹配。我怀疑你正在使用这样的正则表达式:
/<a\s+.*>Announcements<\/a>/s
... .*
匹配第一个锚标记的<a
和第二个锚标记的>Announcements</a>
之间的所有内容。切换到非贪婪的量词:
/<a\s+.*?>Announcements<\/a>/s
......没有帮助;一个不情愿的量词尽快停止匹配,但这里的问题是启动匹配太快。您需要将.*
替换为更具体的内容,这些内容只能匹配单个标记的开头<a
和结束>
之间的内容:
/<a\s+[^<>]+>Announcements<\/a>/
现在,当它到达第一个<a>
标记的末尾并且没有看到Announcements</a>
时,它将中止该匹配尝试,移动并在第二个<a>
标记处重新开始