XML Tutorial · XML in the Real World · Lesson 25 of 28
SVG and Office Documents
Two everyday XML formats you may not think of as XML: SVG graphics and Office Open XML files (.docx, .xlsx), and how to generate and read them.
SVG is XML
An SVG image is an XML document in the http://www.w3.org/2000/svg namespace, so you can generate charts and
icons with any XML library. This SVG is rendered live:
<svg xmlns="http://www.w3.org/2000/svg" width="260" height="120" viewBox="0 0 260 120" font-family="sans-serif" font-size="12">
<rect x="10" y="50" width="50" height="60" fill="#0f766e"/>
<rect x="80" y="20" width="50" height="90" fill="#14b8a6"/>
<rect x="150" y="70" width="50" height="40" fill="#5eead4"/>
<text x="35" y="44" text-anchor="middle">Tea</text>
<text x="105" y="14" text-anchor="middle">Mugs</text>
<text x="175" y="64" text-anchor="middle">Pans</text>
</svg>
Generating it in Python is ordinary XML building:
from lxml import etree
SVG = "http://www.w3.org/2000/svg"
sales = {"Tea": 60, "Mugs": 90, "Pans": 40}
svg = etree.Element(f"{{{SVG}}}svg", nsmap={None: SVG}, width="260", height="120")
for i, (label, value) in enumerate(sales.items()):
x = 10 + i * 70
etree.SubElement(svg, f"{{{SVG}}}rect", x=str(x), y=str(110 - value), width="50", height=str(value))
etree.SubElement(svg, f"{{{SVG}}}text", x=str(x + 25), y=str(104 - value)).text = label
print(etree.tostring(svg, pretty_print=True).decode())
Output
<svg xmlns="http://www.w3.org/2000/svg" width="260" height="120"> <rect x="10" y="50" width="50" height="60"/> <text x="35" y="44">Tea</text> <rect x="80" y="20" width="50" height="90"/> <text x="105" y="14">Mugs</text> <rect x="150" y="70" width="50" height="40"/> <text x="175" y="64">Pans</text> </svg>
SVG files can contain scripts and external references, so treat uploaded SVGs as untrusted: sanitise them, or serve them from a separate domain with a strict Content-Security-Policy.
Office documents are zipped XML
.docx, .xlsx and .pptx files (Office Open XML, ECMA-376 / ISO/IEC 29500) are ZIP archives of XML parts.
A Word document's text lives in word/document.xml, in paragraphs (w:p), runs (w:r) and text (w:t).
OpenDocument (.odt, LibreOffice) works the same way.
import io
import zipfile
from lxml import etree
W = "http://schemas.openxmlformats.org/wordprocessingml/2006/main"
# Build a tiny .docx in memory (just the parts needed to show the structure)
body = "".join(f"<w:p><w:r><w:t>{text}</w:t></w:r></w:p>" for text in ["Invoice 1042", "Total: 15.50 EUR"])
buffer = io.BytesIO()
with zipfile.ZipFile(buffer, "w") as docx:
docx.writestr("word/document.xml", f'<w:document xmlns:w="{W}"><w:body>{body}</w:body></w:document>')
# Read it back the way any .docx is read
with zipfile.ZipFile(buffer) as docx:
print(docx.namelist())
doc = etree.fromstring(docx.read("word/document.xml"))
for paragraph in doc.iter(f"{{{W}}}p"):
print("".join(t.text for t in paragraph.iter(f"{{{W}}}t")))
Output
['word/document.xml'] Invoice 1042 Total: 15.50 EUR
For real work use a library: python-docx and openpyxl (Python), PhpSpreadsheet and PHPWord (PHP), Apache POI
(Java). They handle styles, relationships and the many details of the formats.
Test yourself
What is a .docx file?
A ZIP archive of XML filesA single binary fileA PDF variantAn HTML file
Show answer
Answer: A ZIP archive of XML files
Office Open XML packages store each part (document, styles, relationships) as XML inside a ZIP.