0

I want to try replace all instances of the following tags and remove the p and end p before and after but only when the the class readmore is used

<p><a class="readmore" href="http://www.google.com">My External Link</a></p>

Thanks in advance.

  • 6
    [no no no no do not use regex for this](http://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags/1732454#1732454) – Kevin L Jul 18 '14 at 16:49
  • 1
    Use the xpath expression: `//p[contains(a[@class="readmore"])]` – Ja͢ck Jul 18 '14 at 16:51
  • 1
    FYI, this would be fairly trivial (and very reliable) with e.g. DOMDocument. Do you really need to do it with preg_replace()? – Álvaro González Jul 18 '14 at 16:51

1 Answers1

3

You've asked for regex, but it's not really a good solution for parsing HTML.

DOMDocument / XPath

Load the document you want to process, find the elements you want to shuffle, shuffle them. Something not unlike this might work:

$document = new DOMDocument();
$document->loadHTMLFile(FILENAME);
$xpath = new DOMXPath($document);
$nodeList = $xpath->evaluate("//p[contains(a[@class='readmore'])]");
foreach ($nodeList as $node) {
    $node->parentNode->replaceChild($node->firstChild, $node);
}

XSLT

See this answer for help removing nodes with an XSL stylesheet. You can build a template something like the following:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output omit-xml-declaration="yes"/>

  <xsl:template match="node()|@*">
    <xsl:copy>
      <xsl:apply-templates select="node()|@*"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="p[contains(a[@class='readmore'])]">
    <xsl:copy-of select="a"/>
  </xsl:template>
</xsl:stylesheet>

Regex

If you really want to go the way of doom then I don't suppose I'll be able to stop you. Make sure you've got everything in source control and review the diffs before committing...

preg_replace('#<p>(<a class="readmore" href="[^"]+">[^<]*<\/a>)<\/p>#', '\1');
Community
  • 1
  • 1
simpleigh
  • 2,854
  • 18
  • 19