【问题标题】:DOMDocument removing closing tag within script tagsDOMDocument 删除脚本标签中的结束标签
【发布时间】:2016-01-30 08:03:47
【问题描述】:

我有以下test.php 文件,当我运行它时,结束</h1> 标记被删除。

<?php

$doc = new DOMDocument();

$doc->loadHTML('<html>
    <head>
        <script>
            console.log("<h1>hello</h1>");
        </script>
    </head>
    <body>

    </body>
</html>');

echo $doc->saveHTML();

这是我执行文件时的结果:

PHP Warning:  DOMDocument::loadHTML(): Unexpected end tag : h1 in Entity, line: 4 in /home/ryan/NetBeansProjects/blog/test.php on line 14

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html>
    <head>
        <script>
            console.log("<h1>hello");
        </script>
    </head>
    <body>
    </body>
</html>

那么,为什么要删除标签?它是一个字符串,所以它不应该忽略它吗?

【问题讨论】:

  • 我认为标签已被删除,因为它位于脚本元素中,因此可能需要转义斜杠。尝试将

    hello

    放在正文中,看看会发生什么。
  • 它在体内做同样的事情。但是,我确实读过loadXML() 支持这一点。我试过了,它没有删除标签,但是当我加载外部 html 文件时它无效时我得到错误。
  • 如果你颠倒你的引号,或者像这样转义它console.log(\"&lt;h1&gt;hello&lt;/h1&gt;\");
  • 不,这些方法都不起作用。

标签: php dom domdocument


【解决方案1】:

想到的唯一解决方案是预先匹配脚本标签,然后将它们替换为像&lt;script id="myuniqueid"&gt;&lt;/script&gt; 这样的临时持有者,并在 dom 管理结束时再次替换为实际脚本,如下所示:

//  The dom doc
$doc = new DOMDocument();

//  The html
$html = '<html>
    <head>
        <script>
            console.log("<h1>hello</h1>");
        </script>
    </head>
    <body>

    </body>
</html>';

//  Patter for scripts
$pattern = "/<script([^']*?)<\/script>/";
//  Get all scripts
preg_match_all($pattern, $html, $matches);

//  Only unique scripts
$matches = array_unique( $matches[0] );

//  Construct the arrays for replacement
foreach ( $matches as $match ) {
  //  The simple script
  $id = uniqid('script_');
  $uniqueScript = "<script id=\"$id\"></script>";
  $simple[] = $uniqueScript;
  //  The complete script
  $complete[] = $match;
}

//  Replace the scripts with the simple scripts
$html = str_replace($complete, $simple, $html);
//  load the html into the dom
$doc->loadHTML( $html);

//  Do the dom management here
//  TODO: Whatever you do with the dom

//  When finished
//  Get the html back
$html = $doc->saveHTML();
//  Replace the scripts back
$html = str_replace($simple, $complete, $html);
//Print the result
echo $html;

此解决方案打印干净,没有 dom 错误。

【讨论】:

    【解决方案2】:

    另一种选择是将&lt;/TAG&gt; 替换为&lt;\/TAG&gt;

    <?php
    $html = <<<'EOD'
    <!DOCTYPE html>
    <html>
    <head>
        <script>
        console.log("<h1>hello</h1>");
        var foo = '<a href="#"></a>';
        var bar = "<a href=\"#\"></a>";
        </script>
    </head>
    <body>
    </body>
    </html>
    EOD;
    
    preg_match_all('/<script\b[^>]*>.*?<\/script>/s', $html, $matches);
    $matches = array_unique( $matches[0] );
    if( !empty($matches) ) {
        foreach ( $matches as $matches__value ) {
            $before = $matches__value;
            $after = $matches__value;
            preg_match_all('/<\/[a-zA-Z][a-zA-Z0-9]*>/', $matches__value, $matches_inner);
            $matches_inner = array_unique( $matches_inner[0] );
            if( !empty($matches_inner) ) {
                foreach($matches_inner as $matches_inner__value) {
                    if($matches_inner__value === '</script>') { continue; }
                    $after = str_replace($matches_inner__value, str_replace('/','\/',$matches_inner__value), $after);
                }
                $simple[] = $after;
                $complete[] = $before;
            }
        }
        $html = str_replace($complete, $simple, $html);
    }
    
    $DOMDocument = new \DOMDocument();
    $DOMDocument->loadHTML($html);
    $html = $DOMDocument->saveHTML();
    echo $html;
    

    【讨论】:

      【解决方案3】:

      LIBXML_SCHEMA_CREATE 传递给加载HTML 选项。这将解决问题。

      <?php
      
      $doc = new DOMDocument();
      
      libxml_use_internal_errors(true);
      
      $doc->loadHTML(
        '<html>
          <head>
              <script>
                  console.log("<h1>hello</h1>");
              </script>
          </head>
          <body>
      
          </body>
      </html>',
        LIBXML_HTML_NODEFDTD | LIBXML_SCHEMA_CREATE
      );
      
      echo $doc->saveHTML();
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-03-13
        • 2014-09-03
        • 1970-01-01
        • 2011-01-22
        • 1970-01-01
        • 2017-02-09
        • 2023-03-12
        • 1970-01-01
        相关资源
        最近更新 更多