Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php DOMDocument->;saveHTML()与带有商业at符号(@)的urlencode_Php_Domdocument_Encode_Urlencode_Rfc - Fatal编程技术网

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&amp;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&amp;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