Dokument je ZIP archiv
Od Office 2007 ukládá Microsoft Office dokumenty ve formátu Office Open XML (OOXML), LibreOffice a OpenOffice používají OpenDocument (ODF). Oba formáty stojí na stejném nápadu: dokument je ZIP archiv, v němž jsou text, styly a nastavení uložené v samostatných XML souborech a obrázky jako obyčejné soubory.
Stačí soubor zkopírovat, změnit příponu na .zip a rozbalit — nebo si obsah
vypsat v terminálu:
$ unzip -l zprava.docx
[Content_Types].xml
_rels/.rels
docProps/core.xml autor, datum vytvoření, název
docProps/app.xml aplikace, počet stran a slov
word/document.xml vlastní text dokumentu
word/styles.xml styly (Nadpis 1, Normální…)
word/settings.xml
word/_rels/document.xml.rels
word/media/image1.png vložené obrázky jsou obyčejné soubory Když Word hlásí, že je dokument poškozený, bývá chyba právě v jednom z těchto XML souborů. Rozbal ho, vlož podezřelou část do validátoru a ten ukáže řádek a sloupec, kde je zápis rozbitý.
OOXML a ODF v kostce
| Office Open XML (OOXML) | OpenDocument (ODF) | |
|---|---|---|
| Přípony | .docx, .xlsx, .pptx (s makry .docm, .xlsm, .pptm) | .odt, .ods, .odp, .odg |
| Standard | ECMA-376, ISO/IEC 29500 | OASIS OpenDocument, ISO/IEC 26300 |
| Hlavní aplikace | Microsoft Office | LibreOffice, Collabora; umí je i Microsoft Office |
| Hlavní XML | word/document.xml, xl/worksheets/sheet1.xml, ppt/slides/slide1.xml | content.xml pro všechny typy dokumentů |
| Popis balíčku | [Content_Types].xml a soubory .rels | mimetype a META-INF/manifest.xml |
| Jeden XML soubor bez ZIPu | Word 2003 XML / Flat OPC (okrajově) | Flat ODF: .fodt, .fods, .fodp |
OOXML existuje ve dvou variantách: Transitional, kterou Office ukládá ve výchozím nastavení a která nese i prvky pro zpětnou kompatibilitu se starými .doc soubory, a přísnější Strict. OpenDocument je standard OASIS; aktuální verze 1.4 byla schválena v prosinci 2025; verze 1.2 je zároveň mezinárodní normou ISO/IEC 26300:2015.
Balíček OOXML: typy obsahu a vztahy
OOXML balíček řídí dvě věci. Soubor [Content_Types].xml v kořeni říká, jaký typ
obsahu má která část — podle přípony (Default) nebo podle konkrétní cesty
(Override):
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">
<Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/>
<Default Extension="xml" ContentType="application/xml"/>
<Default Extension="png" ContentType="image/png"/>
<Override PartName="/word/document.xml"
ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml"/>
</Types>
Soubory .rels ve složkách _rels pak popisují vztahy mezi
částmi. Aplikace začne v _rels/.rels, najde hlavní dokument a z jeho vlastního
.rels zjistí, kde leží styly, obrázky nebo záhlaví. Na obrázek se text odkazuje
identifikátorem vztahu (r:embed="rId5"), ne cestou k souboru.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
<Relationship Id="rId1"
Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument"
Target="word/document.xml"/>
</Relationships> | Aplikace | Kořenová složka | Hlavní část | Kořenový element |
|---|---|---|---|
| Word (WordprocessingML) | word/ | document.xml | w:document |
| Excel (SpreadsheetML) | xl/ | workbook.xml + worksheets/sheetN.xml | workbook, worksheet |
| PowerPoint (PresentationML) | ppt/ | presentation.xml + slides/slideN.xml | p:presentation, p:sld |
Word: odstavce, běhy a text
Text dokumentu je v word/document.xml. Struktura WordprocessingML má tři úrovně:
odstavec w:p, běh w:r (úsek textu se stejným formátováním) a vlastní
text w:t. Vlastnosti odstavce jsou v w:pPr, vlastnosti běhu v
w:rPr:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
<w:body>
<w:p>
<w:pPr><w:pStyle w:val="Nadpis1"/></w:pPr>
<w:r><w:t>Výroční zpráva</w:t></w:r>
</w:p>
<w:p>
<w:r><w:t xml:space="preserve">Tržby vzrostly o </w:t></w:r>
<w:r><w:rPr><w:b/></w:rPr><w:t>12 %</w:t></w:r>
<w:r><w:t>.</w:t></w:r>
</w:p>
</w:body>
</w:document> -
Jedna věta může být rozdělená do mnoha běhů — kvůli formátování, kontrole pravopisu, revizím
nebo prostě historii úprav. Hledání slova v XML proto často selže: „Tržby“ může být uložené
jako
<w:t>Trž</w:t>a<w:t>by</w:t>. Při nahrazování zástupných textů v šablonách je potřeba text odstavce nejdřív poskládat. -
Mezery na začátku nebo konci textu se zachovají jen s
xml:space="preserve"— jinak je aplikace smí zahodit. -
Sledované změny jsou elementy
w:insaw:del, komentáře leží v samostatné částiword/comments.xml.
Excel: buňky a sdílené řetězce
Sešit popisuje xl/workbook.xml (seznam listů), každý list má vlastní soubor
xl/worksheets/sheetN.xml. Texty ale v listu nejsou. Excel je ukládá jen jednou do
tabulky sdílených řetězců xl/sharedStrings.xml a v buňce drží pouze jejich index:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<sst xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" count="3" uniqueCount="3">
<si><t>Položka</t></si>
<si><t>Cena</t></si>
<si><t>Klávesnice</t></si>
</sst> <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
<sheetData>
<row r="1">
<c r="A1" t="s"><v>0</v></c>
<c r="B1" t="s"><v>1</v></c>
</row>
<row r="2">
<c r="A2" t="s"><v>2</v></c>
<c r="B2"><v>1250</v></c>
</row>
<row r="3">
<c r="B3"><f>SUM(B2:B2)</f><v>1250</v></c>
</row>
</sheetData>
</worksheet> -
t="s"znamená „hodnota je index do sdílených řetězců“ (počítáno od nuly). Buňka A2 tedy obsahuje text „Klávesnice“. Bez atribututje hodnota číslo. -
Datum je v XML jen číslo — počet dní od roku 1900. Že jde o datum, pozná Excel až podle
číselného formátu ve
styles.xml(atributsbuňky). -
U vzorce je v
<f>zápis vzorce a v<v>naposledy spočítaná hodnota. Program, který soubor jen čte, vzorce nepřepočítává. -
Prázdné buňky se neukládají; souřadnici nese atribut
r. Při čtení proto nespoléhej na pořadí elementůc.
Pokud potřebuješ opačný směr — načíst do Excelu data z XML souboru — pokračuj návodem Převod XML do Excelu.
PowerPoint: snímky a DrawingML
Prezentace má seznam snímků v ppt/presentation.xml, každý snímek je v
ppt/slides/slideN.xml a poznámky řečníka v ppt/notesSlides/. Tvary a
text popisuje sdílený slovník DrawingML (prefix a:), který se
používá i pro grafy a obrázky ve Wordu a Excelu:
<p:sld xmlns:p="http://schemas.openxmlformats.org/presentationml/2006/main"
xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main">
<p:cSld>
<p:spTree>
…
<p:sp>
<p:txBody>
<a:bodyPr/>
<a:p><a:r><a:t>Plán na rok 2027</a:t></a:r></a:p>
</p:txBody>
</p:sp>
</p:spTree>
</p:cSld>
</p:sld> OpenDocument: content.xml
Archiv ODF má jednodušší stavbu. Prvním souborem v ZIPu musí být nekomprimovaný
mimetype s typem dokumentu (například
application/vnd.oasis.opendocument.text), seznam částí je v
META-INF/manifest.xml. Obsah všech typů dokumentů je v content.xml,
styly ve styles.xml a metadata v meta.xml:
<?xml version="1.0" encoding="UTF-8"?>
<office:document-content
xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0"
xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0"
office:version="1.3">
<office:body>
<office:text>
<text:h text:outline-level="1">Výroční zpráva</text:h>
<text:p>Tržby vzrostly o 12 %.</text:p>
</office:text>
</office:body>
</office:document-content>
Tabulky (.ods) používají v témže souboru elementy table:table,
table:table-row a table:table-cell; typ hodnoty nese atribut
office:value-type a číslo je v office:value. Pro verzování v gitu se
hodí „ploché“ varianty .fodt a .fods — celý dokument v jediném
nekomprimovaném XML.
Jak dokument číst a vytvářet programem
Na běžnou práci použij knihovnu, která balíček, vztahy i sdílené řetězce vyřeší za tebe: Open XML SDK v .NET, python-docx a openpyxl v Pythonu, PhpSpreadsheet a PHPWord v PHP, Apache POI v Javě nebo ExcelJS v JavaScriptu. Pro jednoduché čtení ale stačí ZIP a XML parser:
import zipfile
from defusedxml import ElementTree as ET # pip install defusedxml
W = "{http://schemas.openxmlformats.org/wordprocessingml/2006/main}"
with zipfile.ZipFile("zprava.docx") as z:
root = ET.fromstring(z.read("word/document.xml"))
for p in root.iter(W + "p"):
# text odstavce je rozdělený do několika w:t – je potřeba ho spojit
print("".join(t.text or "" for t in p.iter(W + "t"))) - Elementy hledej podle jmenného prostoru, ne podle prefixu — jiné aplikace mohou prefixy pojmenovat jinak.
- Dokumenty od uživatelů zpracovávej parserem s vypnutými externími entitami. Upravený .docx s DTD uvnitř je známý nosič útoku XXE.
-
Soubory
.docma.xlsmobsahují makra VBA v binární částivbaProject.bin. Ta do XML nepatří a nevidíš je, ani když archiv rozbalíš a prohlížíš XML.