将所有相对 URL 替换为绝对 URL

2024-02-01

我看过一些答案(比如this one https://stackoverflow.com/questions/31347340/convert-all-relative-urls-to-absolute-urls-while-maintaining-contents),但我有一些更复杂的场景,我不确定如何解释。

我基本上有完整的 HTML 文档。我需要更换每一个相对 URL 与绝对 URL。

潜在 HTML 中的元素如下所示,也可能是其他情况:

<img src="/relative/url/img.jpg" />
<form action="/">
<form action="/contact-us/">
<a href='/relative/url/'>Note the Single Quote</a>
<img src="//example.com/protocol-relative-img.jpg" />

期望的输出是:

// "//example.com/" is ideal, but "http(s)://example.com/" are acceptable

<img src="//example.com/relative/url/img.jpg" />
<form action="//example.com/">
<form action="//example.com/contact-us/">
<a href='//example.com/relative/url/'>Note the Single Quote</a>
<img src="//example.com/protocol-relative-img.jpg" /> <!-- Unmodified -->

我不想替换协议相对 URL,因为它们已经用作绝对 URL。我已经想出了一些有效的代码,但我想知道我是否可以清理一下它,因为它是极其重复的。

但我必须考虑单引号和双引号属性值src, href, and action(我是否缺少任何可以具有相对 URL 的属性?),同时避免使用协议相对 URL。

这是我到目前为止所拥有的:

// Make URL replacement protocol relative to not break insecure/secure links
$url = str_replace( array( 'http://', 'https://' ), '//', $url );

// Temporarily Modify Protocol-Relative URLS
$str = str_replace( 'src="//', 'src="::TEMP_REPLACE::', $str );
$str = str_replace( "src='//", "src='::TEMP_REPLACE::", $str );
$str = str_replace( 'href="//', 'href="::TEMP_REPLACE::', $str );
$str = str_replace( "href='//", "href='::TEMP_REPLACE::", $str );
$str = str_replace( 'action="//', 'action="::TEMP_REPLACE::', $str );
$str = str_replace( "action='//", "action='::TEMP_REPLACE::", $str );

// Replace all other Relative URLS
$str = str_replace( 'src="/', 'src="'. $url .'/', $str );
$str = str_replace( "src='/", "src='". $url ."/", $str );
$str = str_replace( 'href="/', 'href="'. $url .'/', $str );
$str = str_replace( "href='/", "href='". $url ."/", $str );
$str = str_replace( 'action="/', 'action="'. $url .'/', $str );
$str = str_replace( "action='/", "action='". $url ."/", $str );

// Change Protocol Relative URLs back
$str = str_replace( 'src="::TEMP_REPLACE::', 'src="//', $str );
$str = str_replace( "src='::TEMP_REPLACE::", "src='//", $str );
$str = str_replace( 'href="::TEMP_REPLACE::', 'href="//', $str );
$str = str_replace( "href='::TEMP_REPLACE::", "href='//", $str );
$str = str_replace( 'action="::TEMP_REPLACE::', 'action="//', $str );
$str = str_replace( "action='::TEMP_REPLACE::", "action='//", $str );

我的意思是,它有效,但它是uuugly,我想可能有更好的方法来做到这一点。


新答案

如果您的真实 html 文档是有效的(并且具有父/包含标签),那么最合适和可靠的技术将是使用适当的 DOM 解析器。

以下是如何使用 DOMDocument 和 Xpath 优雅地定位和替换指定的标签属性:

代码 1 - 嵌套 Xpath 查询:(Demo https://3v4l.org/1taUc)

$domain = '//example.com';
$tagsAndAttributes = [
    'img' => 'src',
    'form' => 'action',
    'a' => 'href'
];

$dom = new DOMDocument; 
$dom->loadHTML($html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
$xpath = new DOMXPath($dom);
foreach ($tagsAndAttributes as $tag => $attr) {
    foreach ($xpath->query("//{$tag}[not(starts-with(@{$attr}, '//'))]") as $node) {
        $node->setAttribute($attr, $domain . $node->getAttribute($attr));
    }
}
echo $dom->saveHTML();

Code2 - 带条件块的单个 Xpath 查询:(Demo https://3v4l.org/Ut8Dr)

$domain = '//example.com';
$targets = [
    "//img[not(starts-with(@src, '//'))]",
    "//form[not(starts-with(@action, '//'))]",
    "//a[not(starts-with(@href, '//'))]"
];

$dom = new DOMDocument; 
$dom->loadHTML($html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
$xpath = new DOMXPath($dom);
foreach ($xpath->query(implode('|', $targets)) as $node) {
    if ($src = $node->getAttribute('src')) {
        $node->setAttribute('src', $domain . $src);
    } elseif ($action = $node->getAttribute('action')) {
        $node->setAttribute('action', $domain . $action);
    } else {
        $node->setAttribute('href', $domain . $node->getAttribute('href'));
    }
}
echo $dom->saveHTML();

旧答案:(...正则表达式不是“DOM 感知”的,并且容易受到意外破坏)

如果我正确理解你,你心里有一个基本值,你只想将它应用到相对路径。

图案演示 https://regex101.com/r/AwnWuS/1

Code: (Demo https://3v4l.org/6vtMu)

$html=<<<HTML
<img src="/relative/url/img.jpg" />
<form action="/">
<a href='/relative/url/'>Note the Single Quote</a>
<img src="//site.com/protocol-relative-img.jpg" />
HTML;

$base='https://example.com';

echo preg_replace('~(?:src|action|href)=[\'"]\K/(?!/)[^\'"]*~',"$base$0",$html);

Output:

<img src="https://example.com/relative/url/img.jpg" />
<form action="https://example.com/">
<a href='https://example.com/relative/url/'>Note the Single Quote</a>
<img src="//site.com/protocol-relative-img.jpg" />

模式细分:

~                      #Pattern delimiter
(?:src|action|href)    #Match: src or action or href
=                      #Match equal sign
[\'"]                  #Match single or double quote
\K                     #Restart fullstring match (discard previously matched characters
/                      #Match slash
(?!/)                  #Negative lookahead (zero-length assertion): must not be a slash immediately after first matched slash
[^\'"]*                #Match zero or more non-single/double quote characters
~                      #Pattern delimiter
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

将所有相对 URL 替换为绝对 URL 的相关文章

  • 标准化 UTF-8 到底是什么?

    The 重症监护室项目 http userguide icu project org transforms normalization 现在也有一个PHP库 http us php net manual en class normalize
  • 内部 while 循环不工作

    这是我项目网页上的代码片段 这里我想显示用户选择的类别 然后想显示属于该类别的主题 在那里 用户可以拥有多个类别 这没有问题 我可以在第一个 while 循环中打印所有这些类别 问题是当我尝试打印主题时 结果只显示一行 但每个类别中有更多主
  • 简单的 PHP 表单:电子邮件附件(代码 Golf)

    想象一下 一个用户想要在其网站上放置一个表单 该表单将允许网站访问者上传一个文件和一条简单的消息 该消息将立即通过电子邮件发送 即 该文件未存储在服务器上 或者如果该文件存储在服务器上 仅暂时 作为文件附件 并在邮件正文中添加注释 查看更多
  • 替换多余的空格

    我需要从应用程序中的玩家用户名中删除多余的空格 字母之间不止一次空格 并将其替换为单个空格 我不介意用户有一个空格 但我需要删除彼此相邻的多个空格 目前我是这样实现的 replace array array fill array array
  • 基于mysql表中唯一电子邮件地址的唯一代码?

    我有一个 mysql 表 它将存储用户电子邮件地址 每个地址都是唯一的 并且是主字段 和时间戳 我添加了另一列名为 unique code varchar 64 utf8 unicode ci 我非常感谢您提供的帮助 a 生成5位字母数字代
  • octobercms 任务调度不起作用

    我正在使用基于 Laravel 的 OctoberCMS 我没有 SSH 访问我的服务器的权限 每天我需要删除一些注册后 24 小时内未激活帐户的用户 所以我正在考虑使用任务调度 如 cronjobs 根据 10 月 CMSdocs htt
  • laravel 中的 jwt 中的“无法从请求中解析令牌”

    我面临着 无法从请求中解析令牌 Laravel 中的 JWT 错误 我在 localhost Windows 7 中的 Xampp 中尝试了相同的代码 它正在工作 但在服务器上它不起作用 我已经通过了 授权 标头中的令牌也发生了变化 hta
  • VB 脚本 Documents.Open 抛出 424 错误

    所以我有一个vbs脚本 Function test2open sSourceFile sPDFFile Dim wApp As Word Application Dim wDoc As Word Document logStream wri
  • PHP表单提交后如何显示成功消息?

    这是代码 我想要这样 表单提交 gt page2 php gt 重定向 gt page1 php 这是消息 弹出窗口或其他内容 page1 php
  • 创建一个基于简单文本文件的搜索引擎

    我需要尽快创建一个基于简单文本文件的搜索引擎 使用 PHP 基本上它必须读取目录中的文件 删除停止词和无用词 为每个剩余的有用词及其在每个文档中出现的次数建立索引 我猜这个的伪代码是 for each file in directory r
  • 如何从MySQL数据库获取今天/昨天的数据?

    我想从数据库中检索今天的数据 但我不知道该怎么做 我实际上想要获取不是过去 24 小时的数据 我只想获取今天的数据 因此基于实际服务器时间 我还想获取昨天的数据 谁能帮我怎么做 示例代码 SELECT id FROM folk WHERE
  • Joomla getUser() 不显示更新的用户数据

    下面的代码允许我在用户的 Joomla 个人资料的个人资料页面中显示用户名 鉴于我已经覆盖了模板以获得我想要的外观和感觉 user JFactory getUser if user gt guest echo You are logged
  • “yum install php”需要 httpd-mmn = 20051115

    我从源代码安装了 httpd apache 2 4 6 现在我想安装 PHP 但yum install php吐出错误 Error Package php 5 3 3 40 el6 6 x86 64 updates Requires htt
  • 在 TCPDF 中设置背景颜色

    我已经手动设置了第一页的背景颜色 如下所示 pdf gt AddPage pdf gt SetFillColor 52 21 0 76 pdf gt Rect 0 0 pdf gt getPageWidth pdf gt getPageHe
  • PHP PCRE 函数中的 $0 是什么

    我读过一个文档preg filter功能如下 这是来自 php net http php net manual en function preg filter php site subject array 1 a 2 b 3 A B 4 p
  • 使用 jquery 和 php 测试表单输入是否为 1 或 2 位整数

    我有一个表单 其中有五个字段全部设置为 maxlength 2 基本上 我希望唯一可以输入的值是一位或两位整数 因为在将值存储在数据库中之前对这些字段执行计算 是否有任何 jquery 不允许用户输入不是整数的值 另外 用 jquery 和
  • vagrant box速度慢,如何改进?

    我们已经为我们的开发盒构建了一个 vagrant box 但我们面临着一些延迟问题 Issues Assetic 手表速度很慢 app dev php 中的整体应用程序访问速度很慢 在 vagrant box 的共享文件夹中使用 查找 命令
  • 是否可以在 php.ini 中指示 PHP 使用 postfix 配置?

    是否可以配置 PHP 使用 postfix 的配置集发送电子邮件 WordPress 通过 PHPMailer 依赖于 php ini 中的这些设置是否正确 SMTP localhost http php net smtp port smt
  • 未找到 mysqli 类

    我用过mysqli连接到我的应用程序中的数据库 几天前一直运行良好 突然出现以下错误 致命错误 找不到类 mysqli 我用来连接数据库的行是 link new mysqli localhost uname password scripts
  • 如何使用 Mockery 在第 N 次调用模拟方法时抛出异常

    我需要测试我编写的某些代码多次调用另一个类上的方法时的行为 其中一次调用将导致抛出异常 我在用Mockery http docs mockery io模拟可能引发异常的类 因此 就我而言 该方法将被调用三次 我需要它在第二次抛出异常 这是我

随机推荐

  • 删除重复的尾部斜杠

    我想检测php如果一个字符串像 string包括重复的尾部斜杠 例如 string http somepage com something some html to string http somepage com something so
  • 在 iOS 上使用 Cordova 1.6 设置外部起始页

    是否可以加载外部index html 包含cordova js 而不是本地index html 我在 appdelegate m 中找到了这段代码 self viewController wwwFolderName www self vie
  • 如何在 NodeJs 中安排 Google 会议并获取会议链接?

    在我的项目中 我必须在给定时间在两个用户之间安排一次谷歌会议 我在 NodeJS 中拥有其电子邮件 ID 有人能帮我解决这个问题吗 您将需要使用谷歌日历API https developers google com calendar api
  • 使用 BlueSnap 托管支付字段轻松开始;

    您好 我正在寻找一个可以复制并粘贴到我的网站中的简单脚本 以便我可以开始使用 BlueSnap 的 HPF 字段进行销售 该表单应包括取回代币并向购物者收费所需的最基本元素 我不是在寻找任何设计 只是在寻找功能 我有基础知识 但我需要看看如
  • xml解析-代码重构问题

    我有以下 xml
  • 使用 rxjs 处理刷新令牌

    自从我开始使用 angular2 以来 我已经设置了我的服务来返回 T 的 Observable 在服务中 我将进行 map 调用 并且使用这些服务的组件将仅使用 subscribe 来等待响应 对于这些简单的场景 我真的不需要深入研究 r
  • 从 JavaScript 加载图像

    在我的 Grails 应用程序中 我有一个目录web app images carousel slides包含以下文件 foo png foo thumbnail png bar png bar thumbnail png 我的应用程序正在
  • 如何以惯用的方式计算有多少元素满足条件?

    有了这些数据 gt data 1 1290603356 1290603360 1290603350 1290603344 1290603340 1290603373 7 1290603354 1290603359 1290603345 12
  • QGLWidget 在 Mac OS X Lion 下无法正常工作

    正如你所看到的 我不知道为什么它根本不起作用 When the program run it will look like this 我正在使用 macports 的 qt4 mac v4 8 2 看来该包是预编译的 这是来源 主要 cpp
  • 控制器中的 GGTS 重复方法名称/签名错误

    我正在使用基于 eclipse 4 3 1 64 位版本的最新 GGTS v3 4 在 Grails 2 3 2 上开发应用程序 我的类路径中的每个控制器都有一个错误 每个控制器类都有两个相同的错误 Groovy 类 package Som
  • django 模板中的逗号分隔列表

    If fruits是列表 apples oranges pears 有没有一种使用 django 模板标签快速生成 苹果 橙子和梨 的方法 I know it s not difficult to do this using a loop
  • 如何处理函数数组中的重复函数调用?

    我正在尝试按顺序执行以下函数 同步 异步 数组 避免callbackHell 实现函数runCallbacksInSequence 我需要实现自己的函数来了解回调的工作原理并避免使用 Async js 这是我到目前为止所拥有的 功能runC
  • 在 pandas 数据框替换功能中使用正则表达式匹配组

    我刚刚学习 python pandas 喜欢它的强大和简洁 在数据清理期间 我想使用正则表达式对数据框中的列进行替换 但我想重新插入匹配的部分 组 简单示例 姓氏 名字 gt 名字 姓氏 我尝试了类似以下的内容 实际情况更复杂 所以请原谅简
  • Hyperledger Fabric 了解 MSP

    我想清楚MSP的用途 所以我的问题是 当用户出于任何原因想要使用某个通道时 本地 MSP 会为其提供一个带有私钥的身份 在文档中说 MSP 有一个密钥库 并且在通道确认用户使用该通道 MSP 后 CA何时参与 None
  • 查询字符串是否有类似 hashchange 的事件?

    我一直在使用哈希值在页面之间传递数据 例如设置scrollTop 等 并且还使用了hashChange触发给定页面上的更改的事件 然而 哈希值具有我不一定感兴趣的默认行为 例如使页面跳转到给定的 有时是无关紧要的 位置 我觉得获取 设置查询
  • 游戏路径寻找

    所有类型的游戏中都使用哪些路径查找算法 无论如何 在角色移动的所有类型中 迪杰斯特拉 Dijkstra 曾经被使用过吗 我并不是真的想编写任何代码 只是做一些研究 不过如果你粘贴伪代码或其他东西 那就没问题了 我可以理解 Java 和 C
  • Spyder互动剧情:等待剧情关闭继续

    我使用 Spyder 在 Windows 上工作 使用 matplotlib 进行绘图 我的问题是我想要进行交互式绘图 或者有时绘制很多东西 并且我希望spyder等待我关闭图形以继续代码 与传统终端相同的方式 我试过 plt ion mp
  • Linux 中的堆栈内存管理

    我有几个与 Linux 堆栈大小限制相关的问题 我对 x86 64 系统最感兴趣 但如果存在平台差异 我也想了解它们 我的问题是 1 Linux如何动态增加堆栈的大小 我编写了一个带有递归函数 以使用堆栈空间 的测试程序 我可以在其中指定迭
  • 在 Django 中,如何覆盖“保存并继续”功能?

    我需要向 ModelAdmin 添加一些保存前和保存后逻辑 但仅当用户通过 保存并继续编辑 按钮而不是 保存 按钮提交表单时 我怎样才能做到这一点 就像重写普通的保存方法一样 您需要重写save model ModelAdmin 中的函数
  • 将所有相对 URL 替换为绝对 URL

    我看过一些答案 比如this one https stackoverflow com questions 31347340 convert all relative urls to absolute urls while maintaini