preg_replace href或src仅在缺少协议时使用

时间:2012-02-02 00:48:30

标签: php regex preg-replace

我正在解析输入,即HTML。但是,我需要能够找到所有没有协议的href或src属性,例如http://,https://或ftp://等,当它们不替换它时包含协议和域的变量。

所以我想要

<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属性,但我似乎无法弄清楚如何只匹配和替换IF它缺少一个协议。我发现[^ 0-9]会以反向/不相反的方式工作,但我发现在使用http:// etc进行尝试时我无法使用它。

编辑:

只是提到它,因为我很明显它是这个问题的“范围”的一部分,我想避免因替换而导致网址编码,因为我使用像{}这样的东西其中一些,我不希望他们有像%7B%7D这样的东西。

2 个答案:

答案 0 :(得分:3)

为什么不使用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();

答案 1 :(得分:2)

实质上,您正在寻找“ not ” - 模式。那将是negative assertion

 (?!http://)

例如,在/href="(?!http://)[^"]+"/中添加。

或者您可以使用preg_replace_callback并将其排序。


既然你说“解析”它就是一个主题; HTML遍历的替代方法是。然后,您可以使用以下链接遍历所有链接:

 foreach (htmlqp($html)->find("a[href]") as $tag) {
      if (!strstr($tag->attr("href"), "http://")) {
             $tag->attr("href", "$add....");

输出转换显然有点过分。但对任意HTML来说可能是一个更具弹性的选择。