How to replace strings except inside tag attributes in PHP?

Viewed 51

Problem

I have a working script to mass replace all occurrences of listed strings:

function replace_content( $text_content ) {
    $input = file_get_contents(__DIR__ . "/strings.json");
    $data = json_decode($input, true);
    $textlist = array();
    foreach($data as $item) {
        $text_content = str_ireplace( $item['n.name'], "<span class='hello'>" . $item['n.name'] .'</span>', $text_content );
    }
    return $text_content;
}
add_filter( 'the_content', 'replace_content' );

However, for occurrences inside tag attributes, I don't want them to be replaced. For example, if I have:

<div id="AListedString" foobar="bla n.name='AnotherListedString' bla">
 AListedString YetAnotherListedString
</div>

then the desired output is:

<div id="AListedString" foobar="bla n.name='AnotherListedString' bla">
 <span class='hello'>AListedString</span>
 <span class='hello'>YetAnotherListedString</span>
</div>

So far the script replaces all occurrences of AListedString, AnotherListedString, YetAnotherListedString. How should I do this?

Attempt

I found this question How to replace text except when it's between two tags in PHP?, but when I use this code:

function replace_content( $text_content ) {
    $input = file_get_contents(__DIR__ . "/node.json");
    $inputclean = removeBOM($input);
    $data = json_decode($inputclean, true);
    $textlist = array();
    foreach($data as $item) {
        // $replaceStr = "<span class='beliefnode'>" . $item['n.name'] .'</span>'
        $text_content = str_ireplace( $item['n.name'], "<span class='beliefnode'>" . $item['n.name'] .'</span>', $text_content );
        $domElem = new DOMDocument();
        $domElem->loadXML("<temp_tag>".$text_content."</temp_tag>");
        $nodes = $domElem->getElementsByTagName('div');
        $index = 0;
        while($nodes->item($index)->nodeValue)
          {
            $nodes->item($index)->nodeValue = str_replace("<span class='beliefnode'>" . $item['n.name'] .'</span>',
                                                          $item['n.name'],
                                                          $nodes->item($index)->nodeValue);
            $index++;
          }

        echo $domElem->saveHTML();
    }
    return $text_content;
}
add_filter( 'the_content', 'replace_content' );

It throws a lot of errors that I think it's really not the way to solve this.

0 Answers
Related