XML Tutorial · XML Basics · Lesson 3 of 28

Elements vs Attributes

When to store data in elements and when in attributes, how to design readable XML, and mixed content.

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

Two ways to say the same thing

<!-- attributes -->
<person id="7" name="Ada Lovelace" born="1815"/>

<!-- elements -->
<person>
  <id>7</id>
  <name>Ada Lovelace</name>
  <born>1815</born>
</person>

Both are valid. Common guidelines:

Use an attribute for Use a child element for
Identifiers and metadata (id, lang, currency, version) The actual data or content
Single, simple values Values that can repeat (several phone numbers)
Values that never need structure Values that may later need sub-elements or attributes
Short values Long text, or text containing markup

Attribute order is not significant, and an element can't have the same attribute twice. Element order is significant.

Mixed content

Documents (as opposed to data records) often mix text and elements:

<p>Water boils at <num unit="C">100</num> degrees at <em>sea level</em>.</p>

In tree APIs, text before the first child is the element's text, and text after a child is that child's tail (lxml/ElementTree) or a separate text node (DOM). itertext() collects all of it:

Text and tail in mixed contentTry it yourself
from lxml import etree

p = etree.fromstring(b'<p>Water boils at <num unit="C">100</num> degrees at <em>sea level</em>.</p>')
print("text:", repr(p.text))
for child in p:
    print(f"<{child.tag}> text={child.text!r} tail={child.tail!r}")
print("all text:", "".join(p.itertext()))

Output

text: 'Water boils at '
<num> text='100' tail=' degrees at '
<em> text='sea level' tail='.'
all text: Water boils at 100 degrees at sea level.

Reading attributes and elements together

Attributes and child elementsTry it yourself
from lxml import etree

people = etree.fromstring(b"""<people>
  <person id="7" born="1815"><name>Ada Lovelace</name><role>mathematician</role></person>
  <person id="9" born="1906"><name>Grace Hopper</name><role>admiral</role></person>
</people>""")

for p in people:
    print(p.get("id"), p.findtext("name"), p.get("born"), p.findtext("role"), sep=" | ")

Output

7 | Ada Lovelace | 1815 | mathematician
9 | Grace Hopper | 1906 | admiral

Test yourself

Which is usually better stored as a child element rather than an attribute?

  1. An id
  2. A list of phone numbers
  3. A language code
  4. A version number
Show answer

Answer: A list of phone numbers

Attributes can't repeat on one element; repeating values belong in child elements.

Was this page helpful?