2012-11-19 18 views
8

Istnieje wiele postów dotyczących konwersji w stosunku do ścieżek bezwzględnych w PHP. Poszukuję konkretnej implementacji poza tymi postami (mam nadzieję). Czy ktokolwiek może mi pomóc w tej konkretnej implementacji?PHP: Znajdź obrazy i łącza ze ścieżką względną na wyjściu i przekonwertuj je na ścieżkę bezwzględną

Mam zmiennej PHP zawierające różne HTML, w tym href s i img s zawierające względne adresy URL. Głównie (na przykład) /en/discover lub /img/icons/facebook.png

Chcę przetworzyć tę zmienną PHP w taki sposób, że wartości moich href S i img s będą zamieniane na http://mydomain.com/en/discover i http://mydomain.com/img/icons/facebook.png

wierzę pytanie poniżej okładkach rozwiązanie dla href s. Jak możemy to rozszerzyć, aby uwzględnić także s img s?

Czy regex być w porządku? A skoro mamy do czynienia z dużą ilością wydruków, czy powinniśmy używać DOMDocument?

+0

I nie będzie za pomocą '' ' w swoim' wystarczy? Jeśli nie, to wystarczy użyć wyrażenia regularnego - możesz użyć funkcji 'preg_replace_all'. – shadyyx

+0

Dzięki za odpowiedź. Dobra sugestia, ale nie sądzę, ponieważ wynik będzie wyświetlany w dokumencie XML. Problem polega na tym, że jestem niekompetentny wobec wyrażeń regularnych ... – maartenmachiels

Odpowiedz

8

Po dalszych badaniach natknąłem się na ten artykuł Gerda Riesselmanna na temat rozwiązania problemu braku rozwiązania base href dla kanałów RSS. Snippet faktycznie rozwiązuje moje pytanie!

http://www.gerd-riesselmann.net/archives/2005/11/rss-doesnt-know-a-base-url

<?php 
function relToAbs($text, $base) 
{ 
    if (empty($base)) 
    return $text; 
    // base url needs trailing/
    if (substr($base, -1, 1) != "/") 
    $base .= "/"; 
    // Replace links 
    $pattern = "/<a([^>]*) " . 
      "href=\"[^http|ftp|https|mailto]([^\"]*)\"/"; 
    $replace = "<a\${1} href=\"" . $base . "\${2}\""; 
    $text = preg_replace($pattern, $replace, $text); 
    // Replace images 
    $pattern = "/<img([^>]*) " . 
      "src=\"[^http|ftp|https]([^\"]*)\"/"; 
    $replace = "<img\${1} src=\"" . $base . "\${2}\""; 
    $text = preg_replace($pattern, $replace, $text); 
    // Done 
    return $text; 
} 
?> 

Dziękuję Gerd! I dziękuję Shadyyx, aby wskazał mi kierunek base href!

4

Doskonałe rozwiązanie. Jednak we wzorze występuje mała literówka. Jak napisano powyżej, przycina pierwszy znak href lub src. Oto wzory, które działają zgodnie z przeznaczeniem:

// Replace links 
$pattern = "/<a([^>]*) " . 
     "href=\"([^http|ftp|https|mailto][^\"]*)\"/"; 

i

// Replace images 
$pattern = "/<img([^>]*) " . 
     "src=\"([^http|ftp|https][^\"]*)\"/"; 

Otwarcie nawias drugich odniesień zamiennych są przenoszone. Spowoduje to pojawienie się pierwszego znaku href lub src, który nie pasuje do http | ftp | https do referencji zamienników.

+0

Dzięki, pracuj lepiej! Tylko linki zaczynające się od # nie powinny być zmienione. Używanie [^ http | ftp | https | mailto | #] działa dla '# head1', ale powinno zastąpić 'mypage.html # head1' pełnym adresem URL. – Barryvdh

2

Znalazłem, że gdy href src i adres bazowy zaczęły być coraz bardziej złożone, rozwiązanie zaakceptowanej odpowiedzi nie działało dla mnie.

np

podstawy URL:

http://www.journalofadvertisingresearch.com/ArticleCenter/default.asp?ID=86411&Type=Article

sekcję SRC

/ArticleCenter/LeftMenu.asp?Type=Article&FN=&ID=86411&Vol=&No=&Year=&Any=

nieprawidłowo wracający

/ArticleCenter/LeftMenu.asp?Type=Article&FN=&ID=86411&Vol=&No=&Year=&Any=

, że okazało się, że poniżej funkcji, która prawidłowo zwraca adres. Mam to z komentarza tutaj: http://php.net/manual/en/function.realpath.php od Isaaca Z. Schlueter.

Ten prawidłowo zwrócony:

http://www.journalofadvertisingresearch.com/ArticleCenter/LeftMenu.asp?Type=Article&FN=&ID=86411&Vol=&No=&Year=&Any=

function resolve_href ($base, $href) { 

// href="" ==> current url. 
if (!$href) { 
    return $base; 
} 

// href="http://..." ==> href isn't relative 
$rel_parsed = parse_url($href); 
if (array_key_exists('scheme', $rel_parsed)) { 
    return $href; 
} 

// add an extra character so that, if it ends in a /, we don't lose the last piece. 
$base_parsed = parse_url("$base "); 
// if it's just server.com and no path, then put a/there. 
if (!array_key_exists('path', $base_parsed)) { 
    $base_parsed = parse_url("$base/ "); 
} 

// href="/ ==> throw away current path. 
if ($href{0} === "/") { 
    $path = $href; 
} else { 
    $path = dirname($base_parsed['path']) . "/$href"; 
} 

// bla/./bloo ==> bla/bloo 
$path = preg_replace('~/\./~', '/', $path); 

// resolve /../ 
// loop through all the parts, popping whenever there's a .., pushing otherwise. 
    $parts = array(); 
    foreach ( 
     explode('/', preg_replace('~/+~', '/', $path)) as $part 
    ) if ($part === "..") { 
     array_pop($parts); 
    } elseif ($part!="") { 
     $parts[] = $part; 
    } 

return ( 
    (array_key_exists('scheme', $base_parsed)) ? 
     $base_parsed['scheme'] . '://' . $base_parsed['host'] : "" 
) . "/" . implode("/", $parts); 
} 
+1

Dziękujemy za wkład! – maartenmachiels

Powiązane problemy