phpdom-node

How to convert HTML string to DOMNode to use DOMNode::insertBefore in PHP?


In my PHP project I´m using DOMDocument to get the view like this :

Page object´s method

protected function html_page_template(){
    wp_debug_log();
    $htmlTmpl = new \DOMDocument;
    $html = '<div class="wrap">';
    $html .= $this->writeTopPage();
    $html .= "<hr/>";
    $html .= "</div>";
    $htmlTmpl->loadXML($html);
    $this->current_template->write( $htmlTmpl );
    echo $htmlTmpl->saveXML();
} 

In the template object ( $this->current_template ), I have a write method to get the page content. It´s useful to modify the HTML already injected as well.

Template object´s method

public function write(&$htmlTmpl)
{

    //Link "Options advanced"
    $link_advanced_options = $htmlTmpl->createElement("a", esc_html( __( "Avanced Options", PLUGIN_DOMAIN ) ) );
    $linkOptionsHrefAttribute = $htmlTmpl->createAttribute("href");
    $linkOptionsHrefAttribute->value = "#";
    $linkOptionsClassAttribute = $htmlTmpl->createAttribute("class");
    $linkOptionsClassAttribute->value = "options-advanced-link";
    $link_advanced_options->appendChild($linkOptionsHrefAttribute);
    $link_advanced_options->appendChild($linkOptionsClassAttribute);
    $htmlTmpl->importNode($link_advanced_options, true);

    //Section "Options advanced
    $section_advanced_options = $htmlTmpl->createElement( "section" );
    $sectionOptionsClassAttribute = $htmlTmpl->createAttribute("class");
    $sectionOptionsClassAttribute->value = "options-advanced-section";
    $section_advanced_options->appendChild($sectionOptionsClassAttribute);

    //Input "From Date"
    $inp_element = $htmlTmpl->createElement( "input" );
    $inpTypeAttribute = $htmlTmpl->createAttribute("type");
    $inpTypeAttribute->value = "date";
    $inpValueAttribute = $htmlTmpl->createAttribute("value");
    $inpValueAttribute->value = "2018-06-25";
    $inp_element->appendChild($inpTypeAttribute);
    $inp_element->appendChild($inpValueAttribute);

    //Button "Download foos"
    $btn_element = $htmlTmpl->createElement("a", "Download foos" );
    $btnClassAttribute = $htmlTmpl->createAttribute("class");
    $btnClassAttribute->value = "add-new-h2 h4a-button";
    $btnHrefAttribute = $htmlTmpl->createAttribute("href");
    $admin_build_url = "myexample.com?run=foo";
    $btnHrefAttribute->value = $admin_build_url;
    $btn_element->appendChild($btnClassAttribute);
    $btn_element->appendChild($btnHrefAttribute);
    $section_advanced_options->appendChild($btn_element);
    $section_advanced_options->appendChild($inp_element);

    $nodeLine = $htmlTmpl->getElementsByTagName("hr")->item(0);
    $parentNode = $htmlTmpl->getElementsByTagName("div")->item(0);
    $parentNode->insertBefore( $section_advanced_options, $nodeLine );
    $parentNode->insertBefore( $link_advanced_options, $section_advanced_options );

} 

For more convenience, I would like to write the code to insert as HTML string and convert it as DomNode to use $parentNode->insertBefore(). How can I do this ?


Solution

  • The solution si to use createdocumentfragment like this :

    Template object´s method

    public function write(&$htmlTmpl)
    {
    
        $html_advanced_options = '<a href="#">My link</a>';
        $html_advanced_options .= 'other html';
        ...        
    
        $tmpl_advanced_options = $htmlTmpl->createDocumentFragment();
        $tmpl_advanced_options->appendXML( $html_advanced_options );
    
        $nodeLine = $htmlTmpl->getElementsByTagName("hr")->item(0);
        $parentNode = $htmlTmpl->getElementsByTagName("div")->item(0);
        $parentNode->insertBefore( $section_advanced_options, $nodeLine );
        $parentNode->insertBefore( $tmpl_advanced_options, $section_advanced_options );
    
    }