DOCX, XLSX a ODT: XML uvnitř kancelářských dokumentů

Soubory .docx, .xlsx, .pptx i .odt z LibreOffice jsou ZIP archivy plné XML souborů. Kapitola ukazuje, jak se do nich podívat, jak je uložený text ve Wordu, buňky v Excelu a snímky v PowerPointu, čím se liší Office Open XML od OpenDocumentu a jak data z dokumentu vytáhnout programem.

Autor: Aktualizováno

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:

Obsah souboru .docx
$ 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
StandardECMA-376, ISO/IEC 29500OASIS OpenDocument, ISO/IEC 26300
Hlavní aplikaceMicrosoft OfficeLibreOffice, Collabora; umí je i Microsoft Office
Hlavní XMLword/document.xml, xl/worksheets/sheet1.xml, ppt/slides/slide1.xmlcontent.xml pro všechny typy dokumentů
Popis balíčku[Content_Types].xml a soubory .relsmimetype a META-INF/manifest.xml
Jeden XML soubor bez ZIPuWord 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):

[Content_Types].xml
<?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.

_rels/.rels
<?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>
AplikaceKořenová složkaHlavní částKořenový element
Word (WordprocessingML)word/document.xmlw:document
Excel (SpreadsheetML)xl/workbook.xml + worksheets/sheetN.xmlworkbook, worksheet
PowerPoint (PresentationML)ppt/presentation.xml + slides/slideN.xmlp: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:

word/document.xml (zjednodušeno)
<?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:ins a w:del, komentáře leží v samostatné části word/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:

xl/sharedStrings.xml
<?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>
xl/worksheets/sheet1.xml
<?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 atributu t je 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 (atribut s buň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:

ppt/slides/slide1.xml (výřez)
<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:

content.xml z .odt (zjednodušeno)
<?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:

Python: text odstavců z .docx
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 .docm a .xlsm obsahují makra VBA v binární části vbaProject.bin. Ta do XML nepatří a nevidíš je, ani když archiv rozbalíš a prohlížíš XML.