Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix data part references #934

Merged
merged 3 commits into from
Jun 16, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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);
}
}
}