【问题标题】:Using PHP DOM want to show all string as a output使用 PHP DOM 想要将所有字符串显示为输出
【发布时间】:2016-08-06 05:29:14
【问题描述】:

这里是我在 php 中 $data 变量中的 html 字符串,以及那个字符串 有一些像<140/90 mmHg OR <130/80 mmHg这样的文字这行不是 显示我何时使用 PHP DOMDocument 运行此代码,因为当出现小于和大于时表示它有问题。

<?php
$data = 'THE CORRECT ANSWER IS C.
<p>Choice A Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industrys standard dummy text ever since the 1500s</p>
<p></p>
<p>Choice B Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industrys standard dummy text ever since the 1500s</p>
<p>Choice D Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industrys standard dummy text ever since the 1500s</p>
<p></p>
<p>Choice E simply dummy text of the printing and typesetting industry.</p>
<p></p>
<p><br>THIS IS MY MAIN TITLE IN CAPS<br>This my sub title.</p>
<p><br>TEST ABC: Lorem Ipsum is simply dummy text of the printing and typesetting industry.</p>
<p>1) It is a long established fact <140/90 mmHg OR <130/80 mmHg making it look like readable English will uncover many web sites still in their infancy. 
<br><br>2) There are many variations of passages of Lorem Ipsum available. </p>
<p><br>TEST XYZ: Lorem Ipsum has been the industrys standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.</p>
<p><br>TES T TEST: It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged.</p>
<p><br>TESTXXX: It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</p>';
echo boldFormatExplanation($data);
?>

另外,我在 PHP 下创建了将转换粗体标题的函数 并使用 PHP DOMDocument 加粗一些单词。

  1. 加粗标题:“这是我的大写标题”(标题并不总是相同)
  2. 加粗的单词:TEST ABC:, TEST XYZ:, TES T TEST:, TESTXXX:(这些词总是相同的)

以上 2 点运行良好,只是缺少行,就像我一样 上面在第一个块中描述。

<?php
function boldFormatExplanation($data){
    $dom = new DOMDocument('1.0', 'UTF-8');
    $dom->encoding = 'utf-8';
    $dom->substituteEntities = false;
    $dom->preserveWhiteSpace = true;
    $internalErrors = libxml_use_internal_errors(true);// Set error level
    @$dom->loadHTML($data, LIBXML_HTML_NODEFDTD);// Load html
    libxml_use_internal_errors($internalErrors);// Restore error level
    $xpath = new DOMXPath($dom);// Dom xpath
    $title_flag = true;
    foreach($xpath->query('//text()') as $node) {
        $txt = trim($node->nodeValue);
        $p = $node->parentNode;
        if (preg_match("/^\s*(TEST ABC:|TEST XYZ:|TES T TEST:|TESTXXX)(.*)$/s", $node->nodeValue, $matches)) {
            // Put Choice in bold:
            $p->insertBefore($dom->createElement('b', $matches[1]), $node);
            $node->nodeValue = " " . trim($matches[2]);
        } else 
        if (strtoupper($txt) === $txt && $txt !== '') {
            // Put header in bold
            if($title_flag == true){
                $p->insertBefore($dom->createElement('b', $txt), $node);
                $node->nodeValue = "";
                $title_flag = false;
            }
        }
    }
    $domData = $dom->saveHTML();
    $data = htmlspecialchars_decode($domData);
    return $data; 
} ?>

您可以在here 运行此代码,同时输出跳过此行&lt;140/90 mmHg OR &lt;130/80 mmHg

【问题讨论】:

    标签: php regex dom preg-replace preg-match


    【解决方案1】:

    这里你没有选择,你需要在使用DOMDocument::loadHTML 加载它之前处理字符串。但是你不能像野蛮人那样盲目替换(因为在这种情况下&lt; 之间的scriptstyle 标签也会被替换)。您需要使用 libxml 错误来仅定位有问题的左尖括号。你可以这样做(它并不快,因为你需要构建 DOM 树直到错误消失但它是正确的)

    define('LIBXML_ERR_NAME_REQUIRED', 68);
    
    $skeleton = '<html><head><meta charset="UTF-8"/></head><body id="root">%s</body></html>';
    $htmlDoc = sprintf($skeleton, $data);
    
    $dom = new DOMDocument;
    
    do {
        libxml_use_internal_errors(true);
        $hasError = false;
        $dom->loadHTML($htmlDoc);
        $errors = libxml_get_errors();
    
        foreach ($errors as $error) {
            if ($error->code == LIBXML_ERR_NAME_REQUIRED) {
                $hasError = true;
                $htmlDoc = preg_replace('~\A(?:.*\R){' . ($error->line - 1) . '}.{' . ($error->column - 2) . '}\K<~u', '&lt;', $htmlDoc);
            }
        }
        libxml_clear_errors();
    } while ($hasError);
    
    boldFormatExplanation($dom);
    
    foreach($dom->getElementById('root')->childNodes as $childNode) {
        echo $dom->saveHTML($childNode);
    }
    

    顺便说一句,在你使用DOMDocument::loadHTML之后设置DOMDocument编码属性是没有用的,因为编码是用文档内容设置的(这是我在$data周围放置一个html骨架的主要原因&lt;meta charset="UTF-8"/&gt;).

    关于你的加粗函数,你可以这样写:

    function boldFormatExplanation(&$dom) {
        $xpath = new DOMXPath($dom);
        $title_flag = true;
    
        foreach($xpath->query('//text()') as $node) {
            $txt = trim($node->nodeValue);
            if (empty($txt)) continue;
    
            $p = $node->parentNode;
            if (preg_match("/^(TEST ABC:|TEST XYZ:|TES T TEST:|TESTXXX)\s*(.*)/s", $txt, $matches)) {
                // Put Choice in bold:
                $p->insertBefore($dom->createElement('b', $matches[1]), $node);
                $node->nodeValue = " " . $matches[2];
            } elseif ($title_flag && strtoupper($txt) === $txt) {
                // Put header in bold
                $p->replaceChild($dom->createElement('b', $txt), $node);
                $title_flag = false;
            }
        }
    }
    

    【讨论】:

    • 是的,它运行良好,有时会中断并显示错误?而且我正在尝试根据我对这个功能的需要做出粗体的第 1 点和第 2 点。
    • @Rocky:你需要从这段代码开始,并且只有在应用你的粗体函数之后。显示什么错误?
    • 你能在我的函数中添加粗体的东西吗?
    • 现在 while 循环没有显示任何错误,但它出现在功能中?
    • 感谢您的快速回复,现在它运行良好。
    猜你喜欢
    • 2014-01-14
    • 2019-03-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-13
    • 1970-01-01
    • 2017-08-11
    • 1970-01-01
    相关资源
    最近更新 更多