Php DOMDocument->;saveHTML()与带有商业at符号(@)的urlencode
使用,我正在替换Php DOMDocument->;saveHTML()与带有商业at符号(@)的urlencode,php,domdocument,encode,urlencode,rfc,Php,Domdocument,Encode,Urlencode,Rfc,使用,我正在替换$message中的链接,并添加一些内容,如[@MERGEID]。当我用保存更改时,链接会进行“排序”url编码[@MERGEID]变为%5B@MERGEID%5D 稍后在我的代码中,我需要将[@MERGEID]替换为一个ID。因此我搜索urlencode(“[@MERGEID]”)-但是,将商业at符号(@)更改为%40,而saveHTML()将其单独保留。所以没有匹配-'%5B@MERGEID%5D'!='%5B%40MERGEID%5D' 现在,我知道可以运行str_rep
$message
中的链接,并添加一些内容,如[@MERGEID]
。当我用保存更改时,链接会进行“排序”url编码<代码>[@MERGEID]变为%5B@MERGEID%5D
稍后在我的代码中,我需要将[@MERGEID]
替换为一个ID。因此我搜索urlencode(“[@MERGEID]”)
-但是,将商业at符号(@)更改为%40,而saveHTML()将其单独保留。所以没有匹配-'%5B@MERGEID%5D'!='%5B%40MERGEID%5D'
现在,我知道可以运行str_replace('%40','@',urlencode('[@MERGEID]'))
来获取在$message中查找合并变量所需的内容
我的问题是,DOMDocument使用的是什么RFC规范,为什么它与urlencode甚至rawurlencode不同?我能做些什么来保存stru替换吗
$newlink = 'http://www.example.com/click/'.urlencode('[@MERGEID]').'?url=' . $link;
演示代码:
$message = '<a href="http://www.google.com?ref=abc" data-tag="thebottomlink">Google</a>';
$dom_document = new \DOMDocument();
libxml_use_internal_errors(true); //Supress content errors
$dom_document->loadHTML(mb_convert_encoding($message, 'HTML-ENTITIES', 'UTF-8'));
$elements = $dom_document->getElementsByTagName('a');
foreach($elements as $element) {
$link = $element->getAttribute('href'); //http://www.google.com?ref=abc
$tag = $element->getAttribute('data-tag'); //thebottomlink
if ($link) {
$newlink = 'http://www.example.com/click/[@MERGEID]?url=' . $link;
if ($tag) {
$newlink .= '&tag=' . $tag;
}
$element->setAttribute('href', $newlink);
}
}
$message = $dom_document->saveHTML();
$urlencodedmerge = urlencode('[@MERGEID]');
die($message . ' and url encoded version: ' . $urlencodedmerge);
//<a data-tag="thebottomlink" href="http://www.example.com/click/%5B@MERGEID%5D?url=http://www.google.com?ref=abc&tag=thebottomlink">Google</a> and url encoded version: %5B%40MERGEID%5D
$message='';
$dom_document=new\DOMDocument();
libxml\u使用\u内部错误(true)//抑制内容错误
$dom_document->loadHTML(mb_convert_编码($message,'HTML-ENTITIES','UTF-8'));
$elements=$dom_document->getElementsByTagName('a');
foreach($elements作为$element){
$link=$element->getAttribute('href')//http://www.google.com?ref=abc
$tag=$element->getAttribute('data-tag');//底部链接
如果($link){
$newlink='1http://www.example.com/click/[@MERGEID]?url='.$link;
如果($tag){
$newlink.='&tag='.$tag;
}
$element->setAttribute('href',$newlink);
}
}
$message=$dom_document->saveHTML();
$urlencodedmerge=urlencode(“[@MERGEID]”);
die($message.'和url编码版本:'。$urlencodedmerge);
//和url编码版本:%5B%40MERGEID%5D
我相信这两种编码有不同的用途urlencode()
编码,而$element->setAttribute('href',$newlink)代码>对要用作URL的完整URL进行编码
例如:
urlencode('http://www.google.com'); // -> http%3A%2F%2Fwww.google.com
这便于对查询部分进行编码,但不能在
上使用
然而:
$element->setAttribute('href', $newlink); // -> http://www.google.com
将正确编码字符串,使其在href
中仍然可用。它无法对@
进行编码的原因是因为它无法判断@
是查询的一部分还是用户信息的一部分
或电子邮件
url(例如:邮件收件人:invisal@google.com
或invisal@127.0.0.1
)
解决方案
您可以使用@@MERGEID@
,而不是使用[@MERGEID]
。然后,您稍后将其替换为您的ID。此解决方案甚至不要求您使用urlencode
如果您坚持使用urlencode
,您可以使用%40而不是@。因此,您的代码将如下所示http://www.example.com/click/[%40MERGEID]?url='$链接代码>
您还可以执行类似于$newlink=”的操作http://www.example.com/click/' . urlencode(“[@MERGEID]”)是什么意思?url='$链接代码>
urlencode
函数和rawurlencode
大多基于RFC1738
。然而,自2005年以来,目前用于URI标准的RFC是RFC3986
<?php
function myUrlEncode($string) {
$entities = array('%21', '%2A', '%27', '%28', '%29', '%3B', '%3A', '%40', '%26', '%3D', '%2B', '%24', '%2C', '%2F', '%3F', '%25', '%23', '%5B', '%5D');
$replacements = array('!', '*', "'", "(", ")", ";", ":", "@", "&", "=", "+", "$", ",", "/", "?", "%", "#", "[", "]");
return str_replace($entities, $replacements, urldecode($string));
}
?>
另一方面,DOM扩展使用UTF-8编码,它基于。使用utf8_encode()和utf8_decode()处理ISO-8859-1编码中的文本,或使用Iconv处理其他编码中的文本
通用URI语法要求提供
URI中字符数据的表示实际上必须,
表示不带翻译的非保留集合中的字符,以及
应根据UTF-8将所有其他字符转换为字节,以及
然后对这些值进行百分比编码
下面是一个根据RFC3986
解码URL的函数
<?php
function myUrlEncode($string) {
$entities = array('%21', '%2A', '%27', '%28', '%29', '%3B', '%3A', '%40', '%26', '%3D', '%2B', '%24', '%2C', '%2F', '%3F', '%25', '%23', '%5B', '%5D');
$replacements = array('!', '*', "'", "(", ")", ";", ":", "@", "&", "=", "+", "$", ",", "/", "?", "%", "#", "[", "]");
return str_replace($entities, $replacements, urldecode($string));
}
?>
返回不带百分比的URL时,请使用urldecode($message)
die(urldecode($message) . ' and url encoded version: ' . $urlencodedmerge);
如果使用saveXML()
它不会像saveHTML()
那样干扰编码:
PHP
//your code...
$message = $dom_document->saveXML();
编辑:同时删除XML标记:
//this will add an xml tag, so just remove it
$message=preg_replace("/\<\?xml(.*?)\?\>/","",$message);
echo $message;
//这将添加一个xml标记,所以只需删除它即可
$message=preg\u replace(“/\/”、“”、$message);
回声$信息;
输出
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html><body><a href="http://www.example.com/click/[@MERGEID]?url=http://www.google.com?ref=abc&tag=thebottomlink" data-tag="thebottomlink">Google</a></body></html>
请注意,两者仍然正确地将&
转换为&代码>仅对原始[@mergeid]进行URL编码是否有意义?首先还保存它吗?然后您的搜索应该匹配,而不需要str_替换
$newlink = 'http://www.example.com/click/'.urlencode('[@MERGEID]').'?url=' . $link;
我知道这并没有回答问题的第一篇帖子,但据我所知,您不能在评论中发布代码。从技术角度来看,您的问题的根本原因
然而,在我看来,你的方法有一个概念上的缺陷,它造成了你现在试图修复的局面
通过DomDocument对象处理您的输入$message
,您已经进入了更高的抽象级别。将已“升级”为HTML流的内容作为唯一的纯字符串进行操作是错误的
不要试图复制DomDocument的行为,而是使用库本身来定位、提取和替换感兴趣的值:
$token = 'blah blah [@MERGEID]';
$message = '<a id="' . $token . '" href="' . $token . '"></a>';
$dom = new DOMDocument();
$dom->loadHTML($message);
echo $dom->saveHTML(); // now we have an abstract HTML document
// extract a raw value
$rawstring = $dom->getElementsByTagName('a')->item(0)->getAttribute('href');
// do the low-level fiddling
$newstring = str_replace($token, 'replaced', $rawstring);
// push the new value back into the abstract black box.
$dom->getElementsByTagName('a')->item(0)->setAttribute('href', $newstring);
// less code written, but works all the time
$rawstring = $dom->getElementsByTagName('a')->item(0)->getAttribute('id');
$newstring = str_replace($token, 'replaced', $rawstring);
$dom->getElementsByTagName('a')->item(0)->setAttribute('id', $newstring);
echo $dom->saveHTML();
$token='blah blah[@MERGEID]';
$message='';
$dom=新的DOMDocument();
$dom->loadHTML($message);
echo$dom->saveHTML();//现在我们有了一个抽象的HTML文档
//提取原始值
$rawstring=$dom->getElementsByTagName('a')->item(0)->getAttribute('href');
//做低级的小提琴演奏
$newstring=str_replace($token,'replaced',$rawstring);
//将新值推回抽象黑框。
$dom->getElementsByTagName('a')->item(0)->setAttribute('href',$newstring);
//编写的代码更少,但始终有效
$rawstring=$dom->getElementsByTagName('a')->item(0)->getAttribute('id');
$newstring=str_replace($token,'replaced',$rawstring);
$dom->getElemen