A document that uses polyglot markup is a document that is a stream of bytes that parses into identical document trees (with some exceptions, as noted in the Introduction) when processed as HTML and when processed as XML. Polyglot markup that meets a well-defined set of constraints is interpreted as compatible, regardless of whether they are processed as HTML or as XHTML, per the HTML5 specification. Polyglot markup uses a specific DOCTYPE, namespace declarations, and a specific case—normally lower case but occasionally camel case—for element and attribute names. Polyglot markup uses lower case for certain attribute values. Further constraints include those on void elements, named entity references, and the use of scripts and style.

This document summarizes design guidelines for authors who wish their XHTML or HTML documents to validate on either HTML or XML parsers, assuming the parsers to be HTML5-compliant. This specification is intended to be used by web authors. It is not a specification for user agents and creates no obligations on user agents. Note that this recommendation does not define how HTML5-conforming user agents should process HTML documents. Nor does it define the meaning of the Internet Media Type text/html. For user agent guidance and for these definitions, see [[!HTML5]] and [[!RFC2854]].

This document was published by the HTML working group as an Editor's Draft. Please submit comments regarding this document by using the W3C's public bug database ( http://www.w3.org/Bugs/Public/) with the product set to HTML WG and the component set to HTML/XHTML Compatibility Authoring Guide (ed: Eliot Graff). If you cannot access the bug database, submit comments by email to the mailing list.

Introduction

It is often valuable to be able to serve HTML5 documents that are also well formed XML documents. An author may, for example, use XML tools to generate a document, and they and others may process the document using XML tools. The language used to create documents that can be parsed by both HTML and XML parsers is called polyglot markup. Polyglot markup is the overlap language of documents that are both HTML5 documents and XML documents. It is recommended that these documents be served as either text/html (if the content is transmitted to an HTML-aware user agent) or application/xhtml+xml (if the content is transmitted to an XHTML-aware user agent). Other permissible MIME types are text/xml, application/xml, and any MIME type whose subtype ends with the four characters "+xml". [[!XML-MT]]

Polyglot markup results in:

Polyglot markup is not constrained:

Polyglot markup is scripted according to the rules of XML (does not use document.write, for example) and excludes HTML elements that are impossible to replicate in an XML parser (does not use the noscript element, for example). Polyglot markup triggers non-quirks mode in HTML parsers, as non-quirks mode is closest to XML-mode rendering, in regard to both DOM and CSS. Polyglot markup results in the same encoding and the same language in both HTML-mode and XML-mode.

All web content need not be authored in polyglot markup. Polyglot markup is ideal for publishing when there's a strong desire to serve both HTML and XML tool chains without simultaneously having to maintain dual copies of the content: one in HTML and a second in XHTML. In addition, a single polyglot markup output requires less infrastructure to produce than to produce both HTML and XHTML output for the same content. Polyglot markup is also be beneficial when lightweight processes—such as quick testing or even hand-authoring—are applied to content intended to be published both as HTML and XHTML, especially if that content is not sent through a tool chain.

Polyglot markup, itself being valid HTML5, supports extensibility as it is defined in Section 2.2.3 Extensibility of HTML5, so long as the extension does not violate the rules of polyglot markup. [[!HTML5]] In addition, being well formed XML, polyglot markup can be extended when it is served as application/xhtml+xml.

Processing Instructions and the XML Declaration

Processing Instructions and the XML Declaration are both forbidden in polyglot markup.

Specifying a Document's Character Encoding

Polyglot markup uses the UTF-8 character encoding, the only character encoding for which both HTML and XML require support. HTML requires UTF-8 to be explicitly declared to avoid fallback to a legacy encoding [[!HTML5]]. For XML, UTF-8 is an encoding default. As such, character encoding MAY be left undeclared in XML with the result that UTF-8 is still supported [[!XML10]].

Polyglot markup declares the UTF-8 character encoding in the following ways, which may be used separately or in combination:

The HTML encoding declaration has no effect in XML. When the HTML encoding declaration is the only encoding declaration, the encoding default from XML makes XML parsers treat content as UTF-8.

The W3C Internationalization (i18n) Group recommends to always include a visible encoding declaration in a document, because it helps developers, testers, or translation production managers to check the encoding of a document visually.

The DOCTYPE

Polyglot markup uses a document type declaration (DOCTYPE) specified by section 8.1.1 of [[!HTML5]]. In addition, the DOCTYPE conforms to the following rules:

The string html SHOULD be in lowercase letters, in order to be both well-formed and valid XML; however, the string MAY be in mixed case or uppercase letters and still be well-formed XML.

Note that using about:legacy-compat in XML may yield unpredictable parsing results, depending on the XML processing pipeline.

Polyglot markup does not use document type declarations for HTML4, HTML3, or HTML2, regardless of whether they contain a URI or not and regardless of their effect in HTML5 parsers, as these document type declarations are not compatible with XHTML.

Namespaces

The following rules apply to namespaces used in polyglot markup.

Element-Level Namespaces

[[!HTML5]] introduces undeclared (native) default namespaces for the root HTML element, html, the root SVG element, svg, and the root MathML element, math. Polyglot markup declares the following default namespaces, when the markup languages are included in the document, to maintain XML-compatibility [[!XML10]]:

Polyglot markup declares the default namespaces on the root HTML element, html, the root SVG element, svg, and the root MathML element math, and on any HTML elements used as children of SVG or MathML elements. Polyglot markup does not declare any other default or prefixed element namespace, because [[!HTML5]] does not natively support the declaring of any other default or prefixed element namespace.

Attribute-Level Namespaces

[[!HTML5]] introduces undeclared (native) support for attributes in the XLink namespace and with the prefix xlink:. Polyglot markup declares the XLink namespace on the HTML root element (html) or once on the foreign element where it is used (svg or math), to maintain XML-compatibility [[!XML10]].

In polyglot markup, the xlink prefix uses the namespace declaration xmlns:xlink="http://www.w3.org/1999/xlink" before using the xlink prefix for the following attributes:

Note that there are other prefixed attributes that can be used beyond xlink:href (such as xml:base). Polyglot markup does not declare these prefixes via xmlns. The prefixes are implicitly declared in XML and are automatically applied to the appropriate attributes in HTML.

The prefixed attributes, such as xml:lang="", are "namespaced" within XHTML, SVG and MathML. Thus, they can be styled via CSS3 namespaces. [[!CSS3NAMESPACE]] However, for the HTML serialization, xml:lang would then not have the xml namespace effect. A style such as the following is valid in XHTML, SVG, and MathML, it does not work in HTML and is therefore not used in polyglot markup.

<style type="text/css">
@namespace xml   "http://www.w3.org/XML/1998/namespace";
*[xml|lang]{background:lime;}
</style>
		

Elements

Polyglot markup conforms to the following rules regarding elements.

Required Elements

Every polyglot markup document contains an html, head, title, and body element. The html element is the root element. The head and body elements are children of the html element. The title element is a child of the head element. Therefore, the following source code would be the most basic polyglot markup document.

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
  <head>
    <title></title>
  </head>
  <body>
  </body>
</html>
		

Whenever it uses a tr element, polyglot markup always wraps the tr element inside a tbody, thead, or tfoot element. In HTML, if a group of one or more adjacent tr elements are not explictly wrapped inside a tbody, thead, or tfoot element, the HTML parser creates and wraps a new tbody element around the tr elements. XML parsers do not create the tbody element, thus offering the potential for creating different DOMs.

Correct:

<table>
<tbody>
<tr>...
Incorrect:
<table>
<tr>...

Whenever it uses col elements within a table element, polyglot markup explicitly uses a colgroup element surrounding groups of the col elements. In HTML, if a group of one or more adjacent col elements are not explicitly wrapped inside a colgroup element, the HTML parser creates and wraps a new colgroup element around the col elements. XML parsers do not create the colgroup element, thus offering the potential for creating different DOMs.

Correct:

<table>
<colgroup>
<col>...
Incorrect:
<table>
<col>...

Elements that Cannot Be Used in Polyglot Markup

Polyglot markup does not use the noscript element, because the noscript element cannot be used in XML documents. [[!HTML5]]

Case-Sensitivity

The following guidelines apply to any usage of element names, attribute names, or attribute values in markup, script, or CSS. Polyglot markup uses lower case letters for all ASCII letters. For non-ASCII letters—such as Greek, Cyrillic, or non-ASCII Latin letters—polyglot markup respects case sensitivity as it is called for.

Element Names

Polyglot markup uses the correct case for element names.

  • Polyglot markup uses lowercase letters for all HTML element names.
  • Polyglot markup uses lowercase letters for all MathML element names.
  • Polyglot markup uses lowercase letters for all SVG element names except the following, for which polyglot markup uses mixed case:
    • altGlyph
    • altGlyphDef
    • altGlyphItem
    • animateColor
    • animateMotion
    • animateTransform
    • clipPath
    • feBlend
    • feColorMatrix
    • feComponentTransfer
    • feComposite
    • feConvolveMatrix
    • feDiffuseLighting
    • feDisplacementMap
    • feDistantLight
    • feFlood
    • feFuncA
    • feFuncB
    • feFuncG
    • feFuncR
    • feGaussianBlur
    • feImage
    • feMerge
    • feMergeNode
    • feMorphology
    • feOffset
    • fePointLight
    • feSpecularLighting
    • feSpotLight
    • feTile
    • feTurbulence
    • foreignObject
    • glyphRef
    • linearGradient
    • radialGradient
    • textPath

Attribute Names

Polyglot markup uses the correct case for attribute names.

  • Polyglot markup uses lowercase letters in attribute names for all HTML elements.
  • Polyglot markup uses lowercase letters in attribute names for all MathML elements except the lowercase definitionurl, which polyglot markup changes to the mixed case definitionURL.
  • Polyglot markup uses lowercase letters in attribute names for all SVG elements except the following, for which polyglot markup uses mixed case:
    • attributeName
    • attributeType
    • baseFrequency
    • baseProfile
    • calcMode
    • clipPathUnits
    • contentScriptType
    • contentStyleType
    • diffuseConstant
    • edgeMode
    • externalResourcesRequired
    • filterRes
    • filterUnits
    • glyphRef
    • gradientTransform
    • gradientUnits
    • kernelMatrix
    • kernelUnitLength
    • keyPoints
    • keySplines
    • keyTimes
    • lengthAdjust
    • limitingConeAngle
    • markerHeight
    • markerUnits
    • markerWidth
    • maskContentUnits
    • maskUnits
    • numOctaves
    • pathLength
    • patternContentUnits
    • patternTransform
    • patternUnits
    • pointsAtX
    • pointsAtY
    • pointsAtZ
    • preserveAlpha
    • preserveAspectRatio
    • primitiveUnits
    • refX
    • refY
    • repeatCount
    • repeatDur
    • requiredExtensions
    • requiredFeatures
    • specularConstant
    • specularExponent
    • spreadMethod
    • startOffset
    • stdDeviation
    • stitchTiles
    • surfaceScale
    • systemLanguage
    • tableValues
    • targetX
    • targetY
    • textLength
    • viewBox
    • viewTarget
    • xChannelSelector
    • yChannelSelector
    • zoomAndPan

Attribute Values

For characters in attribute values, polyglot markup maintains case consistency between markup, DOM APIs, and CSS when these attributes are used on HTML elements.

Polyglot markup maintains case consistency for values on the following attributes, which occur on MIME types, language tags, charsets, booleans, media queries, and keywords. Though not required, an easy way to maintain case-consistency is to use only lower case values for these attributes. Polyglot markup maintains case consistency for these values because, for the purpose of selector matching, attribute values in XML are all treated case sensitively; however, HTML treats the values of these attributes as case insensitive (See 4.14.1 Case-sensitivity, in the HTML5 specification). [[!HTML5]]

  • accept
  • accept-charset
  • charset
  • checked
  • defer
  • dir
  • direction
  • disabled
  • enctype
  • hreflang
  • http-equiv
  • lang
  • media
  • method
  • multiple
  • readonly
  • rel (for values that do not contain a colon)
  • scope
  • selected
  • shape
  • target (keywords only; browsing context names are case-sensitive)
  • type (on a, link, object, script, or style elements)
  • type (on input)

Note that other specifications, such as RDFa, may place additional restrictions on the allowed values of certain attributes.

Void Elements

Polyglot markup uses only the elements in the following list as void elements.

Polyglot markup uses the minimized tag syntax for void elements, e.g. <br/>, rather than the alternative syntax <br></br>.

Given an empty instance of an element whose content model is not EMPTY (for example, an empty title or paragraph) polyglot markup does not use the minimized form (e.g. the document uses <p></p> and not <p />).

Note that MathML and SVG elements may be either self-closing or contain content.

Elements with Special Considerations

The following elements or their considerations require exceptions to the general rules for polyglot markup.

HTTP Headers and http-equiv Declarations

Content-Language

The HTTP Content-Language: header warrants special discussion in polyglot markup.

HTTP header: Content-language: ru
			

Whenever there is an HTTP Content-Language: header (whose value is no more and no less than exactly one language tag), polyglot markup declares both the lang and the xml:lang attributes on the root element. For more information, see Language Attributes.

As a general practice and for the sake of expediency and simplicity, polyglot markup may always include both the xml:lang as well as the lang attributes on the root element.

Content-Type

The HTTP Content-Type: header has no extra rules or restrictions, whereas polyglot markup does not use the http-equiv="Content-Type" declaration on the meta element. For more specific information about using the HTTP Content-Type: header, see Specifying a Document's Character Encoding.

Newlines in textarea and pre Elements

When polyglot markup uses either a textarea or pre element, the text within the element does not begin with a newline.

Attributes

Polyglot markup surrounds all attribute values with quotation marks. Polyglot markup surrounds attribute values with either single quotation marks or with double quotation marks.

Polyglot markup does not use directly typed newline characters within an attribute.

Within an attribute's value, polyglot markup represents tabs, line feeds, and carriage returns as numeric character references rather than by using literal characters. For example, within an attribute's value, polyglot markup uses &#x9; for a tab rather than the literal character '\t'. This is because of attribute-value normalization in XML [[!XML10]]. The following example uses numeric character references (escaped characters) for the line feed, tab, and less-than characters within a srcdoc attribute.

<iframe srcdoc="&lt;p>Hello &#x0A; &#x09; world!&lt;/p>" src="demo_iframe_srcdoc.htm"></iframe>

Because of attribute-value normalization in XML [[!XML10]], polyglot markup does not use newline characters within an attribute. Practically speaking, for source code with newlines within attributes, DOMs generated via XML and HTML will be different; however, whitespace differences have no behavioral impact on the page unless:

Note that directly typed newline characters are overtly not allowed in any attribute containing a URI.

See also Attribute Values.

Disallowed Attributes

The following attributes are not allowed in polyglot markup. These attributes have effects in documents parsed as XML but do not have effects in documents parsed as text/html. The HTML5 spec therefore defines them as invalid in text/html documents. [[!HTML5]]

Note that the xml:space and xml:base attributes are allowed on SVG and MathML elements.

Language Attributes

When specifying the language mapping of an element, polyglot markup uses both the lang and xml:lang attributes. Neither attribute is to be used without the other, and polyglot markup maintains identical values for both lang and xml:lang.

Polyglot markup uses the language attributes in the html element to set the default language for the document overtly. Although HTML5 sets the language of the root element via a fallback language mechanism, this mechanism is not required to work in XML.

HTML5 activates the fallback language mechanism whenever the root element lacks language attributes. For the mechanism to actually set a fallback language, however, it has to locate either an http-equiv="Content-Language" declaration on the meta element or an HTTP Content-Language: header, either of whose content value is no more and no less than exactly one language tag. Note that although the mechanism can locate either the meta element or the header, the meta element is considered first. For more information about determining language in HTML5, see the language determination rules. [[!HTML5]].

Attributes with Special Considerations

The following attributes or their considerations require exceptions to the general rules for polyglot markup.

The id Attribute

Polyglot markup does not contain any space characters within the value of an id attribute. This is because values for the id attribute may not contain space characters in HTML5. [[!HTML5]]

Attributes Styled Using CSS Namespaces

The prefixed attributes, such as xml:lang="", are "namespaced" within XHTML, SVG and MathML. Thus, they can be styled via CSS3 namespaces. [[!CSS3NAMESPACE]] However, for the HTML serialization, xml:lang would then not have the xml namespace effect. A style such as the following is valid in XHTML, SVG, and MathML, it does not work in HTML and is therefore not used in polyglot markup.

<style type="text/css">
@namespace xml   "http://www.w3.org/XML/1998/namespace";
*[xml|lang]{background:lime;}
</style>
		

Named Entity References

Polyglot markup uses only the following named entity references:

For entities beyond the previous list, polyglot markup uses character references. For example, polyglot markup uses &#xA0; instead of &nbsp;. Note that polyglot markup may use decimal values for escape characters (such as &#160; in the previous example); however, the Character Model for the World Wide Web recommends that content SHOULD use the hexadecimal form of character escapes rather than the decimal form when both are available. [[!CHARMOD]]

Polyglot markup always uses character references for the less than sign (<) and ampersand (&) when they are used as characters, except when those characters appear inside a CDATA section.

Script and Style

Polyglot markup includes script and style commands by linking to external files rather than including them in-line. Polyglot markup does not link to an external stylesheet by using the xml-stylesheet processing instruction. See also Processing Instructions and the XML Declaration.

The following examples show how polyglot markup includes external script and style, respectively:

<script src="external.js"></script>
<link rel="stylesheet" href="external.css"/>

Although document.write() and document.writeln() are valid in an HTML document, neither function may be used in XHTML. Therefore, neither is used in polyglot markup. Instead, use the innerHTML property for both HTML and XHTML. Note that the innerHTML property takes a string. XML parsers parse the string as XML in XHTML. HTML parsers parse the string as HTML in HTML. Because of the difference in parsing, if you send the parser content that does not follow the rules for polyglot markup the results will differ for a DOM create with an XML parser and one created with an HTML parser.

Ambiguous Strings

Except for noted exceptions (such as xml:lang="foo"), polyglot markup does not use ambiguous strings. In polyglot markup, ambiguous strings are those strings that XML interprets differently from HTML and vice-versa. Therefore, for the content of script and style tags, polyglot markup does not use the following strings:

String Notes
< XML interprets the less than symbol as the commencement of a tag, comment, or CDATA block, even if the symbol occurs within script or style tags.
& XML interprets the ampersand as the commencement of a reference or entity, even if the symbol occurs within script or style tags. As a consequence, polyglot markup does not contain script or style elements that contain HTML entities, XML entities, or character references.
]]> XML interprets this string as the end of a CDATA block.

The following example is polyglot markup because there are no ambiguous strings within the script tag.

<script>document.body.appendChild(document.createElement("div"));</script>

A workaround for using ambiguous strings is to include the properly escaped characters inside the src attribute of style or script tags.

Comments in Polyglot Markup

Polyglot markup does not begin a comment with either ">" or "->".

Example Document

The following example code acts as polyglot markup and validates as either XHTML or as HTML. You can view the page live served as HTML, at http://dev.w3.org/html5/html-xhtml-author-guide/SamplePage.html and the same bytes served as XHTML, at http://dev.w3.org/html5/html-xhtml-author-guide/SamplePage.xhtml.

The example document is served as 'text/html'. Some legacy user agents do not support SVG in when served up as 'text/html' as it is in this example. The example page could also be served as 'application/xhtml+xml' instead, with the file extension .html, maintaining adherence to Polyglot markup and enabling the rendering of the SVG.

<!DOCTYPE html>

<html id="SampleDoc" xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">

  <head>
    <title>A Sample Page Using Polglot Markup</title>
    <meta charset='utf-8' />
	<!-- The link element is self-closing as described in Section 6.4 Void Elements -->
	<!-- Style commands are included by linking to an external file rather than including them in-line, 
	  as described in Section 9. Script and Style -->
	<link type="text/css" rel="stylesheet" href="Sample.css"/>
  </head>

  <body>
<nav><p><strong>NB:</strong> These bytes are available served as <a href="SamplePage.xhtml">XHTML</a> and as <a href="SamplePage.html">HTML</a></p></nav>

    <h1>Sample Page Using Polyglot Markup</h1>
    <p>
      The source code for <a href="#SampleDoc">this document</a> uses <dfn id="sampleDef">polyglot markup</dfn>, 
      a document that is a stream of bytes that parses into identical document trees 
      (with the exception of the xmlns attribute on the root element) when processed as HTML and when processed as XML.
      The source code for this document also contains additional comments about the use of 
      <a href="#sampleDef">polyglot markup</a>.
    </p>

    <h2>Foreign Elements</h2>
    <p>
      The following shapes use SVG elements.
      <a href="#sampleDef">Polyglot markup</a> introduces undeclared (native) default namespaces 
      for the the root SVG element (<code>svg</code>) and respects the mixed-case element names and values 
      when appropriate, as described in the sections 5.1 Element-Level Namespaces, 6.3.1 Element Names, and 6.3.3 Attribute Values.
    </p>

    <!-- <a href="#sampleDef">Polyglot markup</a> declares the xlink: namespace on the <svg> element to maintain XML-compatibility  -->
    <svg width="350" height="250" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
      <g>
        <title>Three SVG shapes</title>
        <desc>
          This SVG image contains an ellipse filled with a gradient that goes from white to blue as it moves outward from the center. 
          A yellow rectangle with a black border overlaps the ellipse in the upper-left quadrant, 
          and a red spiral on a white background overlaps the ellipse in the bottom-right quadrant. 
          The red spiral is also a link to the example code for that SVG shape.
        </desc>
        <defs>
          <!-- Note that "radialGradient" and "myGradient" respect mixed-case values. -->
          <radialGradient id="myGradient" cx="50%" cy="50%" r="50%" fx="50%" fy="50%">
            <stop offset="0%" style="stop-color:rgb(200,200,200); stop-opacity:0"/>
            <stop offset="100%" style="stop-color:rgb(0,0,255); stop-opacity:1"/>
          </radialGradient>
        </defs>
      <ellipse cx="50%" cy="50%" rx="50%" ry="42%" style="fill:url(#myGradient)"/>
      <rect x="0" y="0" width="100" height="100" style="fill: yellow; stroke: black;"/> 
      <a xlink:href="http://www.example.org/foo">
        <!--
          Note that the following attribute contains newlines which will produce a different DOM,
          but will not affect the way in which SVG functions in the least.
        -->
        <path transform="translate(60, -175)"
                 d="M153 334 C153 334 151 334 151 334 C151 339 153 344 156 344 C164 344 171 339 171 334 
                    C171 322 164 314 156 314 C142 314 131 322 131 334 C131 350 142 364 156 364 
                    C175 364 191 350 191 334 C191 311 175 294 156 294 C131 294 111 311 111 334 
                    C111 361 131 384 156 384 C186 384 211 361 211 334 C211 300 186 274 156 274"
                 style="fill:white;stroke:red;stroke-width:2"/>
        </a>
      </g>
    </svg> 		
    <h2>Void Elements</h2>
    <!-- Given an empty instance of an element whose content model is not EMPTY (in this case, an empty paragraph) 
    <a href="#sampleDef">polyglot markup</a> does not use the minimized form, as described in Section 6.4 Void Elements -->
    <p></p>
    <p>
      There is an empty <code>p</code> element before this paragraph. 
      <a href="#sampleDef">Polyglot markup</a> uses <code>&lt;p>&lt;/p></code> and not <code>&lt;p/></code>.
    </p>
    <p>
      <a href="#sampleDef">Polyglot markup</a> treats certain elements as self-closing, 
      void elements, such as the following <code>img</code> element.
    </p>
    <img height="48" width="72" alt="W3C" src="http://www.w3.org/Icons/w3c_home"/>
    <p>
      For more information, see Section 6.4 Void Elements.
    </p>


    <h2>Required Elements</h2>
    <p>
      The following table uses the required <code>tbody</code> element, as described in 
      Section 6.1 Required Elements.
    </p>
    <table>
      <tbody>
        <tr>
          <th>Column One</th>
          <th>Column Two</th>
        </tr>
        <tr>
          <td>Row 1, Column 1</td>
          <td>Row 1, Column 2</td>
        </tr>
        <tr>
          <td>Row 2, Column 1</td>
          <td>Row 2, Column 2</td>
        </tr>
        <tr>
          <td>Row 3, Column 1</td>
          <td>Row 3, Column 2</td>
        </tr>
      </tbody>
    </table>

    <p>
      The following table uses the required <code>colgroup</code> element, as described in 
      Section 6.1 Required Elements.  
    </p>
    <table>
      <colgroup>
        <col style="background-color:silver"/>
        <col style="background-color:gray"/>
        <col style="background-color:yellow"/>
      </colgroup>
      <tbody>
        <tr>
          <th>ISBN</th>
          <th>Title</th>
          <th>Price</th>
        </tr>
        <tr>
          <td>3476896</td>
          <td>My first HTML</td>
          <td>$53</td>
        </tr>
        <tr>
          <td>1234567</td>
          <td>Intermediate Polyglot</td>
          <td>$49</td>
        </tr>
      </tbody>
    </table>

    <h2>Named Entity References</h2>
    <p>
      The paragraph you now read, uses the string <code>&amp;amp;</code> for ampersands (“&amp;”) and uses,
      as described in Section 8. Named Entity References, the string <code>&amp;#xA0;</code> 
      for a non-breaking space between the following two words: <i>“<a href="#sampleDef">polyglot&#xA0;markup</a>”</i>.
    </p>
  </body>
</html>

Acknowledgements

Many thanks to Robin Berjon, David Carlisle, Daniel Glazman, Richard Ishida, Tony Ross, Sam Ruby, Jonas Sicking, Leif Halvard Silli, Henri Sivonen, Manu Sporny, and Philip Taylor. Special thanks to the W3C TAG and the W3C Internationalization (i18n) Core Working Group.