http://qs321.pair.com?node_id=11125300


in reply to regex in perl

"HTML is not a regular language and hence cannot be parsed by regular expressions. Regex queries are not equipped to break down HTML into its meaningful parts."
CodingHorror: Parsing HTML the Cthulu Way

The fact is that it's deceptively simple in appearance. What could be so bad about using regex for this? I really like tchrist's explanation on StackOverflow: Oh Yes You Can Use Regexes to Parse HTML!. Here are a few of the many useful statements in that post:

Let's open our eyes, then. Where's your sample input? I don't see any. So now I have to contrive some. I grabbed this from http://geeksforgeeks.org/span-tag-html:

<!DOCTYPE html> <html> <head> <title>GeeksforGeeks span tag</title> <!-- style for span tag --> <style type=text/css> span{ color: green; text-decoration: underline; font-style: italic; font-weight: bold; font-size: 26px; } </style> </head> <body> <h2>Welcome To GFG</h2> <span>GeeksforGeeks</span></br> <span>GeeksforGeeks</span></br> <span>GeeksforGeeks</span></br> </body> </html>

And now lets open our minds to what a proper DOM class can achieve:

#!/usr/bin/env perl use strict; use warnings; use Mojo::DOM; my $content = <<'HERE'; <!DOCTYPE html> <html> <head> <title>GeeksforGeeks span tag</title> <!-- style for span tag --> <style type=text/css> span{ color: green; text-decoration: underline; font-style: italic; font-weight: bold; font-size: 26px; } </style> </head> <body> <h2>Welcome To GFG</h2> <span>GeeksforGeeks</span></br> <span>GeeksforGeeks</span></br> <span>GeeksforGeeks</span></br> </body> </html> HERE my $dom = Mojo::DOM->new($content); $dom->find('span')->map('remove'); print "$dom\n";

This produces:

<!DOCTYPE html> <html> <head> <title>GeeksforGeeks span tag</title> <!-- style for span tag --> <style type="text/css"> span{ color: green; text-decoration: underline; font-style: italic; font-weight: bold; font-size: 26px; } </style> </head> <body> <h2>Welcome To GFG</h2> </body> </html>

The beauty here is that you don't have to worry about what happens in the case of nested spans, which the regex you're producing doesn't look like it would deal with gracefully. And you don't have to worry about a whole bunch of other nuances, such as the fact that <span and <     span are equivalent (but also not handled by the regex you were crafting).

And what's the cost? In terms of non-core Perl modules, you've added:

All of those are part of the Mojolicious distribution, which is distributed as a 776kb tarball, and installable with only core Perl tools. Additionally, this distribution provides you with a nice User Agent, and a great test framework. It takes under a minute to install, and has no non-core dependencies.

My own take: It may be that I could take a stab at writing an HTML parser that would remove span tags, and also the other things you were asking about the day before, and the things you will ask about tomorrow, for the subset of HTML you deal with in your specific use case. And I might get it right. But I will have wasted a lot of time to implement a more fragile solution to a very specific problem, and it would be a tool that couldn't grow as my problem evolves.

I don't know what your job is, but my job is not to spend more time than necessary to create a less robust, more buggy solution to an already solved problem if I'm aware a shorter-time-to production, more robust, less buggy, easier to understand approach exists. Now I may sometimes manage to do that unintentionally anyway. But when shown the light, I realize that part of my job is to learn, and evolve to adopt the better approach.


Dave