{"id":11292,"date":"2026-07-10T16:37:27","date_gmt":"2026-07-10T11:07:27","guid":{"rendered":"https:\/\/4ksamachar.com\/?p=11292"},"modified":"2026-07-10T16:37:27","modified_gmt":"2026-07-10T11:07:27","slug":"dennis-snell-see-data-cdata-rcdata-and-pcdata-oh-my","status":"publish","type":"post","link":"https:\/\/4ksamachar.com\/?p=11292","title":{"rendered":"Dennis Snell: See DATA, CDATA, RCDATA, and PCDATA oh my!"},"content":{"rendered":"<p class=\"wp-block-paragraph\">HTML and XML are markup languages based on plaintext files. This means that any given character <em>could<\/em> be part of a syntax form (a tag, a comment, a character reference, etc\u2026) <em>or<\/em> it could be representing itself the way it reads in the file literally.<\/p>\n<div class=\"wp-block-code\">\n<div class=\"cm-editor\">\n<div class=\"cm-scroller\">\n<pre>\n<code class=\"language-html\"><div class=\"cm-line\"><span class=\"tok-punctuation\">&lt;<\/span><span class=\"tok-typeName\">tag<\/span><span class=\"tok-punctuation\">&gt;<\/span><span class=\"tok-string\">&amp;middot;<\/span> Text node<span class=\"tok-punctuation\">&lt;\/<\/span><span class=\"tok-typeName\">tag<\/span><span class=\"tok-punctuation\">&gt;<\/span><\/div><\/code><\/pre>\n<\/p><\/div>\n<\/p><\/div>\n<\/div>\n<p class=\"wp-block-paragraph\">Whenever a character might be ambiguous, both languages require explicit indication of the intent of the character. In HTML this occurs via <em>escaping<\/em>, while XML allows escaping <em>or<\/em> wrapping the content in a <em>marked section<\/em>, specifically a <code>CDATA section<\/code>.<\/p>\n<div class=\"wp-block-code\">\n<div class=\"cm-editor\">\n<div class=\"cm-scroller\">\n<pre>\n<code class=\"language-xml\"><div class=\"cm-line\"><span class=\"tok-string\">&amp;lt;<\/span>tag<span class=\"tok-string\">&amp;gt;<\/span><\/div><div class=\"cm-line\"><span class=\"tok-string2\">&lt;![CDATA[&lt;tag&gt;\u00b7 Text node&lt;\/tag&gt;]]&gt;<\/span><\/div><\/code><\/pre>\n<\/p><\/div>\n<\/p><\/div>\n<\/div>\n<p class=\"wp-block-paragraph\">These terms confuse me at times, especially since <code>CDATA<\/code> and <code>CDATA sections<\/code> are distinct forms of the same content, and it\u2019s easy to conflate each term. This post is here to disambiguate the terms, their meanings, and why they exist.<\/p>\n<p class=\"wp-block-paragraph\"><a href=\"https:\/\/fluffyandflakey.blog\/tag\/wordpress\/feed\/#summary\" target=\"_blank\" rel=\"noopener\">The punchline comes at the end<\/a>, but the story is hopefully worth the read.<\/p>\n<p><span><\/span><\/p>\n<h2 class=\"wp-block-heading\">Markup and mixed content<\/h2>\n<p class=\"wp-block-paragraph\">One of the first jobs of a parser for any plaintext-oriented format is to determine if the next input character represents real text or is part of a syntax form that carries special meaning. If it\u2019s a syntax form we would call it <em>markup<\/em>, but if the characters are part of real text meant for display or rendering or reading then we call it <em>data<\/em>.<\/p>\n<p class=\"wp-block-paragraph\">Anything that is not syntax is data.<\/p>\n<p class=\"wp-block-paragraph\">The interpretation of the next character depends on the region of the document in which it\u2019s parsed. While the rules for syntax forms are complicated<sup class=\"fn\"><a href=\"https:\/\/fluffyandflakey.blog\/tag\/wordpress\/feed\/#0ba56e66-ab0f-4fbd-93d2-df22a6984fd7\" target=\"_blank\" rel=\"noopener\">1<\/a><\/sup>, this post will focus on the data forms.<\/p>\n<h3 class=\"wp-block-heading\">PCDATA \u2014 \u201cparsed character data\u201d<\/h3>\n<p class=\"is-style-plain wp-block-paragraph\"><em>May form: tags, comments, sections, character references, literal text.<\/em><\/p>\n<p class=\"wp-block-paragraph\">Characters in this region could be data or could form the start of a new markup element. It\u2019s \u201cparsed\u201d because it needs parsing before determining what it represents.<\/p>\n<p class=\"wp-block-paragraph\">The HTML specification renames this to <code>Data<\/code>, which is simpler and a bit harder to search for. In XML, however, it\u2019s used in a document-type definition (DTD). When an element may contain content \u2014 text \u2014 its data model must include <code>#PCDATA<\/code>. Otherwise the only characters allowable within that element are other elements, comments, and whitespace. XML documents are required to be valid SGML documents, so its own specification adopts the terminology from SGML\u2019s.<\/p>\n<p class=\"wp-block-paragraph\">Those who have worked with DTDs might note that <em>elements<\/em> in XML may contain <code>#PCDATA<\/code> while <em>attributes<\/em> contain <code>CDATA<\/code> instead. First of all, the <code>#<\/code> is there only to make it explicit that <code>PCDATA<\/code> is referring to the reserved keyword, rather than a <code>&lt;pcdata&gt;<\/code> element. Secondly, there\u2019s a good reason for this, which is that attributes can only contain text \u2014 they can\u2019t contain other elements of markup. If an attribute value could contain a <code>&lt;span&gt;<\/code> element, for example, then the attribute value would need to be <code>#PCDATA<\/code> instead, but this is prevented by design.<\/p>\n<p class=\"wp-block-paragraph\">PCDATA actually contains more than just literal text and elements. In addition to comments, processing instructions, and other node-like syntax, one important feature of PCDATA is the <em>character reference<\/em>. These make it possible to represent characters that would conflate with syntax (such as \u2018<code>&lt;<\/code>\u2019 \u2014 <code>&amp;lt;<\/code>) or which might be cumbersome to enter on a keyboard (such as \u2018\u00a7\u2019 \u2014 <code>&amp;sect;<\/code>). When parsing, each character in these sequences neither creates an element nor  displays as the text itself; rather, the entire sequence is parsed and translates into the character it refers to.<\/p>\n<p class=\"wp-block-paragraph\">HTML pre-specifies <a href=\"https:\/\/github.com\/w3c\/html\/blob\/master\/entities.json\" target=\"_blank\" rel=\"noopener\">a fixed set of named character references<\/a>, but any Unicode code point may be referenced by its decimal or hexadecimal numeric index. While XML also allows referencing code points by their index<sup class=\"fn\"><a href=\"https:\/\/fluffyandflakey.blog\/tag\/wordpress\/feed\/#6d3de5b9-f8a6-4f46-853b-3d407731feca\" target=\"_blank\" rel=\"noopener\">2<\/a><\/sup>, it only pre-specifies the five named characters which correspond to its main markup introducers: <code>&lt;<\/code>, <code>&gt;<\/code>, <code>&amp;<\/code>, <code>'<\/code>, and <code>\"<\/code>. In XML, any additional named character references are created through the DTD by defining <em>entities<\/em>.<\/p>\n<h3 class=\"wp-block-heading\"> CDATA \u2014 \u201ccharacter data\u201d<\/h3>\n<p class=\"wp-block-paragraph\"><em>May form: [character references], literal text.<\/em><\/p>\n<p class=\"wp-block-paragraph\">If a character isn\u2019t markup, then it\u2019s <em>character data<\/em>, which means that it\u2019s representing its literal self or it\u2019s part of a <em>character reference<\/em>. Once the parser has entered this region it will not create markup elements.<\/p>\n<p class=\"wp-block-paragraph\">CDATA is the most confusable kind of character data; this is because there are many kinds of CDATA that share the same name:<\/p>\n<ul class=\"wp-block-list\">\n<li>XML attributes may contain CDATA, where character references are decoded.<\/li>\n<li>XML CDATA sections only contain CDATA, but character references are not decoded.<\/li>\n<li>HTML <em>kind of<\/em> has the same CDATA sections, but only in <em>foreign elements<\/em> (inlined SVG and MathML elements).<\/li>\n<li>SGML elements may be declared to have a CDATA content model, in which case all content until the appropriate closing tag is to be parsed as character data, where character references are not decoded.<\/li>\n<\/ul>\n<h4 class=\"wp-block-heading\">CDATA sections contain only literal text<\/h4>\n<p class=\"wp-block-paragraph\">Many people are familiar with <code>CDATA sections<\/code>, but it took me far longer to understand them than my intuition led on. They are the vestige of SGML \u201cmarked regions\u201d which tell the parser to handle a specific range of bytes in a special way. The <code>CDATA<\/code> section is one of those, which tells the parser to <em>completely turn off until it reaches <code>]]&gt;<\/code><\/em>.<\/p>\n<div class=\"wp-block-code\">\n<div class=\"cm-editor\">\n<div class=\"cm-scroller\">\n<pre>\n<code class=\"language-xml\"><div class=\"cm-line\"><span class=\"tok-string2\">&lt;![CDATA[literal characters only in here]]&gt;<\/span><\/div><\/code><\/pre>\n<\/p><\/div>\n<\/p><\/div>\n<\/div>\n<p class=\"wp-block-paragraph\">It had other marked sections, however, which served different purposes.<\/p>\n<div class=\"wp-block-code\">\n<div class=\"cm-editor\">\n<div class=\"cm-scroller\">\n<pre>\n<code class=\"language-xml\"><div class=\"cm-line\">&lt;![IGNORE[everything in here is ignored; it doesn\u2019t exist.]]&gt;<\/div><div class=\"cm-line\">&lt;![INCLUDE[in here things <span class=\"tok-punctuation\">&lt;<\/span><span class=\"tok-typeName\">em<\/span><span class=\"tok-punctuation\">&gt;<\/span>do<span class=\"tok-punctuation\">&lt;\/<\/span><span class=\"tok-typeName\">em<\/span><span class=\"tok-punctuation\">&gt;<\/span> exist as normal.]]&gt;<\/div><div class=\"cm-line\">&lt;![RCDATA[read on to learn about RCDATA!]]&gt;<\/div><\/code><\/pre>\n<\/p><\/div>\n<\/p><\/div>\n<\/div>\n<p class=\"wp-block-paragraph\">The <code>IGNORE<\/code> and <code>INCLUDE<\/code> sections may seem strange, since SGML already has comments, and <code>INCLUDE<\/code> effectively does nothing, but the sections can be marked by replaced <em>entities<\/em>, making for conditional inclusion which can be overwritten via command-line arguments when invoking the SGML parser.<\/p>\n<div class=\"wp-block-code\">\n<div class=\"cm-editor\">\n<div class=\"cm-scroller\">\n<pre>\n<code class=\"language-xml\"><div class=\"cm-line\">&lt;!ENTITY % review-only \"IGNORE\"&gt;<\/div><div class=\"cm-line\"><\/div><div class=\"cm-line\">...<\/div><div class=\"cm-line\"><\/div><div class=\"cm-line\">&lt;![%review-only;[<\/div><div class=\"cm-line\"><span class=\"tok-punctuation\">&lt;<\/span><span class=\"tok-typeName\">aside<\/span><span class=\"tok-punctuation\">&gt;<\/span><\/div><div class=\"cm-line\">Add `-Dreview-only=INCLUDE` when building drafts.<\/div><div class=\"cm-line\">This note won\u2019t appear otherwise.<\/div><div class=\"cm-line\"><span class=\"tok-punctuation\">&lt;\/<\/span><span class=\"tok-typeName\">aside<\/span><span class=\"tok-punctuation\">&gt;<\/span><\/div><div class=\"cm-line\">]]&gt;<\/div><\/code><\/pre>\n<\/p><\/div>\n<\/p><\/div>\n<\/div>\n<p class=\"wp-block-paragraph\"><a href=\"https:\/\/www.w3.org\/XML\/9712-reports.html#:~:text=XML%20will%20have%20CDATA%20marked%20sections\" target=\"_blank\" rel=\"noopener\">XML only retained CDATA sections<\/a> from SGML, while HTML never included them. They are useful because they are so easy to parse. All characters inside of them are to be treated as literal text, up until the first occurrence of the terminating <code>]]&gt;<\/code>. Unlike elements, the marked sections do not nest.<\/p>\n<h4 class=\"wp-block-heading\">There are no CDATA sections in HTML<\/h4>\n<p class=\"wp-block-paragraph\">The Internet is full of discussions about the use of CDATA sections in HTML, but there are no such things, mostly. HTML itself is an amalgam of pure HTML and embedded SVG and MathML. Content inside of those <em>embedded<\/em> SVG and MathML elements is parsed differently, and within this \u201cforeign content\u201d there <em>are<\/em> <code>CDATA section<\/code> nodes.<\/p>\n<p class=\"wp-block-paragraph\">When something which <em>look like a CDATA section<\/em> appears in an HTML document, it\u2019s transformed into a \u201cbogus\u201d HTML comment and considered a snippet of malformed markup. To make things more confusing, the parsing rules differ inside an HTML document for these regions depending on whether they are found within HTML elements or foreign elements.<\/p>\n<ul class=\"wp-block-list\">\n<li>When a real CDATA section appears within SVG and MathML, it parses as in XML or SGML \u2014 everything is  literal text <em>until<\/em> the nearest <code>]]&gt;<\/code>.<\/li>\n<li>When a malformed CDATA look-alike appears in an HTML element, it gets special treatment \u2014 the parser only turns off until the nearest <code>&gt;<\/code>. This means that these sections end even without a closing <code>]]&gt;<\/code>, and when they do, all of their contained content disappears from the page.<\/li>\n<\/ul>\n<p class=\"wp-block-paragraph\">That small difference confuses na\u00efve parsers and is a regular source of bugs.<\/p>\n<div class=\"wp-block-code\">\n<div class=\"cm-editor\">\n<div class=\"cm-scroller\">\n<pre>\n<code class=\"language-html\"><div class=\"cm-line\"><span class=\"tok-punctuation\">&lt;<\/span><span class=\"tok-typeName\">div<\/span><span class=\"tok-punctuation\">&gt;<\/span>&lt;![CDATA[There are no tags in here.]]&gt;<span class=\"tok-punctuation\">&lt;\/<\/span><span class=\"tok-typeName\">div<\/span><span class=\"tok-punctuation\">&gt;<\/span><\/div><div class=\"cm-line\"><span class=\"tok-punctuation\">&lt;<\/span><span class=\"tok-typeName\">svg<\/span><span class=\"tok-punctuation\">&gt;<\/span><span class=\"tok-punctuation\">&lt;<\/span><span class=\"tok-typeName\">text<\/span><span class=\"tok-punctuation\">&gt;<\/span>&lt;![CDATA[<span class=\"tok-punctuation\">&lt;<\/span><span class=\"tok-typeName\">none<\/span><span class=\"tok-punctuation\">&gt;<\/span> here either.]]&gt;<span class=\"tok-punctuation\">&lt;\/<\/span><span class=\"tok-typeName\">text<\/span><span class=\"tok-punctuation\">&gt;<\/span><span class=\"tok-punctuation\">&lt;\/<\/span><span class=\"tok-typeName\">svg<\/span><span class=\"tok-punctuation\">&gt;<\/span><\/div><div class=\"cm-line\"><span class=\"tok-punctuation\">&lt;<\/span><span class=\"tok-typeName\">div<\/span><span class=\"tok-punctuation\">&gt;<\/span>&lt;![CDATA[But there <span class=\"tok-punctuation\">&lt;<\/span><span class=\"tok-typeName\">em<\/span><span class=\"tok-punctuation\">&gt;<\/span>are<span class=\"tok-punctuation\">&lt;\/<\/span><span class=\"tok-typeName\">em<\/span><span class=\"tok-punctuation\">&gt;<\/span> tags in here]]&gt;<span class=\"tok-punctuation\">&lt;\/<\/span><span class=\"tok-typeName\">div<\/span><span class=\"tok-punctuation\">&gt;<\/span><\/div><div class=\"cm-line\">     the section ends here \u256f   \u2570 start of a real end tag<\/div><div class=\"cm-line\"><\/div><div class=\"cm-line\">The following is the equivalent markup to the third line.<\/div><div class=\"cm-line\"><span class=\"tok-punctuation\">&lt;<\/span><span class=\"tok-typeName\">div<\/span><span class=\"tok-punctuation\">&gt;<\/span><span class=\"tok-comment\">&lt;!--But there &lt;em--&gt;<\/span>are<span class=\"tok-punctuation\">&lt;\/<\/span><span class=\"tok-typeName tok-invalid\">em<\/span><span class=\"tok-punctuation\">&gt;<\/span> tags in here]]&gt;<span class=\"tok-punctuation\">&lt;\/<\/span><span class=\"tok-typeName\">div<\/span><span class=\"tok-punctuation\">&gt;<\/span><\/div><\/code><\/pre>\n<\/p><\/div>\n<\/p><\/div>\n<\/div>\n<h4 class=\"wp-block-heading\">SGML contains CDATA regions outside of marked CDATA sections<\/h4>\n<p class=\"wp-block-paragraph\">SGML made it possible to define more kinds of content than XML does for a given element. For example, an element in SGML can be declared to have a CDATA content model, in which case the element itself behaves like a CDATA section. All characters after the opening tag are treated as literal text until the parser finds the nearest appropriate end tag<sup class=\"fn\"><a href=\"https:\/\/fluffyandflakey.blog\/tag\/wordpress\/feed\/#2d0aee27-cf77-4b19-a4c5-3b1cc4192c53\" target=\"_blank\" rel=\"noopener\">3<\/a><\/sup>. XML rejected this ability because it increases the complexity of the parser and requires that every document also contains a full DTD when parsing. For example, if an element were declared to have CDATA content, then <code>a &lt;at&gt; b<\/code> would represent that literal string; on the other hand, if it were declared like any other normal element, it would have three children: \u201c<code>a <\/code>\u201d, the <code>&lt;at&gt;<\/code> opening tag, and \u201c<code> b<\/code>\u201d.<\/p>\n<div class=\"wp-block-code\">\n<div class=\"cm-editor\">\n<div class=\"cm-scroller\">\n<pre>\n<code class=\"language-xml\"><div class=\"cm-line\">&lt;!ELEMENT verbatim - - CDATA&gt;<\/div><div class=\"cm-line\"><\/div><div class=\"cm-line\">...<\/div><div class=\"cm-line\"><\/div><div class=\"cm-line\"><span class=\"tok-punctuation\">&lt;<\/span><span class=\"tok-typeName\">verbatim<\/span><span class=\"tok-punctuation\">&gt;<\/span><\/div><div class=\"cm-line\">There are <span class=\"tok-punctuation\">&lt;<\/span><span class=\"tok-typeName\">no<\/span><span class=\"tok-punctuation\">&gt;<\/span> tags in here, because this is CDATA,<\/div><div class=\"cm-line\">but you wouldn\u2019t know without reading the DTD,<\/div><div class=\"cm-line\">overcomplicating the demands on the parser.<\/div><div class=\"cm-line\"><span class=\"tok-punctuation\">&lt;\/<\/span><span class=\"tok-typeName\">verbatim<\/span><span class=\"tok-punctuation\">&gt;<\/span><\/div><\/code><\/pre>\n<\/p><\/div>\n<\/p><\/div>\n<\/div>\n<p class=\"wp-block-paragraph\">These kinds of elements do exist in HTML, though a few were modified when HTML5 was standardized in 2008. Inside of the elements, the parser essentially turns off, which makes them easy to parse and can help avoid the need to extensively escape content. These elements are, of course, <code>&lt;script&gt;<\/code> and <code>&lt;style&gt;<\/code><sup class=\"fn\"><a href=\"https:\/\/fluffyandflakey.blog\/tag\/wordpress\/feed\/#68152c30-bf36-4e5b-a7df-3f0610daeadb\" target=\"_blank\" rel=\"noopener\">4<\/a><\/sup>.<\/p>\n<p class=\"wp-block-paragraph\">Were it not for the CDATA declared content model, every angle bracket and ampersand would have to be escaped in included JavaScript and CSS. In XHTML this was required, because it had no CDATA declared content model (since it was XML)<sup class=\"fn\"><a href=\"https:\/\/fluffyandflakey.blog\/tag\/wordpress\/feed\/#21aeab38-6e1f-4700-a8f4-27c96ebe0c3b\" target=\"_blank\" rel=\"noopener\">5<\/a><\/sup>.<\/p>\n<h4 class=\"wp-block-heading\">All text in XML is CDATA<\/h4>\n<p class=\"wp-block-paragraph\">Herein lies the most-confusing aspect of discussing CDATA \u2014 XML contains CDATA sections as well as <em>CDATA<\/em> as normal text. After parsing there is no distinction between <code>&amp;lt;tag&amp;gt;<\/code> and <code>&lt;![CDATA[&lt;tag&gt;]]&gt;<\/code> in the parsed content.<\/p>\n<p class=\"wp-block-paragraph\">Many XML generators (or serializers) provide two mechanisms for creating text content: one wraps text in a <code>CDATA section<\/code> and leaves the text as it came (apart from avoiding including the terminating sequence); the other escapes syntax characters instead. While there are times where it would be appropriate to intentionally pick one over the other, a good library design would at least offer a third mechanism (if not <em>only<\/em> providing this third mechanism) which simply produces <em>CDATA<\/em>, itself determining when to wrap and when to escape<sup class=\"fn\"><a href=\"https:\/\/fluffyandflakey.blog\/tag\/wordpress\/feed\/#6e56b2ce-8156-4bf5-a4d3-d297a401c1a3\" target=\"_blank\" rel=\"noopener\">6<\/a><\/sup>, and whether or not to produce chunks of wrapped text interspersed with chunks of escaped text.<\/p>\n<p class=\"wp-block-paragraph\">The real difference between these two kinds of CDATA is purely presentational in the source document, as the XML snippet below only contains one text node, not two. <em>Creating CDATA does not imply creating a <code>CDATA section<\/code>!<\/em><\/p>\n<div class=\"wp-block-code\">\n<div class=\"cm-editor\">\n<div class=\"cm-scroller\">\n<pre>\n<code class=\"language-xml\"><div class=\"cm-line\"><span class=\"tok-punctuation\">&lt;<\/span><span class=\"tok-typeName\">rule<\/span><span class=\"tok-punctuation\">&gt;<\/span><span class=\"tok-string2\">&lt;![CDATA[#X13&lt;d&amp;r&gt;]]&gt;<\/span> (<span class=\"tok-string\">&amp;pp;<\/span>4 <span class=\"tok-string\">&amp;ss;<\/span>3.11)<span class=\"tok-punctuation\">&lt;\/<\/span><span class=\"tok-typeName\">rule<\/span><span class=\"tok-punctuation\">&gt;<\/span><\/div><\/code><\/pre>\n<\/p><\/div>\n<\/p><\/div>\n<\/div>\n<h3 class=\"wp-block-heading\">RCDATA \u2014 \u201creplaceable character data\u201d<\/h3>\n<p class=\"wp-block-paragraph\"><em>May form: character references, literal text.<\/em><\/p>\n<p class=\"wp-block-paragraph\">There\u2019s one more confusing designation for characters in the HTML and XML input streams: <em>RCDATA<\/em>. RCDATA is almost identical to CDATA, except that in contexts where CDATA does not decode character references and entities, RCDATA <em>will<\/em> decode them <em>into<\/em> CDATA. This is confusing, because in the context of an XML attribute, the <code>CDATA<\/code> designation in a DTD automatically implies that character references are decoded, unlike the <code>CDATA<\/code> sections in <em>content<\/em>.<\/p>\n<p class=\"wp-block-paragraph\">To this end there are no RCDATA attributes, since character references are always decoded inside attribute values. The RCDATA declaration is like the SGML CDATA content declaration: all characters following the opening tag for this element will be treated as text until the nearest matching closing tag (the difference being only that character references are recognized and decoded).<\/p>\n<p class=\"wp-block-paragraph\">It\u2019s worth remembering that XML rejected the CDATA content type because of how it complicates parsing, and it also rejected the RCDATA type. On the other hand, RCDATA was incorporated into HTML, but statically so. HTML has no configurable DTD, but in its specification two elements contain RCDATA content:<\/p>\n<ul class=\"wp-block-list\">\n<li><code>TITLE<\/code><\/li>\n<li><code>TEXTAREA<\/code><\/li>\n<\/ul>\n<p class=\"wp-block-paragraph\">While it\u2019s easy to comprehend the way that <code>&lt;textarea&gt;<\/code> works, and that\u2019s probably because we are used to entering text into one on a web page, the behavior of <code>&lt;title&gt;<\/code> is consistently confused in all manner of programming languages, platforms, and HTML-parsing code.<\/p>\n<p class=\"wp-block-paragraph\">The TITLE element <em>only<\/em> contains character data \u2014 it cannot contain other markup. The parsing is among the easiest sections of an HTML document to parse: once the <code>&lt;title&gt;<\/code> opening tag is detected, the parser can capture everything until the nearest <code>&lt;\/title&gt;<\/code> closing tag. Everything it captured is literal text, after decoding character references.<\/p>\n<div class=\"wp-block-code\">\n<div class=\"cm-editor\">\n<div class=\"cm-scroller\">\n<pre>\n<code class=\"language-html\"><div class=\"cm-line\"><span class=\"tok-comment\">&lt;!-- the title is \"&lt;title&gt;\" --&gt;<\/span><\/div><div class=\"cm-line\"><span class=\"tok-punctuation\">&lt;<\/span><span class=\"tok-typeName\">title<\/span><span class=\"tok-punctuation\">&gt;<\/span><span class=\"tok-punctuation\">&lt;<\/span><span class=\"tok-typeName\">title<\/span><span class=\"tok-punctuation\">&gt;<\/span><span class=\"tok-punctuation\">&lt;\/<\/span><span class=\"tok-typeName\">title<\/span><span class=\"tok-punctuation\">&gt;<\/span><\/div><div class=\"cm-line\"><\/div><div class=\"cm-line\"><span class=\"tok-comment\">&lt;!-- equivalent HTML --&gt;<\/span><\/div><div class=\"cm-line\"><span class=\"tok-punctuation\">&lt;<\/span><span class=\"tok-typeName\">title<\/span><span class=\"tok-punctuation\">&gt;<\/span><span class=\"tok-string\">&amp;lt;<\/span>title<span class=\"tok-string\">&amp;gt;<\/span><span class=\"tok-punctuation\">&lt;\/<\/span><span class=\"tok-typeName\">title<\/span><span class=\"tok-punctuation\">&gt;<\/span><\/div><\/code><\/pre>\n<\/p><\/div>\n<\/p><\/div>\n<\/div>\n<p class=\"wp-block-paragraph\">This complicates content management systems like WordPress which allow posts to have HTML in their <em>post titles<\/em>, because a page can show richly-formatted article titles which cannot be represented in the browser tab\u2019s label, and care must be taken to extract the plaintext content from that HTML before display in those contexts.<\/p>\n<h2 class=\"wp-block-heading\">Coda<\/h2>\n<p class=\"wp-block-paragraph\">HTML and XML both speak about different kinds of characters in their source documents and content models, which traces from the complicated ways that SGML documents could be constructed. SGML\u2019s complexity almost always stems from the central idea that computers should do extra work to remove the hassle for humans to enter structured content in plaintext documents.<\/p>\n<p class=\"wp-block-paragraph\">HTML, inspired by SGML, adopted some of the names and mechanisms for parsing those regions of text in distinct ways, but codified a single parsing standard independent of SGML. When XML was later developed, it was meant to form a simplified subset of SGML. This subset flipped the tradeoffs, leaning on humans performing extra work to remove the hassle for computers to parse structure in plaintext documents. For these text forms, this meant rejecting a few of the constructs while retaining others.<\/p>\n<p class=\"wp-block-paragraph\">This is also another demonstration of how <em>balanced tags are not enough<\/em> to have well-behaved HTML with a na\u00efve parser. A well-formed XML document <a href=\"https:\/\/www.ch.imperial.ac.uk\/rzepa\/talks\/pmr11\/xml-dev\/9708\/0152.html\" target=\"_blank\" rel=\"noopener\">may be parsed with a terse PERL script and regular expression<\/a>, but HTML relies heavily on the context in which characters are found. Any HTML parser <em>must<\/em> know the special rules for each kind of element\u2019s content model.<\/p>\n<h3 class=\"wp-block-heading\">In summary<\/h3>\n<ul class=\"wp-block-list\">\n<li>When it\u2019s unclear whether a character forms text or markup, that is PCDATA. Once parsed, there is no PCDATA anymore; it\u2019s either a form of DATA or MARKUP.<\/li>\n<li>All text nodes in HTML are \u201cDATA.\u201d<\/li>\n<li>\u201cCDATA\u201d just means \u201ccharacter data\u201d and means that after parsing, the content is text. It does not indicate whether character references are to be decoded or not; that comes from the region in the document, based on its context.<\/li>\n<li>There are no CDATA sections in HTML<sup class=\"fn\"><a href=\"https:\/\/fluffyandflakey.blog\/tag\/wordpress\/feed\/#31e75dae-1847-44df-92e1-8ae5756eeec6\" target=\"_blank\" rel=\"noopener\">7<\/a><\/sup>.<\/li>\n<li>All text nodes in XML are CDATA, but only after being parsed.<\/li>\n<li>CDATA sections offer a convenient way to avoid escaping, but are indistinguishable from the equivalent escaped text.<\/li>\n<li>HTML contains two special RCDATA elements which <em>only<\/em> and <em>always<\/em> contain a single text node child: <code>&lt;title&gt;<\/code> and <code>&lt;textarea&gt;<\/code>. Everything until the closing tag will be parsed as text, even if it looks like markup.<\/li>\n<\/ul>\n<p class=\"wp-block-paragraph\">This post is already long and still over-simplifies the picture. SGML is a rich and robust specification and includes <code>NDATA<\/code> and <code>SDATA<\/code>, HTML includes a <em>latching<\/em> <code>PLAINTEXT<\/code> parsing mode in which <em>the rest of the entire document is parsed as literal character data<\/em>, and there are other surprising goodies in how entities interact with the character mode.<\/p>\n<p class=\"wp-block-paragraph\">Thanks for making it through to the end, or jumping directly here if you couldn\u2019t wait.<\/p>\n<ol class=\"wp-block-footnotes\">\n<li>As an example, each part of a tag \u2014 its name, attribute names, attribute values \u2014 carries its own parsing rules. The same is true for comments, DOCTYPE declarations, and every other syntax form. <a href=\"https:\/\/fluffyandflakey.blog\/tag\/wordpress\/feed\/#0ba56e66-ab0f-4fbd-93d2-df22a6984fd7-link\" target=\"_blank\" rel=\"noopener\"><img decoding=\"async\" alt=\"\u21a9\" class=\"wp-smiley\" src=\"https:\/\/s.w.org\/images\/core\/emoji\/17.0.2\/72x72\/21a9.png\">\ufe0e<\/a><\/li>\n<li>XML only allows character references to the characters in its \u201ccharacter set,\u201d which is <em>almost<\/em> all Unicode code points, but excludes some control characters and U+FFFE and U+FFFF. <a href=\"https:\/\/fluffyandflakey.blog\/tag\/wordpress\/feed\/#6d3de5b9-f8a6-4f46-853b-3d407731feca-link\" target=\"_blank\" rel=\"noopener\"><img decoding=\"async\" alt=\"\u21a9\" class=\"wp-smiley\" src=\"https:\/\/s.w.org\/images\/core\/emoji\/17.0.2\/72x72\/21a9.png\">\ufe0e<\/a><\/li>\n<li>Because SGML was designed to minimize the amount of necessary syntax, it\u2019s not necessary to have a full end tag for an open element, but that\u2019s a simple-enough model to understand the concept. <a href=\"https:\/\/fluffyandflakey.blog\/tag\/wordpress\/feed\/#2d0aee27-cf77-4b19-a4c5-3b1cc4192c53-link\" target=\"_blank\" rel=\"noopener\"><img decoding=\"async\" alt=\"\u21a9\" class=\"wp-smiley\" src=\"https:\/\/s.w.org\/images\/core\/emoji\/17.0.2\/72x72\/21a9.png\">\ufe0e<\/a><\/li>\n<li>The <code>&lt;style&gt;<\/code> element is straightforward, but <a href=\"https:\/\/sirre.al\/2025\/08\/06\/safe-json-in-script-tags-how-not-to-break-a-site\/\" target=\"_blank\" rel=\"noopener\">the <code>&lt;script&gt;<\/code> element has its own complicated modification<\/a> of the CDATA content model. It\u2019s mostly CDATA, but makes it possible to escape the closing tag so that very old pages won\u2019t break. HTML also applies this parsing mode for the <code>&lt;iframe&gt;<\/code>, <code>&lt;noembed&gt;<\/code>, <code>&lt;noframes&gt;<\/code>, and <code>&lt;noscript&gt;<\/code> elements (as well as for the deprecated <code>&lt;xmp&gt;<\/code> element), but these nominally should have no content inside of them (or shouldn\u2019t be used); applying the CDATA content model prevents creating other elements as their children. <a href=\"https:\/\/fluffyandflakey.blog\/tag\/wordpress\/feed\/#68152c30-bf36-4e5b-a7df-3f0610daeadb-link\" target=\"_blank\" rel=\"noopener\"><img decoding=\"async\" alt=\"\u21a9\" class=\"wp-smiley\" src=\"https:\/\/s.w.org\/images\/core\/emoji\/17.0.2\/72x72\/21a9.png\">\ufe0e<\/a><\/li>\n<li>Frustratingly, in XHTML one <em>must<\/em> escape JavaScript and CSS in the page to avoid parsing failure, while in HTML one <em>must not<\/em>. This alone makes for a complicated stage in any reliable HTML\/XHTML converter. <a href=\"https:\/\/fluffyandflakey.blog\/tag\/wordpress\/feed\/#21aeab38-6e1f-4700-a8f4-27c96ebe0c3b-link\" target=\"_blank\" rel=\"noopener\"><img decoding=\"async\" alt=\"\u21a9\" class=\"wp-smiley\" src=\"https:\/\/s.w.org\/images\/core\/emoji\/17.0.2\/72x72\/21a9.png\">\ufe0e<\/a><\/li>\n<li>Wrapping a language like HTML inside a CDATA section is a convenient way to represent the HTML visually and retain the ability to easily modify it, but entities present a problem. The serializer must either pre-translate the entity into its resolved character content, losing the macro-like behavior and its name; or leave the entity in place, thus nullifying it because it will not be recognized as an entity on parse. However, in such a situation, a serializer is free to terminate the CDATA section, append the entity, and open a new one to continue. <a href=\"https:\/\/fluffyandflakey.blog\/tag\/wordpress\/feed\/#6e56b2ce-8156-4bf5-a4d3-d297a401c1a3-link\" target=\"_blank\" rel=\"noopener\"><img decoding=\"async\" alt=\"\u21a9\" class=\"wp-smiley\" src=\"https:\/\/s.w.org\/images\/core\/emoji\/17.0.2\/72x72\/21a9.png\">\ufe0e<\/a><\/li>\n<li>As mentioned in the discussion about CDATA, embedded SVG and MathML elements <em>can<\/em> contain CDATA sections, but these are not technically HTML elements. <a href=\"https:\/\/fluffyandflakey.blog\/tag\/wordpress\/feed\/#31e75dae-1847-44df-92e1-8ae5756eeec6-link\" target=\"_blank\" rel=\"noopener\"><img decoding=\"async\" alt=\"\u21a9\" class=\"wp-smiley\" src=\"https:\/\/s.w.org\/images\/core\/emoji\/17.0.2\/72x72\/21a9.png\">\ufe0e<\/a><\/li>\n<\/ol>\n","protected":false},"excerpt":{"rendered":"<p>HTML and XML are markup languages based on plaintext files. This means that any given character could be part of a syntax form (a tag, a comment, a character reference, etc\u2026) or it could be representing itself the way it reads in the file literally. &lt;tag&gt;&amp;middot; Text node&lt;\/tag&gt; Whenever a character might be ambiguous, both [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-11292","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"blog_post_layout_featured_media_urls":{"thumbnail":"","full":""},"categories_names":{"1":{"name":"Uncategorized","link":"https:\/\/4ksamachar.com\/?cat=1"}},"tags_names":[],"comments_number":"0","wpmagazine_modules_lite_featured_media_urls":{"thumbnail":"","cvmm-medium":"","cvmm-medium-plus":"","cvmm-portrait":"","cvmm-medium-square":"","cvmm-large":"","cvmm-small":"","full":""},"_links":{"self":[{"href":"https:\/\/4ksamachar.com\/index.php?rest_route=\/wp\/v2\/posts\/11292","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/4ksamachar.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/4ksamachar.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/4ksamachar.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/4ksamachar.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=11292"}],"version-history":[{"count":0,"href":"https:\/\/4ksamachar.com\/index.php?rest_route=\/wp\/v2\/posts\/11292\/revisions"}],"wp:attachment":[{"href":"https:\/\/4ksamachar.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=11292"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/4ksamachar.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=11292"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/4ksamachar.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=11292"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}