Question

I am not very good with Regex but I am learning.

I would like to remove some html tag by the class name. This is what I have so far :

<div class="footer".*?>(.*?)</div>

The first .*? is because it might contain other attribute and the second is it might contain other html stuff.

What am I doing wrong? I have try a lot of set without success.

Update

Inside the DIV it can contain multiple line and I am playing with Perl regex.

Was it helpful?

Solution

You will also want to allow for other things before class in the div tag

<div[^>]*class="footer"[^>]*>(.*?)</div>

Also, go case-insensitive. You may need to escape things like the quotes, or the slash in the closing tag. What context are you doing this in?

Also note that HTML parsing with regular expressions can be very nasty, depending on the input. A good point is brought up in an answer below - suppose you have a structure like:

<div>
    <div class="footer">
        <div>Hi!</div>
    </div>
</div>

Trying to build a regex for that is a recipe for disaster. Your best bet is to load the document into a DOM, and perform manipulations on that.

Pseudocode that should map closely to XML::DOM:

document = //load document
divs = document.getElementsByTagName("div");
for(div in divs) {
    if(div.getAttributes["class"] == "footer") {
        parent = div.getParent();
        for(child in div.getChildren()) {
            // filter attribute types?
            parent.insertBefore(div, child);
        }
        parent.removeChild(div);
    }
}


Here is a perl library, HTML::DOM, and another, XML::DOM
.NET has built-in libraries to handle dom parsing.

OTHER TIPS

As other people said, HTML is notoriously tricky to deal with using regexes, and a DOM approach might be better. E.g.:

use HTML::TreeBuilder::XPath;

my $tree = HTML::TreeBuilder::XPath->new;
$tree->parse_file( 'yourdocument.html' );

for my $node ( $tree->findnodes( '//*[@class="footer"]' ) ) {
    $node->replace_with_content;   # delete element, but not the children
}

print $tree->as_HTML;

In Perl you need the /s modifier, otherwise the dot won't match a newline.

That said, using a proper HTML or XML parser to remove unwanted parts of a HTML file is much more appropriate.

<div[^>]*class="footer"[^>]*>(.*?)</div>

Worked for me, but needed to use backslashes before special characters

<div[^>]*class=\"footer\"[^>]*>(.*?)<\/div>

Partly depends on the exact regex engine you are using - which language etc. But one possibility is that you need to escape the quotes and/or the forward slash. You might also want to make it case insensitive.

<div class=\"footer\".*?>(.*?)<\/div>

Otherwise please say what language/platform you are using - .NET, java, perl ...

Try this:

<([^\s]+).*?class="footer".*?>([.\n]*?)</([^\s]+)>

Your biggest problem is going to be nested tags. For example:

<div class="footer"><b></b></div>

The regexp given would match everything through the </b>, leaving the </div> dangling on the end. You will have to either assume that the tag you're looking for has no nested elements, or you will need to use some sort of parser from HTML to DOM and an XPath query to remove an entire sub-tree.

This will be tricky because of the greediness of regular expressions, (Note that my examples may be specific to perl, but I know that greediness is a general issue with REs.) The second .*? will match as much as possible before the </div>, so if you have the following:

<div class="SomethingElse"><div class="footer"> stuff </div></div>

The expression will match:

<div class="footer"> stuff </div></div>

which is not likely what you want.

why not <div class="footer".*?</div> I'm not a regex guru either, but I don't think you need to specify that last bracket for your open div tag

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top