從 Gregarius 專案提取的實用函數,自動將 HTML 內容中的相對路徑(href="/path"、src="/path")轉換為基於源站點的絕對路徑,適用於 RSS 聚合、內容抓取、郵件模板渲染等場景。
<?php
/**
* 將 HTML 內容中的相對路徑轉為絕對路徑
* @param string $content HTML 內容
* @param string $feed_url 源站點 URL(如 https://example.com/blog/feed.xml)
* @return string 處理後的 HTML
*/
function relative_to_absolute($content, $feed_url) {
// 提取協議
if (!preg_match('/^(https?|ftp):\/\//i', $feed_url, $protocol_match)) {
return $content; // 無協議直接返回
}
$protocol = $protocol_match[0]; // https:// 或 https://
// 提取域名(含端口)
$server_url = preg_replace('/^(https?|ftp):\/\//i', '', $feed_url);
$server_url = preg_replace('/\/.*$/', '', $server_url); // 移除路徑部分
if (empty($server_url)) return $content;
$base = $protocol . $server_url;
// 替換以 / 開頭的相對路徑
$content = preg_replace('/href\s*=\s*["\']\//i', 'href="' . $base . '/', $content);
$content = preg_replace('/src\s*=\s*["\']\//i', 'src="' . $base . '/', $content);
return $content;
}
?>
<?php
$html = '<a href="/about">關於</a> <img src="/logo.png">';
$source_url = 'https://blog.example.com/feed/rss.xml';
echo relative_to_absolute($html, $source_url);
// 輸出: <a href="https://blog.example.com/about">關於</a> <img src="https://blog.example.com/logo.png">
?>
| 特點 | 說明 |
|---|---|
| 自動提取基礎 URL | 從完整 URL 解析協議+域名+端口 |
| 處理雙引號/單引號 | 正則兼容 href="/path" 和 href='/path' |
| 僅處理根相對路徑 | 以 / 開頭的路徑;不處理 ../path、path、完整 URL |
| 不依賴 DOM 解析器 | 正則替換,性能高,但不處理屬性值中包含 / 的邊界情況 |
function relative_to_absolute_advanced($html, $base_url) {
$base = rtrim($base_url, '/') . '/';
$dom = new DOMDocument();
@$dom->loadHTML('' . $html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
foreach (['a' => 'href', 'img' => 'src', 'link' => 'href', 'script' => 'src'] as $tag => $attr) {
foreach ($dom->getElementsByTagName($tag) as $node) {
$val = $node->getAttribute($attr);
if ($val && !preg_match('/^(https?|ftp|data):/i', $val)) {
// 相對路徑轉絕對
if ($val[0] === '/') {
$parsed = parse_url($base_url);
$new_val = $parsed['scheme'] . '://' . $parsed['host'] . (isset($parsed['port']) ? ':' . $parsed['port'] : '') . $val;
} else {
$new_val = $base . ltrim($val, '/');
}
$node->setAttribute($attr, $new_val);
}
}
}
return $dom->saveHTML();
}
正則版適合簡單高性能場景,DOM 版適合複雜 HTML 結構與高可靠性需求。