Search code examples
phphtmldomdomxpath

How to append the text (increasing order) using DOM parser in PHP?


$html='<h1 class="title">Exponents[label*exponents]</h1>
<h2 class="title">Exponents[label*exponents]</h2>
<h2 class="title">Exponents[label*exponents]</h2>
<h1 class="title">Exponents[label*exponents]</h1>
<h2 class="title">Exponents[label*exponents]</h2>
<h2 class="title">Exponents[label*exponents]</h2>
<h2 class="title">Exponents[label*exponents]</h2>
<h3 class="title">Exponents[label*exponents]</h3>
<h1 class="title">Exponents[label*exponents]</h1>
<h1 class="title">Exponents[label*exponents]</h1>
<h2 class="title">Exponents[label*exponents]</h2>';

Expected output:

<h1 class="title">1.1 Exponents[label*exponents]</h1>
<h2 class="title">1.1.1 Exponents[label*exponents]</h2>
<h2 class="title">1.1.2 Exponents[label*exponents]</h2>
<h1 class="title">1.2 Exponents[label*exponents]</h1>
<h2 class="title">1.2.1 Exponents[label*exponents]</h2>
<h2 class="title">1.2.2 Exponents[label*exponents]</h2>
<h2 class="title">1.2.3 Exponents[label*exponents]</h2>
<h3 class="title">1.2.3.1 Exponents[label*exponents]</h3>
<h1 class="title">1.3 Exponents[label*exponents]</h1>
<h1 class="title">1.4 Exponents[label*exponents]</h1>
<h2 class="title">1.4.1 Exponents[label*exponents]</h2>;

For example, if the append text is 1.1 then first 1 is chapter no. and second 1 is first occurrence of h1, if it is 1.2.2 then it is chapter no. then second occurrence of h1 and second occurrence of h2. As I'm learning DOM parser class I have tried something like this below,

$dom = new DOMDocument;
$dom->loadHTML($html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);

$xp = new DOMXPath($dom);
$xp->registerNamespace("php", "http://php.net/xpath");
$className="title";
$hElement = $xp->query("//*[contains(@class, '$className')]");
$chapno=1;
$h1=0;
$h2=0;
$h3=0;
$h4=0;

foreach($hElement as $hNode) {
     if($hElement==="h1"){
         $h1++;
         $append="$chapno.$h1 ";
         $hnode->nodeValue =$append.$hNode->textContent;
         $h2=0;$h3=0;$h24=0;         
     }
     if($hElement==="h2"){
         $h2++;
         $append="$chapno.$h1.$h2 ";
         $hnode->nodeValue =$append.$hNode->textContent;
     }

     if($hElement==="h3"){
         $h3++;
         $append="$chapno.$h1.$h2.$h3 ";
         $hnode->nodeValue =$append.$hNode->textContent;
     }

     if($hElement==="h4"){
         $h4++;
         $append="$chapno.$h1.$h2.$h3.$h4 "; 
         $hnode->nodeValue =$append.$hNode->textContent;
     }           
}

I don't know whether it is correct approach to get my expected output and if it is correct,I don't know how to do further.


Solution

  • I simplify your code, and then was able to understand it. I hope all is clear.

    $dom = new DOMDocument;
    $dom->loadHTML($html);
    
    $xp = new DOMXPath($dom);
    $xp->registerNamespace("php", "http://php.net/xpath");
    $className="title";
    $hElement = $xp->query("//*[contains(@class, '$className')]");
    $chapno=1;
    $h = array(0, 0, 0, 0); 
    
    foreach($hElement as $hNode) {
        if ($hNode->nodeName[0] === 'h') {     // 1st letter is tag name
           $i =  $hNode->nodeName[1];          // level number 
    
           $h[$i-1]++;                         // increase counter of level
           $append = $chapno.".".implode('.', array_slice($h, 0, $i));
           while($i < count($h)) $h[$i++] = 0; // set lower levels with start value 
           $hNode->nodeValue = $append." ".$hNode->nodeValue;  // Don't forget to change title text
        }
    }   
    
    echo $dom->saveHTML();
    

    result

    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
    <html><body><h1 class="title">1.1 Exponents[label*exponents]</h1>
    <h2 class="title">1.1.1 Exponents[label*exponents]</h2>
    <h2 class="title">1.1.2 Exponents[label*exponents]</h2>
    <h1 class="title">1.2 Exponents[label*exponents]</h1>
    <h2 class="title">1.2.1 Exponents[label*exponents]</h2>
    <h2 class="title">1.2.2 Exponents[label*exponents]</h2>
    <h2 class="title">1.2.3 Exponents[label*exponents]</h2>
    <h3 class="title">1.2.3.1 Exponents[label*exponents]</h3>
    <h1 class="title">1.3 Exponents[label*exponents]</h1>
    <h1 class="title">1.4 Exponents[label*exponents]</h1>
    <h2 class="title">1.4.1 Exponents[label*exponents]</h2></body></html>