代码之家  ›  专栏  ›  技术社区  ›  Avatar

用html标记替换括起来的撇号,但不在<code>块内

  •  0
  • Avatar  · 技术社区  · 8 年前

    目标: 修改包含撇号的HTML字符串以内联包装代码(就像stackoverflow那样)。但同时 <code> 也可以包含应保持不变的撇号的块。

    例子:

    <p>This is my `inline code`, it can be replaced and tag-wrapped.</p>
    <p><code>This text contains `apostrophs`, but should `not` be changed.</code></p>
    

    此正则表达式用于将所有换行撇号转换为<代码>元素:

    // replace apostroph with incorporating <code> tag
    $content = preg_replace('/(.+?)\`(.+?)\`/', '$1<code class="inlinecode">$2</code>', $content);
    


    必修的:
    更改regex,这样它就可以 不 如果撇号不带 <代码& GT; 块。



    免责声明:我花了几个小时阅读html字符串,使用php的dom解析器,提取类型为 code ,更改其内容,将其写回,然后发现nodeValue正在删除所有HTML标记(尤其是换行符)。然后尝试了网上找到的几种解决方案,仍然不起作用…现在我又回到了regex,即使是在逆境中。

    仅供参考,我是如何尝试dom方式的:

    $code_blocks = $dom->getElementsByTagName('code');
    foreach($code_blocks as $codenode) {
    // nodeValue strips HTML tags, we need to hack
    $nodevalue_html = $codenode->ownerDocument->saveXML($codenode);
    // replace, i.e. custom-store each apostroph with '~~~APO~~~' so that they survive
    $nodevalue_html = preg_replace('/`/', '~~~APO~~~', $nodevalue_html);
    // $codenode->textValue = $nodevalue_html; // fail
    // $codenode->nodeValue = $nodevalue_html; // fail
    // ...
    }
    // html to string
    $html_new = $dom->saveHTML();
    $html_new = preg_replace('/~~~APO~~~/', '`', $html_new);
    

    我希望可以像stackoverflow那样使用markdown,但我仍然需要处理html。

    2 回复  |  直到 8 年前
        1
  •  0
  •   CSSBurner    8 年前

    我相信唯一的方法就是爆炸并重新组装管柱:

    $html_string = '....................'; // contains apostrophes and <code>...</code> blocks
    
    $delim = "<code>";
    $closing_tag = "</code>";
    $explode = explode($delim, $html_string);
    
    foreach($explode as &$ex) {
        $closing_tag_pos = strpos($ex, $closing_tag);
        if ($closing_tag_pos !== false) {
            $pre_closing_tag = substr($ex, 0, $closing_tag_pos);
            $post_closing_tag = substr($ex, $closing_tag_pos);
            $ex = $pre_closing_tag . preg_replace('/`/', '~~~APO~~~', $post_closing_tag);
        }
    }
    
    $mapped_html_string = implode($delim, $explode);
    
        2
  •  1
  •   Casimir et Hippolyte    8 年前

    使用xpath查询避免具有 code 元素作为祖先:

    $dom = new DOMDocument;
    $dom->loadHTML($html, LIBXML_HTML_NODEFDTD | LIBXML_HTML_NOIMPLIED);
    $xp = new DOMXPath($dom);
    $textNodes = $xp->query('//text()[not(ancestor::code)][contains(.,"`")]');
    foreach ($textNodes as $textNode) {
        $parts = (function($text) { yield from explode('`', $text); })($textNode->nodeValue);
        $frag = $dom->createDocumentFragment();
        do {
            $frag->appendChild($dom->createTextNode($parts->current()));
            $parts->next();
            if ( $parts->valid() ) {
                $codeElt = $dom->createElement('code');
                $codeElt->appendChild($dom->createTextNode($parts->current()));
                $frag->appendChild($codeElt);
                $parts->next();
            }
        } while ($parts->valid());
        $textNode->parentNode->replaceChild($frag, $textNode);
    }
    echo $dom->saveHTML();
    

    demo

    demo for php < 7.0