0
\$\begingroup\$

Goal

I want to extract HTML tags and its content from a string. The content (input) is queried from WordPress database.

Sample data (input)

I extract this dummy data from my WordPress database: https://www.phpliveregex.com/p/tan
I believe this should cover all the needed tags to parse.

Expectation (output)

Accepting a HTML-format string as input. The output should be able to return a string which could be any of these:

  1. The HTML element string itself
  2. Attributes string of the HTML element
  3. Text nodes, child nodes string of the HTML element

My concern

  • Which solutions take less execution time?
  • Which solutions save more server memory?
  • Security vulnerable of each solutions.

Solutions

I've come up with a 2 solutions by myself. It works fine, but I don't know which one is good for my case.

Regex pattern

$el = 'li'; // Ex
$match = []; // Reserving for results

/**
 * Regex - extract HTML tag and its content
 * Array map:
 * x[0] = everything
 * x[1] = open tag
 * x[2] = attributes
 * x[3] = content & end tag
 * x[4] = content only
 * 
 * Note for content: including text node + children node
 */
$reg = '/(<'.$el.'(.*?)>)((\n*?.*?\n*?)<\/'.$el.'>|)/';

if (preg_match($reg, $html_str, $match)) { echo 'Moving onward!';}

Result: see demo of regex

DOM object

$dom = new DomDocument();
$content = mb_convert_encoding(
    get_the_content(null, true), # WordPress func, it gives input str
    'HTML-ENTITIES',
    'UTF-8'
);
$dom->loadHTML($content);

$el = $doc->getElementsByTagName('li');

Result: returning a DOMNodeList and I have to do few more tasks to print it to a string which can be used.

\$\endgroup\$
4
  • 2
    \$\begingroup\$ They do different things, with different behavior in various cases of malformed or nested tags. It would be better to show us your real code, in context, with a clear statement of the task that your code accomplishes, so that we can advise you properly. See How to Ask. \$\endgroup\$ – 200_success Aug 16 '19 at 1:28
  • 1
    \$\begingroup\$ Those are my real code, unless you want to see my repo. The context accepts WordPress content as input. A sample data were added as demo of regex. phpliveregex.com/p/tan \$\endgroup\$ – Star Light Aug 16 '19 at 1:36
  • 5
    \$\begingroup\$ As always, see this answer for important information on parsing HTML with regex. \$\endgroup\$ – AJNeufeld Aug 16 '19 at 2:22
  • 1
    \$\begingroup\$ Please do not update the code in your question to incorporate feedback from answers, doing so goes against the Question + Answer style of Code Review. This is not a forum where you should keep the most updated version in your question. Please see what you may and may not do after receiving answers. \$\endgroup\$ – Vogel612 Aug 16 '19 at 14:26
5
\$\begingroup\$

Using regex to parse valid html will work (and you might call it beautiful) until it doesn't work... then you'll bend over backwards (over and over) each time you encounter an anomaly then try to write a patch for the pattern.

Allow me to notify you of a simple, valid html occurrence that will break your sample pattern:

Demo

<link rel="stylesheet" href="/html_5/tags/html_link_tag_example.css">

It would match because your li needle is not immediately followed by a word boundary character (\b). Is this a simple thing to fix? Yes, but my point remains -- regex is an inappropriate tool for parsing valid html.

I generally rely on DomDocument for most cases and when XPath makes life simpler, I use that to perform clean, readable queries on the document.

This is one time when focussing on speed is a moot point -- speed is the least of your worries. What good is speed if the results are bogus? The goal should be to design a robust and reliable script using DOM-aware techniques.

\$\endgroup\$
4
  • \$\begingroup\$ Didn't see that comin'. But if I just use it in a very small scope of HTML then maybe it's ok right? Only makup tags, not meta tags. \$\endgroup\$ – Star Light Aug 16 '19 at 12:43
  • \$\begingroup\$ Btw, I take advise about the speed. But what about memory consuming? (didn't got coffee last night untill this morning. Sorry) \$\endgroup\$ – Star Light Aug 17 '19 at 0:42
  • \$\begingroup\$ Okay, one last example breakage: 3v4l.org/0J5Wt. Now, to answer your comment about "Can I do it? What if I do it just a little bit? And only when it feels right? And I'll promise to stop as soon as I can." That right there, my friend, is how people wind up pregnant and battling horrid STDs. My advice: abstain. Draw a good thick line in the sand and bellow the mantra: "Thou shall not parse valid html with regex." Can I stop you? No. I can only give advice about what I think is best. Is there a greater cost in speed and memory? Certainly. Is it worth it? Certainly. \$\endgroup\$ – mickmackusa Aug 17 '19 at 5:25
  • 1
    \$\begingroup\$ You are absolute right. I've just encountered a problem that it's ridiculous hard to solve by regex. It's querying a child node of an element. Because regex is just a fixed pattern, I couldn't get as much as I want in easy way. Now I really few sorry for changing to regex solution, it took another day good for nothing. Also like you say, yeah, regex is not a good choice when it comes to HTML. Thanks, I've been enlightened. Your example is so wonderful! \$\endgroup\$ – Star Light Aug 17 '19 at 11:04

Not the answer you're looking for? Browse other questions tagged or ask your own question.