Search code examples
phpregexlaravel-5.3

PHP replace only plain text


Following PHP function replaces all Latin digits with Persian digits, But it also replaces all Latin digits of the attributes of HTML tags, that makes them not working anymore, I want to replace the digits of only plain text, Please help me if know how to do that, thank you.

public static function LatinToPersianDigits($html)
{
  $Latin= ['0','1','2','3','4','5','6','7','8','9'];
  $Persian= ['۰','۱','۲','۳','۴','۵','۶','۷','۸','۹'];
  return str_replace($latin, $persian, $html);
}

Solution

  • An example:

    const TRANSDIGIT = [ '۰','۱','۲','۳','۴','۵','۶','۷','۸','۹' ];
    
    public static function LatinToPersianDigits($html)
    {
        libxml_use_internal_errors(true);
        $dom = new \DOMDocument;
        $dom->loadHTML('<?xml encoding="utf-8" ?><div>' . $html . '</div>', LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
        libxml_clear_errors();
    
        $xp = new \DOMXPath($dom);
        $textNodeList = $xp->query('//text()');
    
        foreach($textNodeList as $textNode) {
            $textNode->parentNode->replaceChild($dom->createTextNode(strtr($textNode->nodeValue, self::TRANSDIGIT)), $textNode);
        }
    
        $result = '';
    
        foreach ($dom->documentElement->childNodes as $childNode) {
            $result .= $dom->saveHTML($childNode);
        }
    
        return $result;
    }
    

    If you need something more smart to select specific parts of the text, you can always build a pattern (for preg_replace_callback) or a function to select these parts.

    demo