Skip to content

Commit

Permalink
Fix data part references (#934)
Browse files Browse the repository at this point in the history
* Add dataPartReferences to child instead of this #931

* Add test case for #931

* Fix modify while iterating issue

This issue was uncovered by adding a new test case

Co-authored-by: Lars Klein <lars.klein@deepl.com>
  • Loading branch information
lklein53 and Lars Klein authored Jun 16, 2021
1 parent 29531d5 commit 0952534
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 3 deletions.
11 changes: 8 additions & 3 deletions src/DocumentFormat.OpenXml/Packaging/OpenXmlPartContainer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1698,6 +1698,7 @@ private OpenXmlPart AddSubPartFromOtherPackage(OpenXmlPart part, IDictionary<Ope
}
}

var updatedParts = new Dictionary<DataPart, DataPart>();
foreach (var item in dataPartsDictionary)
{
if (item.Value is null)
Expand All @@ -1714,17 +1715,21 @@ private OpenXmlPart AddSubPartFromOtherPackage(OpenXmlPart part, IDictionary<Ope

InternalOpenXmlPackage.AddDataPartToList(newDataPart);

dataPartsDictionary[dataPart] = newDataPart;
updatedParts.Add(dataPart, newDataPart);
}
}

foreach (var item in updatedParts) {
dataPartsDictionary[item.Key] = item.Value;
}

// then create data part reference relationship
foreach (var dataPartReferenceRelationship in part.DataPartReferenceRelationships)
{
if (dataPartsDictionary[dataPartReferenceRelationship.DataPart] is MediaDataPart newDataPart)
{
var newDataPartReference = DataPartReferenceRelationship.Create(this, newDataPart, dataPartReferenceRelationship.RelationshipType, dataPartReferenceRelationship.Id);
ReferenceRelationshipList.AddLast(newDataPartReference);
var newDataPartReference = DataPartReferenceRelationship.Create(child, newDataPart, dataPartReferenceRelationship.RelationshipType, dataPartReferenceRelationship.Id);
child.AddDataPartReferenceRelationship(newDataPartReference);
}
}

Expand Down
47 changes: 47 additions & 0 deletions test/DocumentFormat.OpenXml.Packaging.Tests/OpenXmlPackageTests.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using DocumentFormat.OpenXml.Presentation;
using DocumentFormat.OpenXml.Wordprocessing;
using System;
using System.Collections.Generic;
Expand All @@ -9,6 +10,8 @@
using System.Xml.Linq;
using Xunit;

using Text = DocumentFormat.OpenXml.Wordprocessing.Text;

namespace DocumentFormat.OpenXml.Packaging.Tests
{
public class OpenXmlPackageTests
Expand Down Expand Up @@ -208,5 +211,49 @@ public void CanTransformWordprocessingDocumentWithAltChunksToFlatOpc()
Assert.All(altChunkParts, p => Assert.NotEmpty(p.Elements(Pkg + "binaryData")));
}
}

private static MemoryStream CreatePresentationDocumentWithDataReference()
{
var stream = new MemoryStream();

using (var ppt = PresentationDocument.Create(stream, PresentationDocumentType.Presentation))
{
var mainPart = ppt.AddPresentationPart();
var slide = new Slide();
var slidePart = mainPart.AddNewPart<SlidePart>();
var dataPart = new MediaDataPart(ppt.InternalOpenXmlPackage, MediaDataPartType.Mp3);
var dataPartReferenceRelationship = DataPartReferenceRelationship.Create(slidePart, dataPart, MediaReferenceRelationship.RelationshipTypeConst, "rId2");
slidePart.AddDataPartReferenceRelationship(dataPartReferenceRelationship);
slide.Save(slidePart);
mainPart.Presentation = new Presentation.Presentation(slide);
mainPart.Presentation.Save();
}

stream.Seek(0, SeekOrigin.Begin);
return stream;
}

// This is a regression test case for issue #931
// Saving a office documents opened using the OpenXML SDK removed data references from the saved document.
// This lead to invalid documents that couldn't be opened by office.
[Fact]
public void TestDataReferenceRelationshipsAreClonedCorrectly()
{
using var stream = CreatePresentationDocumentWithDataReference();
using var ppt = PresentationDocument.Open(stream, false);
Assert.NotNull(ppt.PresentationPart);
Assert.NotNull(ppt.PresentationPart.Presentation);
Assert.Single(ppt.PresentationPart.SlideParts);
var slidePart = ppt.PresentationPart.SlideParts.First();
Assert.NotEmpty(slidePart.DataPartReferenceRelationships);
var clonedStream = new MemoryStream();
ppt.Clone(clonedStream);
using var clonedPpt = PresentationDocument.Open(clonedStream, false);
Assert.NotNull(clonedPpt.PresentationPart);
Assert.NotNull(clonedPpt.PresentationPart.Presentation);
Assert.Single(clonedPpt.PresentationPart.SlideParts);
var clonedSlidePart = clonedPpt.PresentationPart.SlideParts.First();
Assert.NotEmpty(clonedSlidePart.DataPartReferenceRelationships);
}
}
}

0 comments on commit 0952534

Please sign in to comment.