PHP DOMDocument replace DOMElement child with HTML string

后端 未结 5 1615
[愿得一人]
[愿得一人] 2020-12-31 13:09

Using PHP I\'m attempting to take an HTML string passed from a WYSIWYG editor and replace the children of an element inside of a preloaded HTML document with the new HTML.

5条回答
  •  清酒与你
    2020-12-31 13:58

    The current accepted answer suggests using appendXML(), but acknowledges that it won't handle complex html such as what is returned from a WYSISYG editor as specified in the original question. As suggested loadHTML() can address this. but no one has yet shown how.

    This is what I believe is the best/correct answer to the original question addressing encoding issues, "Document Fragment is empty" warnings and "Wrong Document Error" errors that someone is likely to hit if they write this from scratch. I know I found them after following the hints in the previous responses.

    This is code from a site I support that inserts WordPress sidebar content into the $content of a post. It assumes that $doc is a valid DOMDocument similar to the way $doc is defined in the original question. It also assumes that $element is the tag after which you wish to insert the sidebarcontent (or whatever).

                // NOTE: Cannot use a document fragment here as the AMP html is too complex for the appendXML function to accept.
                // Instead create it as a document element and insert that way.
                $node = new DOMDocument();
                // Note that we must encode it correctly or strange characters may appear.
                $node->loadHTML( mb_convert_encoding( $sidebarContent, 'HTML-ENTITIES', 'UTF-8') );
                // Now we need to move this document element into the scope of the content document 
                // created above or the insert/append will be rejected.
                $node = $doc->importNode( $node->documentElement, true );
                // If there is a next sibling, insert before it.
                // If not, just add it at the end of the element we did find.
                if (  $element->nextSibling ) {
                    $element->parentNode->insertBefore( $node, $element->nextSibling );
                } else {
                    $element->parentNode->appendChild($node);
                }
    

    After all of this is done, if you don't want to have the source of a full HTML document with body tags and what not, you can generate the more localized html with this:

        // Now because we have moved the post content into a full document, we need to get rid of the 
        // extra elements that make it a document and not a fragment
        $body = $doc->getElementsByTagName( 'body' );
        $body = $body->item(0);
    
        // If you need an element with a body tag, you can do this.
        // return $doc->savehtml( $body );
    
        // Extract the html from the body tag piece by piece to ensure valid html syntax in destination document
        $bodyContent = ''; 
        foreach( $body->childNodes as $node ) { 
                $bodyContent .= $body->ownerDocument->saveHTML( $node ); 
        } 
        // Now return the full content with the new content added. 
        return $bodyContent;
    

提交回复
热议问题