我一直在分析一个输入,它是HTML。但是,我需要能够找到所有没有协议(如http://、https://或ftp://等)的href或src属性,并且当它们没有用包含协议和域的变量替换时。
例如,我想要
<a href="/_mylink/goes/here">Link 1</a>
<a href="http://site.com/_myotherlink/goes/here">Link 2</a>
返回:
<a href="http://mydomain.com/_mylink/goes/here">Link 1</a>
<a href="http://site.com/_myotherlink/goes/here">Link 2</a>
我可以获得整个href属性,但我似乎不知道如何仅在缺少协议的情况下匹配和替换它。我发现[^0-9]会以相反/不相反的方式工作,但我发现在尝试使用http://etc.时无法使其工作
编辑:
顺便提一下,因为我很清楚这是这个问题的"范围"的一部分,所以我想避免因为替换而使用url编码,因为我在其中一些上使用了{}之类的东西,我不希望它们包含%7B%7D之类的东西。
为什么不使用DOM轻松替换这些属性?例如
$domain = 'http://mydomain.com';
$currentPath = '/some/absolute/path/'; // make sure this starts and ends with a forward-slash
$doc = new DOMDocument();
$doc->loadHTML($html);
$xpath = new DOMXPath($doc);
$attrs = $xpath->query('//@href[not(contains(., "://"))]');
foreach ($attrs as $attr) {
$attr->value = sprintf('%s%s%s',
$domain,
$attr->value[0] == '/' ? '' : $currentPath,
htmlspecialchars($attr->value)
);
}
$attrs = $xpath->query('//@src[not(contains(., "://"))]');
foreach ($attrs as $attr) {
$attr->value = sprintf('%s%s%s',
$domain,
$attr->value[0] == '/' ? '' : $currentPath,
htmlspecialchars($attr->value)
);
}
echo $doc->saveHTML();
本质上,您正在寻找"而非"-模式。这将是一个消极的断言:
(?!http://)
例如,将其添加到/href="(?!http://)[^"]+"/
中。
或者您可以使用preg_replace_callback
并在那里进行排序。
既然你说了"解析",那就有点离题了;另一种选择是phpquery或用于HTML遍历的querypath。然后你可以循环所有的链接:
foreach (htmlqp($html)->find("a[href]") as $tag) {
if (!strstr($tag->attr("href"), "http://")) {
$tag->attr("href", "$add....");
显然,对于输出转换来说,这太过分了。但对于任意HTML来说,这可能是一个更有弹性的选项。