【问题标题】:How to remove CDATA blocks inside a script element?如何删除脚本元素内的 CDATA 块?
【发布时间】:2017-05-03 12:38:43
【问题描述】:

使用 PHP,在 HTML 文件中,我想删除脚本元素中的 CDATA 块。

<script type="text/javascript">
    /* <![CDATA[ */
    var A=new Array();
    ..........................
    ..........................
/* ]]> */
</script>
some text2 ........................
some text3 ........................
some text4 ........................
<script type="text/javascript">
    /* <![CDATA[ */
    var B=new Array();
    ..........................
    ..........................
/* ]]> */
some text5 ........................

我还没有找到如何使用 XPath 和 PHP DomDocument 选择和删除此节点。

我试过这个正则表达式 $re = '/\/\*\s*&lt;!\[CDATA\[[\s\S]*\/\*\s*\]\]&gt;\s*\*\//i';

但这会删除所有文本,包括两个 CDATA 块之间的文本。

结果我得到一个空字符串而不是

some text2 ........................ 
some text3 ........................ 
some text4 ........................ 
some text5 ........................

有什么想法吗?

使用 ThW 解决方案更新:

有了这个页面,好像CDATA部分的文字解析不好

libxml_use_internal_errors(true);
$domDoc = new DOMDocument();
$domDoc->loadHTMLFile('https://www.maisons-qualite.com/le-reseau-mdq/recherche-constructeurs-agrees/construction-maison-neuve-centre-val-loire');
libxml_clear_errors();

$xpath = new DOMXpath($domDoc);
foreach($xpath->evaluate('//text()') as $section) {
  if ($section instanceof DOMCDATASection) {
    print_r($section->textContent);
    $section->parentNode->removeChild($section);
  }
}
$content = $domDoc->saveHTML();

我得到了这个文本内容

.....
.....
function updateConstructeurs(list) {
    for (var i in list) {
        if(list[i]['thumbnail']) {
            jQuery('#reseau-constructeurs').append('<div class="reseau-constructeur">' +
                '<div class="img" style="background-image:url(' + list[i]['thumbnail'] + ')">

function updateConstructeurs(list) {
    for (var i in list) {
        if(list[i]['thumbnail']) {
            jQuery('#reseau-constructeurs').append('<div class="reseau-constructeur">' +
                '<div class="img" style="background-image:url(' + list[i]['thumbnail'] + ')"></div>' +
                '<h3>' + list[i]['title'] + '</h3>' +
                '<a class="btn purple" href="' + list[i]['link'] + '">Accéder à la fiche</a>' +
            '</div>');
        }
    }
}

因此,我们得到的不是空字符串,而是:

                        '<h3>' + list[i]['title'] + '</h3>' +
                        '<a class="btn purple" href="'%20+%20list%5Bi%5D%5B'link'%5D%20+%20'">Acc&eacute;der &agrave; la fiche</a>' +
                    '</div>');
                }
            }
        }
    /* ]]&gt; */

【问题讨论】:

    标签: php regex xpath preg-replace cdata


    【解决方案1】:

    使[\s\S]* 非贪婪,即[\s\S]*?

    \/\*\s*<!\[CDATA\[[\s\S]*?\/\*\s*\]\]>\s*\*\/
    

    演示:https://regex101.com/r/AutLW9/1

    【讨论】:

    • 好像不行。显示 processing... 没有结果
    • 同样的错误,但在 PHP 中没问题。我用 PHP 发布你的解决方案。
    【解决方案2】:

    Dmitry Egorov 在 PHP 中的解决方案。

    $re = '/\/\*\s*<!\[CDATA\[[\s\S]*?\/\*\s*\]\]>\s*\*\//';
    $str = '<script type="text/javascript">
        /* <![CDATA[ */
        var A=new Array();
        ..........................
        ..........................
    /* ]]> */
    </script>
    some text2 ........................
    some text3 ........................
    some text4 ........................
    <script type="text/javascript">
        /* <![CDATA[ */
        var B=new Array();
        ..........................
        ..........................
    /* ]]> */
    </script>
    some text5 ........................';
    $subst = '';
    
    $result = preg_replace($re, $subst, $str);
    
    echo "The result of the substitution is ".$result;
    

    【讨论】:

      【解决方案3】:

      CData 节是一种字符节点,类似于文本节点。对于大多数目的,您以相同的方式处理它们 - 区别在于序列化。因此,如果它们是 CDATA 部分(而不是文本节点),则使用 Xpath 获取节点并删除它们:

      $document = new DOMDocument();
      $document->loadHtml($html);
      $xpath = new DOMXpath($document);
      
      foreach($xpath->evaluate('//text()') as $section) {
        if ($section instanceof DOMCDATASection) {
          $section->parentNode->removeChild($section);
        }
      }
      
      echo $document->saveHtml();
      

      但是,您可能需要重新考虑这一点。没有 CDATA 部分真的很重要吗?您可能想要删除 script 元素的内容。这甚至更短:

      $document = new DOMDocument();
      $document->loadHtml($html);
      $xpath = new DOMXpath($document);
      
      foreach($xpath->evaluate('//script/node()') as $node) {
        $node->parentNode->removeChild($section);
      }
      
      echo $document->saveHtml();
      

      //script/node() 匹配script 元素内的任何子节点。无论是 CDATA 部分、文本节点还是其他任何内容。

      【讨论】:

      • 不使用 RegExp 的 Goog 解决方案。但我有一个错误。我用它更新我的帖子。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-07-22
      • 1970-01-01
      相关资源
      最近更新 更多