XHTML in IE9

IE9 is the first version of Internet Explorer to natively support XHTML. For those not familiar, XHTML is the XML serialization of HTML. Among other benefits, XHTML can help maintain cleaner markup due to its fail-fast nature in the face of parsing errors. You can see IE9 running XHTML for yourself by visiting examples on the Internet Explorer Test Drive site like SVG Helicopter, IE Beatz, and SVG-oids. In this post I’ll share a few details about XHTML and IE9's support for it.

What version of XHTML does IE9 support?

The short answer is XHTML5 (defined by the HTML5 specification). This means that new HTML5 elements such as <canvas>, <audio>, and <video> are all supported by XHTML in IE9. In fact, all of the same HTML (and SVG) elements and attributes that can be used in HTML in IE9 can also be used in XHTML in IE9. Moreover IE9 continues to follow "Same Markup" principles with XHTML just like with other parts of the platform, meaning most of the same XHTML markup should "just work" in the same way across IE9, Firefox, Chrome, etc.

How do I use XHTML in IE9?

Adding a <!DOCTYPE> pointing to an XHTML DTD does NOT influence whether a page is treated as HTML or XHTML. XHTML support for files on the web can only be triggered by the MIME type of the response from the web server. This is true both in IE9 and other browsers. This MIME type should be "application/xhtml+xml" (though you can technically use any supported XML mime type). Local files with ".xht" or ".xhtml" extensions will also be opened as XHTML.

You can verify the correct MIME type was sent to the browser using the "Network" tab in IE9's developer tools. Press F12 to open the tools, click "Start Capturing", and then refresh the page. The MIME type will be listed in the "Type" column for each file received from the server:

IE9 Dev tools, Network tab.

How does versioning impact XHTML?

IE9 will always run documents received with the "application/xhtml+xml" MIME type in IE9 Standards Mode. Not even the developer toolbar can override this behavior. The reason legacy document modes are not supported is because XHTML is new to IE9. Note that this means XHTML documents cannot be loaded into frames unless the parent page is also running in IE9 Standards Mode. These versioning rules also apply to SVG documents received as "image/svg+xml".

How does XHTML differ from HTML?

One of the most notable differences between XHTML and HTML is how parsing errors are handled. Any parsing error in an XHTML document will cause parsing to stop; no fix-up rules are applied. IE9 displays content parsed up until the point at which the error occurred. This is useful during development to catch errors quickly. You can find parsing error details in the "Console" tab of the developer toolbar (note you'll need to refresh the page to see the error if you opened the developer toolbar after the page loaded).

Another important difference is that XHTML is case-sensitive. For XHTML, this generally means that element and attribute names should be lowercased, both in markup and when referenced from script or CSS. Other languages embedded in XHTML may have elements and attributes with mixed case. Such elements and attributes must be written exactly as documented in the appropriate language specification. The "textPath" element from SVG is an example of this.

Yet another difference between HTML and XHTML is that XHTML supports namespaces in markup. This allows integration of XML languages beyond those explicitly defined in HTML5. Note that XHTML requires explicit namespace declarations for each language in use. This means that the root <html> element of an XHTML document must have the XHTML namespace declared in order to be interpreted properly:

 <!DOCTYPE html>
<html xmlns="https://www.w3.org/1999/xhtml">
    <head>
        <title>Sample</title>
    </head>
    <body>
        <h1>Sample</h1>
    </body>
</html>

Any embedded languages require their own namespace declarations as well. This is most easily done by placing the declaration on the start of the embedded sub-tree:

 <!DOCTYPE html>
<html xmlns="https://www.w3.org/1999/xhtml">
    <head>
        <title>Sample</title>
    </head>
    <body>
        <h1>Sample</h1>
        <svg xmlns="https://www.w3.org/2000/svg" width="100" height="100">
            <circle fill="green" cx="50" cy="50" r="50"/>
        </svg>
    </body>
</html>

Note that namespaces can also be associated with elements in other ways, though the approach outlined above generally results in markup that is more portable between HTML and XHTML. For a more in-depth explanation about authoring pages that validate in both HTML and XHTML, see the latest draft of the W3C's Polyglot Markup: HTML-Compatible XHTML Documents.

Next Steps

XHTML can be used today. Just be sure to apply feature detection when using XHTML while still supporting older browsers. Use server-side code to look at HTTP Accept header of incoming requests for the presence of "application/xhtml+xml" to determine if XHTML is supported by the requesting browser. If not, have your server fall back to returning polyglot markup as HTML (or some other reasonable alternative).

 // Pseudo-code for server-side XHTML detection
// Pivots between sending polyglot markup as XHTML or HTML
IF request.headers["Accept"] CONTAINS "application/xhtml+xml"
    // XHTML is supported; use it
    response.headers["Content-Type"] = "application/xhtml+xml"
ELSE
    // XHTML is not supported; fall back to HTML
    response.headers["Content-Type"] = "text/html"

Tony Ross

Program Manager