Skip to content

[BUG] pptx: targeted edit re-serializes every untouched slide XML part #267

Description

@Coldwings

Summary

On a PPTX authored by Microsoft Macintosh PowerPoint, changing one paragraph on slide 1 with officecli set re-serializes every slide XML part in the package.

The untouched slides remain visually valid in my test, but they are no longer byte-preserved. This creates noisy package diffs and increases the round-trip risk for unsupported or extension XML on slides that the command did not target.

Environment

  • OfficeCLI: 1.0.142
  • OS: Linux x86_64
  • Source PPTX producer (docProps/app.xml): Microsoft Macintosh PowerPoint
  • Deck: 18 slides

Reproduction

cp input.pptx before.pptx
cp input.pptx after.pptx

officecli set after.pptx \
  '/slide[1]/shape[@id=4]/paragraph[1]' \
  --prop 'text=OfficeCLI round-trip probe' \
  --json

mkdir before after
unzip -qq before.pptx -d before
unzip -qq after.pptx -d after

for f in before/ppt/slides/slide*.xml; do
  name=$(basename "$f")
  cmp -s "$f" "after/ppt/slides/$name" || echo "$name"
done

Observed output:

slide1.xml
slide2.xml
...
slide18.xml

Only slide 1 was targeted. For example, slide2.xml changed from 19,543 bytes to 19,944 bytes solely through serializer normalization (XML declaration/empty-element/whitespace formatting); its content was not intentionally edited.

The same command on a PPTX generated by OfficeCLI itself did not produce unrelated slide diffs, so this appears to be most visible when OfficeCLI first opens a package serialized by another producer.

Expected behavior

A targeted edit to slide 1 should persist the modified slide and any package-level parts that genuinely require an update, while leaving unrelated slide parts byte-for-byte unchanged.

If whole-deck normalization is intentional, an explicit opt-in mode would be safer than making it the default for a targeted edit.

Possible cause

PowerPointHandler calls InitShapeIdCounter() when an editable document is opened. That method walks GetSlideParts() and calls GetSlide(slidePart) for every slide, loading every slide root into the Open XML SDK DOM. A later package save may then serialize all loaded roots, including clean slides.

Relevant locations:

  • src/officecli/Handlers/PowerPointHandler.cs (editable constructor)
  • src/officecli/Handlers/Pptx/PowerPointHandler.Helpers.ShapeId.cs (InitShapeIdCounter)

A regression test could use a fixture with deliberately non-SDK lexical serialization, edit one paragraph on slide 1, then assert that the raw ZIP bytes for ppt/slides/slide2.xml and subsequent untouched slides remain identical.

If a shareable fixture is needed, I can build a synthetic PPTX that preserves the relevant producer/serialization characteristics. The original test deck contains private business material and will not be uploaded.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions