tags:

views:

122

answers:

3

I am trying to write a regex which match the first ending form tag.

  <form.*name="loginForm".*>[^~]*</form>

The above regex matches till the second from ends i.e till line 8. but I want a regex that matches the immediate ending from tag in the below example it should match line 5.

<html>
<body>
<form method = "post" name="loginForm" >
<input type="text" name="userName"/>
</form>
<form method = "post" name="signupForm" >
<input type="text" name="userName"/>
</form>
</body>
</html>
+3  A: 

Use a real parser like DOMDocument, SimpleXML or SimpleHTMLDOM. Regular expressions are not suitable for parsing non-regular languages like HTML.

Gumbo
+1 Was going to say it, but I had to make the question presentable first. Let's link to the explanation of why (http://stackoverflow.com/questions/701166/can-you-provide-some-examples-of-why-it-is-hard-to-parse-xml-and-html-with-a-rege) and the example of parsers (http://stackoverflow.com/questions/773340/can-you-provide-an-example-of-parsing-html-with-your-favorite-parser) for completeness.
Chris Lutz
A regular expression works just fine for parsing a string like this. There is definitely no need for it to be a regular language to be parsed by a regular expression.
Guffa
+2  A: 

You should NOT use regular expressions, but parse it with DOM:

Javascript:

var forms = document.getElementsByTagName('form');
forms[0] // is the first form element.

PHP:

$dom = new DOMDocument();
$dom->loadHTML( $html );
$forms = $dom->getElementsByTagName('form');
$first = $forms->item(0); // reference to first form

You can use minidom and ElementTree for Python.

meder
+2  A: 

Just make the pattern non-greedy so that it matches the smallest possible amount of characters instead of the largest possible:

<form[^>]*name="loginForm"[^>]*>[^~]*?</form>

Edit:
Changed .* to [^>]* in the form tag, so that it doesn't match outside the tag.

Guffa
Will fail for nested tags. Not sure that forms will ever be nested, but using a regex to parse HTML is still a bad idea, even if it works in some select cases.
Chris Lutz
@Guffa: Then you should make all quantifiers non-greedy.
Gumbo
The question didn't ask for the matching form tag, it asked for the first, which might not be the best thing to do, but this is a valid and useful trick sometimes.
Kevin Peterson
@Chris: Form tags can't be nested.
Guffa
Sure they *can* be nested. It won't be valid of course.
meder
@Kevin: The first ending tag is the matching tag.
Guffa
@meder: Well, if the code is invalid, it can't be reliably parsed anyhow...
Guffa
@Gumbo: Good point, however they don't have to be non-greedy, they just have to be kept inside the tag.
Guffa
@Gumbo: Actually, if the expression before the name attribute would be just non-greedy, it fails if the loginForm is not the first form in the code...
Guffa