Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

Gabotronix's avatar

PHP DOMDocument : loop through all elements with text in an html string

I made a php method which takes an html string and loops through all "p" paragraph elements and translates them, now I want to improve my method to loop through all elements with text inside! So h2, span, a elements.

Can you help me?

My PHP method

$htmlString = 
        '<section>
        <h2>Ámbito de aplicación</h2>
        <p>
            Estas condiciones generales constituyen las condiciones de uso
            junto con las normas comunitarias, disponibles en
            http://add.com/community-rules y las posibles condiciones
            complementarias pactadas entre el usuario!.
        </p>
    </section>';
        

        
        $dom = new \DOMDocument();
        libxml_use_internal_errors(true);
        $dom->loadHTML($htmlString);

        foreach( $dom->getElementsByTagName("p") as $pnode ) 
        {
            //$nodeValue
            $nodeValue = $pnode->nodeValue;

            $translated = $this->translate($nodeValue)

            $newNode = $dom->createElement("p", $translated );

            $pnode->parentNode->replaceChild($newNode, $pnode);
        }
        $dom->saveHTML($dom);

Thanks in advance!

0 likes
6 replies
Braunson's avatar

You can do something like this within your foreach loop..

$childNodes = $pnode->childNodes;
foreach ($childNodes as $childNode) {
     // Perform actions with $childNode
}
Gabotronix's avatar

@Braunson I Want to replace all text values, currently I only do paragraphs.

Your solution is not working

Ishra's avatar

Do you know which tag names to look for?

If yes, then maybe you could use xpath, i found this stackoverflow answer that explains it better than i could: https://stackoverflow.com/a/7906888

If you don't know which tags to look for (if you want any tag that has text inside), then the solution by @braunson is your best option i think.

i took the liberty to combine your code with the solution offered by @braunsun This is untested code, but it should be pretty much correct.

$dom = new \DOMDocument();
libxml_use_internal_errors(true);
$dom->loadHTML($htmlString);

// get your first <section>
$section = $dom->getElementsByTagName('section')->item(0); 

// loop through each child of <section>
foreach ($section->childNodes as $childNode) { 
    // get the text of the child
    $nodeValue = $pnode->nodeValue; 

    if ($nodeValue === '') {
        // don't translate this, doesn't have any text content.
        continue; 
    }

    // the child have text that can be translated
    // almost identical to your original code

    $translated = $this->translate($nodeValue)

    $newNode = $dom->createElement($pnode->nodeName, $translated );

    $pnode->parentNode->replaceChild($newNode, $pnode);
}
Braunson's avatar

@Gabotronix Iterate through the sections..

// loop through each section
foreach ($dom->getElementsByTagName('section') as $section) {

    // loop through each child of <section>
     foreach ($section->childNodes as $childNode) { 

// ....
1 like
Ishra's avatar

@Gabotronix

Like @braunson said, find all <section> and loop through all of them.


$dom = new \DOMDocument();
libxml_use_internal_errors(true);
$dom->loadHTML($htmlString);

// get all <section>
$sections = $dom->getElementsByTagName('section'); 

// loop through each <section>
foreach ($sections as $section) {
    // loop through each child of <section>
    foreach ($section->childNodes as $childNode) { 
        // get the text of the child
        $nodeValue = $pnode->nodeValue; 

        if ($nodeValue === '') {
            // don't translate this, doesn't have any text content.
            continue; 
        }

        // the child have text that can be translated
        // almost identical to your original code

        $translated = $this->translate($nodeValue)

        $newNode = $dom->createElement($pnode->nodeName, $translated);

        $pnode->parentNode->replaceChild($newNode, $pnode);
    }
}

Please or to participate in this conversation.