XML Tutorial · XML Basics · Lesson 2 of 28

XML Syntax

The XML declaration, the root element, start and end tags, empty elements, attributes, comments and processing instructions.

Create a free account to save this page, take notes and track your progress. Sign in

The parts of an XML document

<?xml version="1.0" encoding="UTF-8"?>          <!-- 1. XML declaration (optional, must be first) -->
<!-- 2. A comment -->
<library>                                        <!-- 3. The root element: exactly one -->
  <book id="b1" lang="en">                       <!-- 4. Start tag with attributes -->
    <title>Dune</title>                          <!-- 5. Element with text content -->
    <available/>                                 <!-- 6. Empty element (self-closing) -->
  </book>                                        <!-- 7. End tag -->
  <?print-style compact?>                        <!-- 8. Processing instruction -->
</library>
  • The declaration states the XML version and character encoding. It's optional (UTF-8 is the default), but if present it must be the very first thing in the file, with no whitespace before it.
  • There is exactly one root element; everything else lives inside it.
  • Every start tag needs a matching end tag (<title>…</title>), or the element is written self-closing (<available/>).
  • Attributes are name="value" pairs in the start tag; values are always quoted (single or double quotes).
  • Comments are <!-- … --> and can't contain --.
  • Processing instructions (<?target data?>) pass hints to applications, like <?xml-stylesheet?>.

Names

Element and attribute names are case-sensitive (<Book> and <book> are different), must start with a letter or underscore, and may contain letters, digits, -, _ and .. Names starting with xml (in any case) are reserved.

The document is a tree

A parser turns the text into a tree of nodes. Walking it shows the structure:

Walk the treeTry it yourself
from lxml import etree

doc = etree.fromstring(b"""<library>
  <book id="b1" lang="en">
    <title>Dune</title>
    <available/>
  </book>
  <!-- more books soon -->
</library>""")

def show(node, depth=0):
    pad = "  " * depth
    if isinstance(node, etree._Comment):
        print(f"{pad}comment: {node.text.strip()}")
        return
    attrs = " ".join(f'{k}="{v}"' for k, v in node.attrib.items())
    text = (node.text or "").strip()
    print(f"{pad}<{node.tag}{' ' + attrs if attrs else ''}>{' text=' + repr(text) if text else ''}")
    for child in node:
        show(child, depth + 1)

show(doc)
print("root:", doc.tag, "| children:", len(doc))

Output

<library>
  <book id="b1" lang="en">
    <title> text='Dune'
    <available>
  comment: more books soon
root: library | children: 2

Whitespace between elements is kept as text nodes. Most programs ignore it, but it matters for documents (mixed content) and when you compare or sign XML.

Test yourself

How many root elements can a well-formed XML document have?

  1. Exactly one
  2. One or more
  3. Any number
  4. None; the declaration is the root
Show answer

Answer: Exactly one

Every other element must be nested inside the single root (document) element.

Was this page helpful?