fork download
  1. <?php
  2.  
  3. function separateAnchors($html) {
  4. // Define a character sequence that
  5. // will certainly not occur in your document,
  6. // and is interpreted as literal in regular expressions:
  7. $magicChar = "²³²";
  8. $doc = new DOMDocument();
  9. $doc->loadHTML($html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
  10. $xpath = new DOMXPath($doc);
  11. $anchors = $xpath->query("//a");
  12. foreach (array_reverse(iterator_to_array($anchors)) as $anchor) {
  13. $parent = $anchor->parentNode;
  14. $origAnchor = $anchor->cloneNode(true);
  15. // temporariy put the special text in the anchor
  16. $anchor->textContent = $magicChar;
  17. // and then take the document's text content
  18. $txt = $doc->textContent;
  19. // If that contains the special text with a non-space following it:
  20. if (preg_match("/{$magicChar}\S/u", $txt)) {
  21. // ... then add a single space node after it, after
  22. // any closing parent nodes
  23. $elem = $anchor;
  24. while (!$elem->nextSibling) $elem = $elem->parentNode;
  25. $elem->parentNode->insertBefore($doc->createTextNode(" "),
  26. $elem->nextSibling);
  27. }
  28. // Put original anchor back in place
  29. $parent->replaceChild($origAnchor, $anchor);
  30. }
  31. return $doc->saveHTML();
  32. }
  33.  
  34. // sample data
  35. $html = "<p><a>first link</a>&nbsp;<a>second link</a>this word is too close</p>\n
  36. <table><tr><td><a>table cell</a></td></tr></table><span>end</span>\n
  37. <div><a>link</a></div><span><a>too close</a></span>";
  38.  
  39. // inject spaces
  40. $html = separateAnchors($html);
  41.  
  42. // Show result
  43. echo $html;
  44.  
  45. ?>
Success #stdin #stdout 0s 52488KB
stdin
Standard input is empty
stdout
<p><a>first link</a>&nbsp;<a>second link</a> this word is too close<table><tr><td><a>table cell</a></td></tr></table> <span>end</span><div><a>link</a></div> <span><a>too close</a></span></p>