Structure of a PresentationML document

A PresentationML file is an Open Packaging Convention package. The .pptx file is a ZIP container whose parts are connected by relationship items. ooxmlsdk exposes that graph through PresentationDocument and generated part accessors.

A presentation is not stored as one large XML body. The presentation root, slide masters, slide layouts, slides, themes, notes, comments, media, and other resources live in separate parts. A separate XML part is created for each slide.

The minimum document structure includes the presentation, slide master, slide layout, slide, and theme parts. Real decks can also include notes slides, handout masters, shapes, pictures, tables, animations, audio, video, and slide transitions.

Package parts

Package partRoot elementooxmlsdk access
Presentation<p:presentation/>PresentationDocument::presentation_part()
Slide<p:sld/>PresentationPart::slide_parts(&document)
Slide master<p:sldMaster/>PresentationPart::slide_master_parts(&document)
Slide layout<p:sldLayout/>SlidePart::slide_layout_part(&document)
Notes slide<p:notes/>SlidePart::notes_slide_part(&document)
Notes master<p:notesMaster/>PresentationPart::notes_master_part(&document)
Handout master<p:handoutMaster/>PresentationPart::handout_master_part(&document)
Theme<a:theme/>PresentationPart::theme_part(&document)
Comments<p:cmLst/>slide comment part accessors when present
Comment authors<p:cmAuthorLst/>PresentationPart::comment_authors_part(&document)

The exact set of parts depends on the document. A small deck can contain only the package relationship item, the presentation part, slide parts, and the required content type declarations.

Relationship graph

The package-level relationship points to ppt/presentation.xml. The presentation part then owns relationships to slide parts and other top-level presentation resources.

<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
  <Relationship
    Id="rId1"
    Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument"
    Target="ppt/presentation.xml"/>
</Relationships>

Inside ppt/presentation.xml, slide ids refer to relationship ids:

<p:sldIdLst>
  <p:sldId id="256" r:id="rId1"/>
  <p:sldId id="257" r:id="rId2"/>
</p:sldIdLst>

Those ids are resolved in ppt/_rels/presentation.xml.rels:

<Relationship
  Id="rId1"
  Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/slide"
  Target="slides/slide1.xml"/>

Reading the graph in Rust

Use the package model rather than opening ZIP paths manually:

#![allow(unused)]
fn main() {
use std::io::Cursor;
use std::path::Path;

use ooxmlsdk::parts::comment_authors_part::CommentAuthorsPart;
use ooxmlsdk::parts::presentation_document::PresentationDocument;
use ooxmlsdk::parts::presentation_part::PresentationPart;
use ooxmlsdk::parts::slide_comments_part::SlideCommentsPart;
use ooxmlsdk::parts::slide_part::SlidePart;
use ooxmlsdk::sdk::MediaDataPartType;
use ooxmlsdk::sdk::{OpenSettings, PackageOpenMode, PresentationDocumentType};

pub fn open_presentation_read_only(path: &Path) -> Result<usize, Box<dyn std::error::Error>> {
  let document = PresentationDocument::new_from_file_with_settings(path, lazy_settings())?;
  let presentation_part = document.presentation_part()?;

  Ok(presentation_part.slide_parts(&document).count())
}
}

That pattern is the base for the other PresentationML examples: open the package, get the presentation part, then walk typed child parts or relationship iterators.

Minimal slide part

A slide part stores only one slide. Text and drawing content are under <p:cSld/>.

<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:nvGrpSpPr>
        <p:cNvPr id="1" name=""/>
        <p:cNvGrpSpPr/>
        <p:nvPr/>
      </p:nvGrpSpPr>
      <p:grpSpPr/>
      <p:sp>
        <p:nvSpPr>
          <p:cNvPr id="2" name="Text 2"/>
          <p:cNvSpPr/>
          <p:nvPr/>
        </p:nvSpPr>
        <p:spPr/>
        <p:txBody>
          <a:bodyPr/>
          <a:lstStyle/>
          <a:p><a:r><a:t>Hello</a:t></a:r></a:p>
        </p:txBody>
      </p:sp>
    </p:spTree>
  </p:cSld>
</p:sld>

For schema details, keep the XML element names separate from the Rust package API: XML stores ids and content; ooxmlsdk resolves ids into typed parts and relationships.