【问题标题】:Replace the href value of qualifying <a>'s using the tag's visible text使用标签的可见文本替换限定 <a> 的 href 值
【发布时间】:2020-11-22 04:20:48
【问题描述】:

我有一个包含很多 URL 的大字符串,我需要替换匹配的 URL:

<a href="../plugins/re_records/somefile.php?page=something&id=X">important_name</a>

(其中X 是任意整数,important_name 是任意字符串)与:

<a href="/map/important_name">important_name</a>

我使用preg_match_all() 匹配所有网址:

preg_match_all('/\/plugins\/re\_records\/somefile\.php\?page\=something\&id\=*(\d+)/', $bigString, $matches, PREG_OFFSET_CAPTURE);

问题是我不明白如何从超链接的可见文本中获取important_name,以便在 URL 匹配后成为新 URL 的一部分。

使用preg_match_all() 是个好主意吗?

【问题讨论】:

    标签: php replace html-parsing anchor href


    【解决方案1】:

    不要使用正则表达式。使用DOMDocument。它们专门用于解析 HTML/XML 文档。

    获取所有锚标记元素,检查href 属性中的值并使用setAttribute() 方法相应地更改属性。

    片段:

    <?php
    
    libxml_use_internal_errors(true); // to disable warnings if HTML is not well formed 
    $o = new DOMDocument();
    $o->loadHTML('<a href="../plugins/re_records/somefile.php?page=something&id=45">important_name</a>');
    
    foreach($o->getElementsByTagName('a') as $anchor_tag){
        $href = $anchor_tag->getAttribute('href');
        if(strpos($href,'/plugins/re_records/somefile.php?page=something&id=') !== false){
            $anchor_tag->setAttribute('href','/map/'.$anchor_tag->nodeValue);
        }
    }
    
    echo $o->saveHTML();
    

    演示: https://3v4l.org/5GPXA

    【讨论】:

    • 感谢您的回答!这解决了我的问题,我认为这是最干净和最漂亮的方式,但不幸的是(我知道这很愚蠢),这添加了 和 标签,有没有办法(无需更多代码)来避免这种情况?也许是一些 DOMDocument 方法?
    • 嗯,你可以使用 str_replace 来修剪掉那些。
    • 是的,我看到这个问题已经很久了。我可以使用很多东西来删除它们。谢谢!
    【解决方案2】:

    如果我对您的理解正确,您正在尝试获得匹配的important_name

    然后只需在其周围加上括号,即可在$matches 中获取。

    <?php
    $s = '<a href="../plugins/re_records/somefile.php?page=something&id=123">important_name</a>';
    
    preg_match_all('/\<a href\=\"\.\.\/plugins\/re\_records\/somefile\.php\?page\=something\&id\=*(\d+)\"\>(.*?)\<\/a\>/', $s, $matches, PREG_OFFSET_CAPTURE);
    
    var_dump($matches[2][0][0])
    ?>
    
    

    【讨论】:

      【解决方案3】:
      • 一定要养成使用合法 DOM 解析器解析 HTML 的习惯。使用正则表达式最终会让你头疼。当 DOM 解析器失败时,然后考虑使用正则表达式。

      • 我更喜欢使用 XPath 过滤已解析的文档,因为表达式可以非常强大和灵活。

      • 要在将字符串加载到 DOMDocument 时消除任何警告,请调用 libxml_use_internal_errors(true);。这将使所有警告静音。

      • 使用LIBXML_HTML_NODEFDTD | LIBXML_HTML_NOIMPLIED flags 省略您不需要/不需要的&lt;DOCTYPE&gt;&lt;HTML&gt;&lt;BODY&gt; 标签。

      • starts-with() 会很好,因为您不会尝试从查询字符串的末尾提取 id 号。

      • 不要被输出中编码的&amp; 推迟——it's a good thing / part of a more modern standard

      代码:(Demo)

      $html = <<<HTML
      <div>
          <p> some text <a href="../plugins/re_records/somefile.php?page=something&id=345">find_me_1</a></p>
          <br>
          <a href="../plugins/re_records/somefile.php?page=something&id=99">find_me_2</a>
          <div>
              <div>
                  <a href="example.com?page=something&id=55">don't even think about it!</a>
                  <a href="../plugins/re_records/somefile.php?page=something&id=90210">find_me_3</a>
              </div>
          </div>
      </div>
      HTML;
      
      $hrefStartsWith = '../plugins/re_records/somefile.php?page=something&id=';
      
      $dom = new DOMDocument();
      libxml_use_internal_errors(true);
      $dom->loadHTML($html, LIBXML_HTML_NODEFDTD | LIBXML_HTML_NOIMPLIED);
      $xpath = new DOMXPath($dom);
      foreach ($xpath->query("//a[starts-with(@href, '$hrefStartsWith')]") as $a) {
          $a->setAttribute('href', '/map/' . $a->nodeValue);
      }
      echo $dom->saveHTML();
      

      输出:

      <div>
          <p> some text <a href="/map/find_me_1">find_me_1</a></p>
          <br>
          <a href="/map/find_me_2">find_me_2</a>
          <div>
              <div>
                  <a href="example.com?page=something&amp;id=55">don't even think about it!</a>
                  <a href="/map/find_me_3">find_me_3</a>
              </div>
          </div>
      </div>
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-09-05
        • 1970-01-01
        • 2023-01-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-03-04
        相关资源
        最近更新 更多