From 1c0ae6c0a4380aed9a45ae70d8ce6a5079d6e417 Mon Sep 17 00:00:00 2001 From: antony-liu Date: Thu, 11 Jun 2015 15:51:58 +0800 Subject: [PATCH] Improve the number of steps when generating an ID of a new relationship, and add more tests, bug #53904 --- .../OPC/PackageRelationshipCollection.cs | 940 +++++++++--------- testcases/openxml4net/TestRelationships.cs | 304 +++--- 2 files changed, 656 insertions(+), 588 deletions(-) diff --git a/ooxml/openxml4Net/OPC/PackageRelationshipCollection.cs b/ooxml/openxml4Net/OPC/PackageRelationshipCollection.cs index f930e2e97..378d198a0 100644 --- a/ooxml/openxml4Net/OPC/PackageRelationshipCollection.cs +++ b/ooxml/openxml4Net/OPC/PackageRelationshipCollection.cs @@ -9,478 +9,528 @@ namespace NPOI.OpenXml4Net.OPC { -/** - * Represents a collection of PackageRelationship elements that are owned by a - * given PackagePart or the Package. - * - * @author Julien Chable, CDubettier - * @version 0.1 - */ + /** + * Represents a collection of PackageRelationship elements that are owned by a + * given PackagePart or the Package. + * + * @author Julien Chable, CDubettier + * @version 0.1 + */ public class PackageRelationshipCollection : IEnumerator { - private static POILogger logger = POILogFactory.GetLogger(typeof(PackageRelationshipCollection)); - - /** - * Package relationships ordered by ID. - */ - private SortedList relationshipsByID; - - /** - * Package relationships ordered by type. - */ - private SortedList relationshipsByType; - - /** - * This relationshipPart. - */ - private PackagePart relationshipPart; - - /** - * Source part. - */ - private PackagePart sourcePart; - - /** - * This part name. - */ - private PackagePartName partName; - - /** - * Reference to the package. - */ - private OPCPackage container; - - /** - * Constructor. - */ - public PackageRelationshipCollection() { - relationshipsByID = new SortedList(); - relationshipsByType = new SortedList(new DuplicateComparer()); - } - class DuplicateComparer : IComparer - { - - #region IComparer Members - - public int Compare(string x, string y) + private static POILogger logger = POILogFactory.GetLogger(typeof(PackageRelationshipCollection)); + + /** + * Package relationships ordered by ID. + */ + private SortedList relationshipsByID; + + /** + * Package relationships ordered by type. + */ + private SortedList relationshipsByType; + + /** + * This relationshipPart. + */ + private PackagePart relationshipPart; + + /** + * Source part. + */ + private PackagePart sourcePart; + + /** + * This part name. + */ + private PackagePartName partName; + + /** + * Reference to the package. + */ + private OPCPackage container; + /** + * The ID number of the next rID# to generate, or -1 + * if that is still to be determined. + */ + private int nextRelationshipId = -1; + /** + * Constructor. + */ + public PackageRelationshipCollection() { - if (x.CompareTo(y) < 0) + relationshipsByID = new SortedList(); + relationshipsByType = new SortedList(new DuplicateComparer()); + } + class DuplicateComparer : IComparer + { + + #region IComparer Members + + public int Compare(string x, string y) { - return -1; + if (x.CompareTo(y) < 0) + { + return -1; + } + return 1; } - return 1; + + #endregion } + /** + * Copy constructor. + * + * This collection will contain only elements from the specified collection + * for which the type is compatible with the specified relationship type + * filter. + * + * @param coll + * Collection to import. + * @param filter + * Relationship type filter. + */ + public PackageRelationshipCollection(PackageRelationshipCollection coll, + String filter) + : this() + { - #endregion -} - /** - * Copy constructor. - * - * This collection will contain only elements from the specified collection - * for which the type is compatible with the specified relationship type - * filter. - * - * @param coll - * Collection to import. - * @param filter - * Relationship type filter. - */ - public PackageRelationshipCollection(PackageRelationshipCollection coll, - String filter):this() - { - - foreach(PackageRelationship rel in coll.relationshipsByID.Values) { - if (filter == null || rel.RelationshipType.Equals(filter)) - AddRelationship(rel); - } - } - - /** - * Constructor. - */ - public PackageRelationshipCollection(OPCPackage container) - : this(container, null) - { - - } - - /** - * Constructor. - * - * @throws InvalidFormatException - * Throws if the format of the content part is invalid. - * - * @throws InvalidOperationException - * Throws if the specified part is a relationship part. - */ - public PackageRelationshipCollection(PackagePart part): - this(part.container, part) - { - - } - - /** - * Constructor. Parse the existing package relationship part if one exists. - * - * @param container - * The parent package. - * @param part - * The part that own this relationships collection. If null - * then this part is considered as the package root. - * @throws InvalidFormatException - * If an error occurs during the parsing of the relatinships - * part fo the specified part. - */ - public PackageRelationshipCollection(OPCPackage container, PackagePart part):this() - { - - - if (container == null) - throw new ArgumentException("container"); - - // Check if the specified part is not a relationship part - if (part != null && part.IsRelationshipPart) - throw new ArgumentException("part"); - - this.container = container; - this.sourcePart = part; - this.partName = GetRelationshipPartName(part); - if ((container.GetPackageAccess() != PackageAccess.WRITE) - && container.ContainPart(this.partName)) + foreach (PackageRelationship rel in coll.relationshipsByID.Values) + { + if (filter == null || rel.RelationshipType.Equals(filter)) + AddRelationship(rel); + } + } + + /** + * Constructor. + */ + public PackageRelationshipCollection(OPCPackage container) + : this(container, null) + { + + } + + /** + * Constructor. + * + * @throws InvalidFormatException + * Throws if the format of the content part is invalid. + * + * @throws InvalidOperationException + * Throws if the specified part is a relationship part. + */ + public PackageRelationshipCollection(PackagePart part) : + this(part.container, part) + { + + } + + /** + * Constructor. Parse the existing package relationship part if one exists. + * + * @param container + * The parent package. + * @param part + * The part that own this relationships collection. If null + * then this part is considered as the package root. + * @throws InvalidFormatException + * If an error occurs during the parsing of the relatinships + * part fo the specified part. + */ + public PackageRelationshipCollection(OPCPackage container, PackagePart part) + : this() + { + + + if (container == null) + throw new ArgumentException("container"); + + // Check if the specified part is not a relationship part + if (part != null && part.IsRelationshipPart) + throw new ArgumentException("part"); + + this.container = container; + this.sourcePart = part; + this.partName = GetRelationshipPartName(part); + if ((container.GetPackageAccess() != PackageAccess.WRITE) + && container.ContainPart(this.partName)) + { + relationshipPart = container.GetPart(this.partName); + ParseRelationshipsPart(relationshipPart); + } + } + + /** + * Get the relationship part name of the specified part. + * + * @param part + * The part . + * @return The relationship part name of the specified part. Be careful, + * only the correct name is returned, this method does not check if + * the part really exist in a package ! + * @throws InvalidOperationException + * Throws if the specified part is a relationship part. + */ + private static PackagePartName GetRelationshipPartName(PackagePart part) + { + PackagePartName partName; + if (part == null) + { + partName = PackagingUriHelper.PACKAGE_ROOT_PART_NAME; + } + else + { + partName = part.PartName; + } + return PackagingUriHelper.GetRelationshipPartName(partName); + } + + /** + * Add the specified relationship to the collection. + * + * @param relPart + * The relationship to add. + */ + public void AddRelationship(PackageRelationship relPart) { - relationshipPart = container.GetPart(this.partName); - ParseRelationshipsPart(relationshipPart); - } - } - - /** - * Get the relationship part name of the specified part. - * - * @param part - * The part . - * @return The relationship part name of the specified part. Be careful, - * only the correct name is returned, this method does not check if - * the part really exist in a package ! - * @throws InvalidOperationException - * Throws if the specified part is a relationship part. - */ - private static PackagePartName GetRelationshipPartName(PackagePart part) - { - PackagePartName partName; - if (part == null) { - partName = PackagingUriHelper.PACKAGE_ROOT_PART_NAME; - } else { - partName = part.PartName; - } - return PackagingUriHelper.GetRelationshipPartName(partName); - } - - /** - * Add the specified relationship to the collection. - * - * @param relPart - * The relationship to add. - */ - public void AddRelationship(PackageRelationship relPart) { - relationshipsByID.Add(relPart.Id, relPart); - relationshipsByType.Add(relPart.RelationshipType, relPart); - } - - /** - * Add a relationship to the collection. - * - * @param targetUri - * Target URI. - * @param targetMode - * The target mode : INTERNAL or EXTERNAL - * @param relationshipType - * Relationship type. - * @param id - * Relationship ID. - * @return The newly created relationship. - * @see PackageAccess - */ - public PackageRelationship AddRelationship(Uri targetUri, - TargetMode targetMode, String relationshipType, String id) { - - if (id == null) { - // Generate a unique ID is id parameter is null. - int i = 0; - do { - id = "rId" + ++i; - } while (relationshipsByID.ContainsKey(id)); - } - - PackageRelationship rel = new PackageRelationship(container, - sourcePart, targetUri, targetMode, relationshipType, id); - relationshipsByID.Add(rel.Id, rel); - relationshipsByType.Add(rel.RelationshipType, rel); - return rel; - } - - /** - * Remove a relationship by its ID. - * - * @param id - * The relationship ID to Remove. - */ - public void RemoveRelationship(String id) { - if (relationshipsByID != null && relationshipsByType != null) { - PackageRelationship rel = relationshipsByID[id]; - if (rel != null) { - relationshipsByID.Remove(rel.Id); - for (int i = 0; i < relationshipsByType.Count; i++) + relationshipsByID.Add(relPart.Id, relPart); + relationshipsByType.Add(relPart.RelationshipType, relPart); + } + + /** + * Add a relationship to the collection. + * + * @param targetUri + * Target URI. + * @param targetMode + * The target mode : INTERNAL or EXTERNAL + * @param relationshipType + * Relationship type. + * @param id + * Relationship ID. + * @return The newly created relationship. + * @see PackageAccess + */ + public PackageRelationship AddRelationship(Uri targetUri, + TargetMode targetMode, String relationshipType, String id) + { + if (id == null) + { + // Generate a unique ID is id parameter is null. + if (nextRelationshipId == -1) { - if(relationshipsByType.Values[i]==rel) - relationshipsByType.RemoveAt(i); + nextRelationshipId = Size + 1; } - } - } - } - - /** - * Remove a relationship by its reference. - * - * @param rel - * The relationship to delete. - */ - public void RemoveRelationship(PackageRelationship rel) { - if (rel == null) - throw new ArgumentException("rel"); - - relationshipsByID.Values.Remove(rel); - relationshipsByType.Values.Remove(rel); - } - - /** - * Retrieves a relationship by its index in the collection. - * - * @param index - * Must be a value between [0-relationships_count-1] - */ - public PackageRelationship GetRelationship(int index) { - if (index < 0 || index > relationshipsByID.Values.Count) - throw new ArgumentException("index"); - - PackageRelationship retRel = null; - int i = 0; - foreach (PackageRelationship rel in relationshipsByID.Values) { - if (index == i++) - return rel; - } - return retRel; - } - - /** - * Retrieves a package relationship based on its id. - * - * @param id - * ID of the package relationship to retrieve. - * @return The package relationship identified by the specified id. - */ - public PackageRelationship GetRelationshipByID(String id) { - if (!relationshipsByID.ContainsKey(id)) - return null; - return relationshipsByID[id]; - } - - /** - * Get the numbe rof relationships in the collection. - */ - public int Size - { - get{ - return relationshipsByID.Values.Count; + + // Work up until we find a unique number (there could be gaps etc) + do + { + id = "rId" + nextRelationshipId++; + } while (relationshipsByID.ContainsKey(id)); + } + + PackageRelationship rel = new PackageRelationship(container, + sourcePart, targetUri, targetMode, relationshipType, id); + relationshipsByID.Add(rel.Id, rel); + relationshipsByType.Add(rel.RelationshipType, rel); + return rel; } - } - - /** - * Parse the relationship part and add all relationship in this collection. - * - * @param relPart - * The package part to parse. - * @throws InvalidFormatException - * Throws if the relationship part is invalid. - */ - private void ParseRelationshipsPart(PackagePart relPart) - { - try { - logger.Log(POILogger.DEBUG, "Parsing relationship: " + relPart.PartName); - XPathDocument xmlRelationshipsDoc = new XPathDocument(relPart.GetInputStream()); - - // Check OPC compliance M4.1 rule - bool fCorePropertiesRelationship = false; - ///xmlRelationshipsDoc.ChildNodes.GetEnumerator(); - XPathNavigator xpathnav = xmlRelationshipsDoc.CreateNavigator(); - XmlNamespaceManager nsMgr = new XmlNamespaceManager(xpathnav.NameTable); + + /** + * Remove a relationship by its ID. + * + * @param id + * The relationship ID to Remove. + */ + public void RemoveRelationship(String id) + { + if (relationshipsByID != null && relationshipsByType != null) + { + PackageRelationship rel = relationshipsByID[id]; + if (rel != null) + { + relationshipsByID.Remove(rel.Id); + for (int i = 0; i < relationshipsByType.Count; i++) + { + if (relationshipsByType.Values[i] == rel) + relationshipsByType.RemoveAt(i); + } + } + } + } + + /** + * Remove a relationship by its reference. + * + * @param rel + * The relationship to delete. + */ + public void RemoveRelationship(PackageRelationship rel) + { + if (rel == null) + throw new ArgumentException("rel"); + + relationshipsByID.Values.Remove(rel); + relationshipsByType.Values.Remove(rel); + } + + /** + * Retrieves a relationship by its index in the collection. + * + * @param index + * Must be a value between [0-relationships_count-1] + */ + public PackageRelationship GetRelationship(int index) + { + if (index < 0 || index > relationshipsByID.Values.Count) + throw new ArgumentException("index"); + + PackageRelationship retRel = null; + int i = 0; + foreach (PackageRelationship rel in relationshipsByID.Values) + { + if (index == i++) + return rel; + } + return retRel; + } + + /** + * Retrieves a package relationship based on its id. + * + * @param id + * ID of the package relationship to retrieve. + * @return The package relationship identified by the specified id. + */ + public PackageRelationship GetRelationshipByID(String id) + { + if (!relationshipsByID.ContainsKey(id)) + return null; + return relationshipsByID[id]; + } + + /** + * Get the numbe rof relationships in the collection. + */ + public int Size + { + get + { + return relationshipsByID.Values.Count; + } + } + + /** + * Parse the relationship part and add all relationship in this collection. + * + * @param relPart + * The package part to parse. + * @throws InvalidFormatException + * Throws if the relationship part is invalid. + */ + private void ParseRelationshipsPart(PackagePart relPart) + { + try + { + logger.Log(POILogger.DEBUG, "Parsing relationship: " + relPart.PartName); + XPathDocument xmlRelationshipsDoc = new XPathDocument(relPart.GetInputStream()); + + // Check OPC compliance M4.1 rule + bool fCorePropertiesRelationship = false; + ///xmlRelationshipsDoc.ChildNodes.GetEnumerator(); + XPathNavigator xpathnav = xmlRelationshipsDoc.CreateNavigator(); + XmlNamespaceManager nsMgr = new XmlNamespaceManager(xpathnav.NameTable); nsMgr.AddNamespace("x", PackageNamespaces.RELATIONSHIPS); - XPathNodeIterator iterator = xpathnav.Select("//x:"+PackageRelationship.RELATIONSHIP_TAG_NAME,nsMgr); + XPathNodeIterator iterator = xpathnav.Select("//x:" + PackageRelationship.RELATIONSHIP_TAG_NAME, nsMgr); - while(iterator.MoveNext()) + while (iterator.MoveNext()) + { + // Relationship ID + String id = iterator.Current.GetAttribute(PackageRelationship.ID_ATTRIBUTE_NAME, xpathnav.NamespaceURI); + // Relationship type + String type = iterator.Current.GetAttribute( + PackageRelationship.TYPE_ATTRIBUTE_NAME, xpathnav.NamespaceURI); + + /* Check OPC Compliance */ + // Check Rule M4.1 + if (type.Equals(PackageRelationshipTypes.CORE_PROPERTIES)) + if (!fCorePropertiesRelationship) + fCorePropertiesRelationship = true; + else + throw new InvalidFormatException( + "OPC Compliance error [M4.1]: there is more than one core properties relationship in the package !"); + + /* End OPC Compliance */ + + // TargetMode (default value "Internal") + string targetModeAttr = iterator.Current.GetAttribute(PackageRelationship.TARGET_MODE_ATTRIBUTE_NAME, xpathnav.NamespaceURI); + TargetMode targetMode = TargetMode.Internal; + if (targetModeAttr != string.Empty) + { + targetMode = targetModeAttr.ToLower() + .Equals("internal") ? TargetMode.Internal + : TargetMode.External; + } + + // Target converted in URI + Uri target; + String value = string.Empty; + try + { + value = iterator.Current.GetAttribute( + PackageRelationship.TARGET_ATTRIBUTE_NAME, xpathnav.NamespaceURI); + + + target = PackagingUriHelper.ToUri(value); + } + catch (UriFormatException e) + { + logger.Log(POILogger.ERROR, "Cannot convert " + value + + " in a valid relationship URI-> ignored", e); + continue; + } + AddRelationship(target, targetMode, type, id); + } + } + catch (Exception e) { - // Relationship ID - String id = iterator.Current.GetAttribute(PackageRelationship.ID_ATTRIBUTE_NAME, xpathnav.NamespaceURI); - // Relationship type - String type = iterator.Current.GetAttribute( - PackageRelationship.TYPE_ATTRIBUTE_NAME,xpathnav.NamespaceURI); - - /* Check OPC Compliance */ - // Check Rule M4.1 - if (type.Equals(PackageRelationshipTypes.CORE_PROPERTIES)) - if (!fCorePropertiesRelationship) - fCorePropertiesRelationship = true; - else - throw new InvalidFormatException( - "OPC Compliance error [M4.1]: there is more than one core properties relationship in the package !"); - - /* End OPC Compliance */ - - // TargetMode (default value "Internal") - string targetModeAttr = iterator.Current.GetAttribute(PackageRelationship.TARGET_MODE_ATTRIBUTE_NAME,xpathnav.NamespaceURI); - TargetMode targetMode = TargetMode.Internal; - if (targetModeAttr != string.Empty) { - targetMode = targetModeAttr.ToLower() - .Equals("internal") ? TargetMode.Internal - : TargetMode.External; - } - - // Target converted in URI - Uri target; - String value = string.Empty; - try { - value = iterator.Current.GetAttribute( - PackageRelationship.TARGET_ATTRIBUTE_NAME,xpathnav.NamespaceURI); - - - target = PackagingUriHelper.ToUri(value); - } catch (UriFormatException e) { - logger.Log(POILogger.ERROR, "Cannot convert " + value - + " in a valid relationship URI-> ignored", e); - continue; - } - AddRelationship(target, targetMode, type, id); - } - } catch (Exception e) { - logger.Log(POILogger.ERROR, e); - throw new InvalidFormatException(e.Message); + logger.Log(POILogger.ERROR, e); + throw new InvalidFormatException(e.Message); + } } - } - - /** - * Retrieves all relations with the specified type. - * - * @param typeFilter - * Relationship type filter. If null then all - * relationships are returned. - * @return All relationships of the type specified by the filter. - */ - public PackageRelationshipCollection GetRelationships(String typeFilter) { - PackageRelationshipCollection coll = new PackageRelationshipCollection( - this, typeFilter); - return coll; - } - - /** - * Get this collection's iterator. - */ - public IEnumerator GetEnumerator() - { - return relationshipsByID.Values.GetEnumerator(); - } - - /** - * Get an iterator of a collection with all relationship with the specified - * type. - * - * @param typeFilter - * Type filter. - * @return An iterator to a collection containing all relationships with the - * specified type contain in this collection. - */ - public IEnumerator Iterator(String typeFilter) { - List retArr = new List(); - foreach (PackageRelationship rel in relationshipsByID.Values) { - if (rel.RelationshipType.Equals(typeFilter)) - retArr.Add(rel); - } - return retArr.GetEnumerator(); - } - - /** - * Clear all relationships. - */ - public void Clear() { - relationshipsByID.Clear(); - relationshipsByType.Clear(); - } - - public override String ToString() { - String str; - if (relationshipsByID == null) { - str = "relationshipsByID=null"; - } else { - str = relationshipsByID.Count + " relationship(s) = ["; - } - if ((relationshipPart != null) && (relationshipPart.PartName != null)) { - str = str + "," + relationshipPart.PartName; - } else { - str = str + ",relationshipPart=null"; - } - - // Source of this relationship - if ((sourcePart != null) && (sourcePart.PartName != null)) + + /** + * Retrieves all relations with the specified type. + * + * @param typeFilter + * Relationship type filter. If null then all + * relationships are returned. + * @return All relationships of the type specified by the filter. + */ + public PackageRelationshipCollection GetRelationships(String typeFilter) { - str = str + "," + sourcePart.PartName; - } else { - str = str + ",sourcePart=null"; - } - if (partName != null) { - str = str + "," + partName; - } else { - str = str + ",uri=null)"; - } - return str + "]"; - } - - #region IEnumerator Members - - PackageRelationship IEnumerator.Current - { - get { throw new NotImplementedException(); } - } + PackageRelationshipCollection coll = new PackageRelationshipCollection( + this, typeFilter); + return coll; + } - #endregion + /** + * Get this collection's iterator. + */ + public IEnumerator GetEnumerator() + { + return relationshipsByID.Values.GetEnumerator(); + } - #region IDisposable Members + /** + * Get an iterator of a collection with all relationship with the specified + * type. + * + * @param typeFilter + * Type filter. + * @return An iterator to a collection containing all relationships with the + * specified type contain in this collection. + */ + public IEnumerator Iterator(String typeFilter) + { + List retArr = new List(); + foreach (PackageRelationship rel in relationshipsByID.Values) + { + if (rel.RelationshipType.Equals(typeFilter)) + retArr.Add(rel); + } + return retArr.GetEnumerator(); + } - void IDisposable.Dispose() - { - //relationshipsByID=null; - //relationshipsByType = null; - } + /** + * Clear all relationships. + */ + public void Clear() + { + relationshipsByID.Clear(); + relationshipsByType.Clear(); + } - #endregion + public override String ToString() + { + String str; + if (relationshipsByID == null) + { + str = "relationshipsByID=null"; + } + else + { + str = relationshipsByID.Count + " relationship(s) = ["; + } + if ((relationshipPart != null) && (relationshipPart.PartName != null)) + { + str = str + "," + relationshipPart.PartName; + } + else + { + str = str + ",relationshipPart=null"; + } - #region IEnumerator Members + // Source of this relationship + if ((sourcePart != null) && (sourcePart.PartName != null)) + { + str = str + "," + sourcePart.PartName; + } + else + { + str = str + ",sourcePart=null"; + } + if (partName != null) + { + str = str + "," + partName; + } + else + { + str = str + ",uri=null)"; + } + return str + "]"; + } - object System.Collections.IEnumerator.Current - { - get { throw new NotImplementedException(); } - } + #region IEnumerator Members - bool System.Collections.IEnumerator.MoveNext() - { - throw new NotImplementedException(); - } + PackageRelationship IEnumerator.Current + { + get { throw new NotImplementedException(); } + } - void System.Collections.IEnumerator.Reset() - { - Clear(); - } + #endregion - #endregion + #region IDisposable Members + + void IDisposable.Dispose() + { + //relationshipsByID=null; + //relationshipsByType = null; + } + + #endregion + + #region IEnumerator Members + + object System.Collections.IEnumerator.Current + { + get { throw new NotImplementedException(); } + } + + bool System.Collections.IEnumerator.MoveNext() + { + throw new NotImplementedException(); + } + + void System.Collections.IEnumerator.Reset() + { + Clear(); + } + + #endregion } } diff --git a/testcases/openxml4net/TestRelationships.cs b/testcases/openxml4net/TestRelationships.cs index bf9e9b545..18e175b18 100644 --- a/testcases/openxml4net/TestRelationships.cs +++ b/testcases/openxml4net/TestRelationships.cs @@ -29,12 +29,12 @@ namespace TestCases.OPC [TestFixture] public class TestRelationships { - private static String HYPERLINK_REL_TYPE = - "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink"; - private static String COMMENTS_REL_TYPE = - "http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments"; - private static String SHEET_WITH_COMMENTS = - "/xl/worksheets/sheet1.xml"; + private static String HYPERLINK_REL_TYPE = + "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink"; + private static String COMMENTS_REL_TYPE = + "http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments"; + private static String SHEET_WITH_COMMENTS = + "/xl/worksheets/sheet1.xml"; private static POILogger logger = POILogFactory.GetLogger(typeof(TestPackageCoreProperties)); @@ -71,7 +71,7 @@ public void TestFetchFromCollection() { Stream is1 = OpenXml4NetTestDataSamples.OpenSampleStream("ExcelWithHyperlinks.xlsx"); OPCPackage pkg = OPCPackage.Open(is1); PackagePart sheet = pkg.GetPart( - PackagingUriHelper.CreatePartName(SHEET_WITH_COMMENTS)); + PackagingUriHelper.CreatePartName(SHEET_WITH_COMMENTS)); Assert.IsNotNull(sheet); Assert.IsTrue(sheet.HasRelationships); @@ -79,9 +79,9 @@ public void TestFetchFromCollection() { // Should have three hyperlinks, and one comment PackageRelationshipCollection hyperlinks = - sheet.GetRelationshipsByType(HYPERLINK_REL_TYPE); + sheet.GetRelationshipsByType(HYPERLINK_REL_TYPE); PackageRelationshipCollection comments = - sheet.GetRelationshipsByType(COMMENTS_REL_TYPE); + sheet.GetRelationshipsByType(COMMENTS_REL_TYPE); Assert.AreEqual(3, hyperlinks.Size); Assert.AreEqual(1, comments.Size); @@ -112,30 +112,30 @@ public void TestFetchFromCollection() { public void TestLoadExcelHyperlinkRelations() { Stream is1 = OpenXml4NetTestDataSamples.OpenSampleStream("ExcelWithHyperlinks.xlsx"); OPCPackage pkg = OPCPackage.Open(is1); - PackagePart sheet = pkg.GetPart( - PackagingUriHelper.CreatePartName(SHEET_WITH_COMMENTS)); - Assert.IsNotNull(sheet); - - // rId1 is url - PackageRelationship url = sheet.GetRelationship("rId1"); - Assert.IsNotNull(url); - Assert.AreEqual("rId1", url.Id); - Assert.AreEqual("/xl/worksheets/sheet1.xml", url.SourceUri.ToString()); - Assert.AreEqual("http://poi.apache.org/", url.TargetUri.ToString()); - - // rId2 is file - PackageRelationship file = sheet.GetRelationship("rId2"); - Assert.IsNotNull(file); - Assert.AreEqual("rId2", file.Id); - Assert.AreEqual("/xl/worksheets/sheet1.xml", file.SourceUri.ToString()); - Assert.AreEqual("WithVariousData.xlsx", file.TargetUri.ToString()); - - // rId3 is mailto - PackageRelationship mailto = sheet.GetRelationship("rId3"); - Assert.IsNotNull(mailto); - Assert.AreEqual("rId3", mailto.Id); - Assert.AreEqual("/xl/worksheets/sheet1.xml", mailto.SourceUri.ToString()); - Assert.AreEqual("mailto:dev@poi.apache.org?subject=XSSF%20Hyperlinks", mailto.TargetUri.AbsoluteUri); + PackagePart sheet = pkg.GetPart( + PackagingUriHelper.CreatePartName(SHEET_WITH_COMMENTS)); + Assert.IsNotNull(sheet); + + // rId1 is url + PackageRelationship url = sheet.GetRelationship("rId1"); + Assert.IsNotNull(url); + Assert.AreEqual("rId1", url.Id); + Assert.AreEqual("/xl/worksheets/sheet1.xml", url.SourceUri.ToString()); + Assert.AreEqual("http://poi.apache.org/", url.TargetUri.ToString()); + + // rId2 is file + PackageRelationship file = sheet.GetRelationship("rId2"); + Assert.IsNotNull(file); + Assert.AreEqual("rId2", file.Id); + Assert.AreEqual("/xl/worksheets/sheet1.xml", file.SourceUri.ToString()); + Assert.AreEqual("WithVariousData.xlsx", file.TargetUri.ToString()); + + // rId3 is mailto + PackageRelationship mailto = sheet.GetRelationship("rId3"); + Assert.IsNotNull(mailto); + Assert.AreEqual("rId3", mailto.Id); + Assert.AreEqual("/xl/worksheets/sheet1.xml", mailto.SourceUri.ToString()); + Assert.AreEqual("mailto:dev@poi.apache.org?subject=XSSF%20Hyperlinks", mailto.TargetUri.AbsoluteUri); } /* @@ -145,120 +145,138 @@ public void TestLoadExcelHyperlinkRelations() { */ [Test] public void TestCreateExcelHyperlinkRelations() { - String filepath = OpenXml4NetTestDataSamples.GetSampleFileName("ExcelWithHyperlinks.xlsx"); - OPCPackage pkg = OPCPackage.Open(filepath, PackageAccess.READ_WRITE); - PackagePart sheet = pkg.GetPart( - PackagingUriHelper.CreatePartName(SHEET_WITH_COMMENTS)); - Assert.IsNotNull(sheet); - - Assert.AreEqual(3, sheet.GetRelationshipsByType(HYPERLINK_REL_TYPE).Size); - - // Add three new ones - PackageRelationship openxml4j = - sheet.AddExternalRelationship("http://www.Openxml4j.org/", HYPERLINK_REL_TYPE); - PackageRelationship sf = - sheet.AddExternalRelationship("http://openxml4j.sf.net/", HYPERLINK_REL_TYPE); - PackageRelationship file = - sheet.AddExternalRelationship("MyDocument.docx", HYPERLINK_REL_TYPE); - - // Check they were Added properly - Assert.IsNotNull(openxml4j); - Assert.IsNotNull(sf); - Assert.IsNotNull(file); - - Assert.AreEqual(6, sheet.GetRelationshipsByType(HYPERLINK_REL_TYPE).Size); - - Assert.AreEqual("http://www.openxml4j.org/", openxml4j.TargetUri.ToString()); - Assert.AreEqual("/xl/worksheets/sheet1.xml", openxml4j.SourceUri.ToString()); - Assert.AreEqual(HYPERLINK_REL_TYPE, openxml4j.RelationshipType); - - Assert.AreEqual("http://openxml4j.sf.net/", sf.TargetUri.ToString()); - Assert.AreEqual("/xl/worksheets/sheet1.xml", sf.SourceUri.ToString()); - Assert.AreEqual(HYPERLINK_REL_TYPE, sf.RelationshipType); - - Assert.AreEqual("MyDocument.docx", file.TargetUri.ToString()); - Assert.AreEqual("/xl/worksheets/sheet1.xml", file.SourceUri.ToString()); - Assert.AreEqual(HYPERLINK_REL_TYPE, file.RelationshipType); - - // Will Get ids 7, 8 and 9, as we already have 1-6 - Assert.AreEqual("rId7", openxml4j.Id); - Assert.AreEqual("rId8", sf.Id); - Assert.AreEqual("rId9", file.Id); - - - // Write out and re-load - MemoryStream baos = new MemoryStream(); - pkg.Save(baos); - MemoryStream bais = new MemoryStream(baos.ToArray()); - pkg = OPCPackage.Open(bais); - - // Check again - sheet = pkg.GetPart( - PackagingUriHelper.CreatePartName(SHEET_WITH_COMMENTS)); - - Assert.AreEqual(6, sheet.GetRelationshipsByType(HYPERLINK_REL_TYPE).Size); - - Assert.AreEqual("http://poi.apache.org/", - sheet.GetRelationship("rId1").TargetUri.ToString()); - Assert.AreEqual("mailto:dev@poi.apache.org?subject=XSSF Hyperlinks", - sheet.GetRelationship("rId3").TargetUri.ToString()); - - Assert.AreEqual("http://www.openxml4j.org/", - sheet.GetRelationship("rId7").TargetUri.ToString()); - Assert.AreEqual("http://openxml4j.sf.net/", - sheet.GetRelationship("rId8").TargetUri.ToString()); - Assert.AreEqual("MyDocument.docx", - sheet.GetRelationship("rId9").TargetUri.ToString()); + String filepath = OpenXml4NetTestDataSamples.GetSampleFileName("ExcelWithHyperlinks.xlsx"); + OPCPackage pkg = OPCPackage.Open(filepath, PackageAccess.READ_WRITE); + PackagePart sheet = pkg.GetPart( + PackagingUriHelper.CreatePartName(SHEET_WITH_COMMENTS)); + Assert.IsNotNull(sheet); + + Assert.AreEqual(3, sheet.GetRelationshipsByType(HYPERLINK_REL_TYPE).Size); + + // Add three new ones + PackageRelationship openxml4j = + sheet.AddExternalRelationship("http://www.Openxml4j.org/", HYPERLINK_REL_TYPE); + PackageRelationship sf = + sheet.AddExternalRelationship("http://openxml4j.sf.net/", HYPERLINK_REL_TYPE); + PackageRelationship file = + sheet.AddExternalRelationship("MyDocument.docx", HYPERLINK_REL_TYPE); + + // Check they were Added properly + Assert.IsNotNull(openxml4j); + Assert.IsNotNull(sf); + Assert.IsNotNull(file); + + Assert.AreEqual(6, sheet.GetRelationshipsByType(HYPERLINK_REL_TYPE).Size); + + Assert.AreEqual("http://www.openxml4j.org/", openxml4j.TargetUri.ToString()); + Assert.AreEqual("/xl/worksheets/sheet1.xml", openxml4j.SourceUri.ToString()); + Assert.AreEqual(HYPERLINK_REL_TYPE, openxml4j.RelationshipType); + + Assert.AreEqual("http://openxml4j.sf.net/", sf.TargetUri.ToString()); + Assert.AreEqual("/xl/worksheets/sheet1.xml", sf.SourceUri.ToString()); + Assert.AreEqual(HYPERLINK_REL_TYPE, sf.RelationshipType); + + Assert.AreEqual("MyDocument.docx", file.TargetUri.ToString()); + Assert.AreEqual("/xl/worksheets/sheet1.xml", file.SourceUri.ToString()); + Assert.AreEqual(HYPERLINK_REL_TYPE, file.RelationshipType); + + // Will Get ids 7, 8 and 9, as we already have 1-6 + Assert.AreEqual("rId7", openxml4j.Id); + Assert.AreEqual("rId8", sf.Id); + Assert.AreEqual("rId9", file.Id); + + + // Write out and re-load + MemoryStream baos = new MemoryStream(); + pkg.Save(baos); + MemoryStream bais = new MemoryStream(baos.ToArray()); + pkg = OPCPackage.Open(bais); + + // Check again + sheet = pkg.GetPart( + PackagingUriHelper.CreatePartName(SHEET_WITH_COMMENTS)); + + Assert.AreEqual(6, sheet.GetRelationshipsByType(HYPERLINK_REL_TYPE).Size); + + Assert.AreEqual("http://poi.apache.org/", + sheet.GetRelationship("rId1").TargetUri.ToString()); + Assert.AreEqual("mailto:dev@poi.apache.org?subject=XSSF Hyperlinks", + sheet.GetRelationship("rId3").TargetUri.ToString()); + + Assert.AreEqual("http://www.openxml4j.org/", + sheet.GetRelationship("rId7").TargetUri.ToString()); + Assert.AreEqual("http://openxml4j.sf.net/", + sheet.GetRelationship("rId8").TargetUri.ToString()); + Assert.AreEqual("MyDocument.docx", + sheet.GetRelationship("rId9").TargetUri.ToString()); } [Test] public void TestCreateRelationsFromScratch() { - MemoryStream baos = new MemoryStream(); - OPCPackage pkg = OPCPackage.Create(baos); - - PackagePart partA = - pkg.CreatePart(PackagingUriHelper.CreatePartName("/partA"), "text/plain"); - PackagePart partB = - pkg.CreatePart(PackagingUriHelper.CreatePartName("/partB"), "image/png"); - Assert.IsNotNull(partA); - Assert.IsNotNull(partB); - - // Internal - partA.AddRelationship(partB.PartName, TargetMode.Internal, "http://example/Rel"); - - // External - partA.AddExternalRelationship("http://poi.apache.org/", "http://example/poi"); - partB.AddExternalRelationship("http://poi.apache.org/ss/", "http://example/poi/ss"); - - // Check as expected currently - Assert.AreEqual("/partB", partA.GetRelationship("rId1").TargetUri.ToString()); - Assert.AreEqual("http://poi.apache.org/", - partA.GetRelationship("rId2").TargetUri.ToString()); - Assert.AreEqual("http://poi.apache.org/ss/", - partB.GetRelationship("rId1").TargetUri.ToString()); - - - // Save, and re-load - pkg.Close(); - MemoryStream bais = new MemoryStream(baos.ToArray()); - pkg = OPCPackage.Open(bais); - - partA = pkg.GetPart(PackagingUriHelper.CreatePartName("/partA")); - partB = pkg.GetPart(PackagingUriHelper.CreatePartName("/partB")); - - - // Check the relations - Assert.AreEqual(2, partA.Relationships.Size); - Assert.AreEqual(1, partB.Relationships.Size); - - Assert.AreEqual("/partB", partA.GetRelationship("rId1").TargetUri.OriginalString); - Assert.AreEqual("http://poi.apache.org/", - partA.GetRelationship("rId2").TargetUri.ToString()); - Assert.AreEqual("http://poi.apache.org/ss/", - partB.GetRelationship("rId1").TargetUri.ToString()); - // Check core too - Assert.AreEqual("/docProps/core.xml", - pkg.GetRelationshipsByType( + MemoryStream baos = new MemoryStream(); + OPCPackage pkg = OPCPackage.Create(baos); + + PackagePart partA = + pkg.CreatePart(PackagingUriHelper.CreatePartName("/partA"), "text/plain"); + PackagePart partB = + pkg.CreatePart(PackagingUriHelper.CreatePartName("/partB"), "image/png"); + Assert.IsNotNull(partA); + Assert.IsNotNull(partB); + + // Internal + partA.AddRelationship(partB.PartName, TargetMode.Internal, "http://example/Rel"); + + // External + partA.AddExternalRelationship("http://poi.apache.org/", "http://example/poi"); + partB.AddExternalRelationship("http://poi.apache.org/ss/", "http://example/poi/ss"); + + // Check as expected currently + Assert.AreEqual("/partB", partA.GetRelationship("rId1").TargetUri.ToString()); + Assert.AreEqual("http://poi.apache.org/", + partA.GetRelationship("rId2").TargetUri.ToString()); + Assert.AreEqual("http://poi.apache.org/ss/", + partB.GetRelationship("rId1").TargetUri.ToString()); + + + // Save, and re-load + pkg.Close(); + MemoryStream bais = new MemoryStream(baos.ToArray()); + pkg = OPCPackage.Open(bais); + + partA = pkg.GetPart(PackagingUriHelper.CreatePartName("/partA")); + partB = pkg.GetPart(PackagingUriHelper.CreatePartName("/partB")); + + + // Check the relations + Assert.AreEqual(2, partA.Relationships.Size); + Assert.AreEqual(1, partB.Relationships.Size); + + Assert.AreEqual("/partB", partA.GetRelationship("rId1").TargetUri.OriginalString); + Assert.AreEqual("http://poi.apache.org/", + partA.GetRelationship("rId2").TargetUri.ToString()); + Assert.AreEqual("http://poi.apache.org/ss/", + partB.GetRelationship("rId1").TargetUri.ToString()); + // Check core too + Assert.AreEqual("/docProps/core.xml", + pkg.GetRelationshipsByType( "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties").GetRelationship(0).TargetUri.ToString()); + + // Add some more + partB.AddExternalRelationship("http://poi.apache.org/new", "http://example/poi/new"); + partB.AddExternalRelationship("http://poi.apache.org/alt", "http://example/poi/alt"); + + // Check the relations + Assert.AreEqual(2, partA.Relationships.Size); + Assert.AreEqual(3, partB.Relationships.Size); + + Assert.AreEqual("/partB", partA.GetRelationship("rId1").TargetUri.OriginalString); + Assert.AreEqual("http://poi.apache.org/", + partA.GetRelationship("rId2").TargetUri.OriginalString); + Assert.AreEqual("http://poi.apache.org/ss/", + partB.GetRelationship("rId1").TargetUri.OriginalString); + Assert.AreEqual("http://poi.apache.org/new", + partB.GetRelationship("rId2").TargetUri.OriginalString); + Assert.AreEqual("http://poi.apache.org/alt", + partB.GetRelationship("rId3").TargetUri.OriginalString); } [Test]