Hi again!

Before I get to the real issue, I think I should give you a little bit of background. I'm working for a company which makes a web browser. We've been having some problems with our algorithm for parsing illegal html, so we decided to scrap the whole module and implement the algorithm exactly as outlined in the html5 spec. So far this has been a great success. We're already way better than we used to be, but there are some situations where the html5 parsing algorithm does not quite give us the result we expected.

Yesterday I noticed that we were not displaying the site http://bankrate.com correctly. The problem we had on that page boils down to the following markup:

<div id="firstdiv">
   A
   <div id="seconddiv">
       <form id="firstform">
           <div id="thirddiv">
               <form id="secondform"></form>
           </div>
       </form>
   </div>
   B
</div>

I'll walk you through it; Everything is normal until we reach the start tag for the "secondform". It is ignored, since we're already in a form (the form element pointer points to "firstform".) Then we see the end tag which was meant for "secondform". We pop elements from the stack of open elements until we find a form element (which is "firstform") popping off "thirddiv" in the process. The next token we get is the end div tag which was meant for "thirddiv". Since "thirddiv" is already gone, we pop "seconddiv" instead, and now we're sort of off-balance. The result is that A and B does not end up as children of the same div.

If any of you would like to see the effect this can have on a real page, you can use the parse.py script in html5lib. On a command line, use the following commands:

[EMAIL PROTECTED] html]$ wget -k -O bankrate.html http://bankrate.com
[EMAIL PROTECTED] html]$ /path/to/html5lib/python/parse.py bankrate.html > bankrate_parsed.html
[EMAIL PROTECTED] html]$ firefox bankrate_parsed.html

I've applied a fix to our code which makes us handle this particular case better. I haven't tested it very thoroughly, but the change is to implement the 'An end tag whose tag name is "form"' section in "in body" as if it said:

------
An end tag whose tag name is "form"

   Let /node/ be the form element pointer
   Set the form element pointer to null.

If the stack of open elements does not have an element in scope with the same tag name as that of the token, then this is a parse error; ignore the token.

   Otherwise, run these steps:

      1. Generate implied end tags.
2. If the current node is not an element with the same tag name as that of the token, then this is a parse error.
      3. Remove /node/ from the stack of open elements
------

This seems to give us pretty much the same behaviour as Opera for the simple example above. Can any of you see any potential problems with this approach? In any case, I do believe that the specification needs to be changed one way or another, so that it handles this case better.

I think I have a couple of other instances where we've had to deviate from the specification in order to tackle problems discovered by our testers, and if any of you are interested in this kind of feedback, I'll dig them out and post them on this list.

Best regards
Tommy Thorsen

Reply via email to