public void RemoveImage(string id)
        {
            if (id == null)
            {
                throw new ArgumentNullException("id");
            }
            if (id.Length == 0)
            {
                return;
            }

            if (!_part.RelationshipExists(id))
            {
                return;
            }

            PackageRelationship imageRel = _part.GetRelationship(id);

            Uri imageUri = PackUriHelper.ResolvePartUri(imageRel.SourceUri, imageRel.TargetUri);

            if (_part.Package.PartExists(imageUri))
            {
                _part.Package.DeletePart(imageUri);
            }

            _part.DeleteRelationship(id);
        }
Ejemplo n.º 2
0
        private void ClearPackagePartsWithRelationshipType(string relType, PackagePart parent, string partUri)
        {
            PackageRelationshipCollection rels = parent == null?Package.GetRelationshipsByType(relType) : parent.GetRelationshipsByType(relType);

            List <string> relIds = new List <string>();

            foreach (PackageRelationship r in rels)
            {
                if (r.TargetMode == TargetMode.Internal)
                {
                    if (partUri == null || r.TargetUri.ToString() == partUri)
                    {
                        Package.DeletePart(r.TargetUri);
                        relIds.Add(r.Id);
                    }
                }
            }

            foreach (string relId in relIds)
            {
                if (parent == null)
                {
                    Package.DeleteRelationship(relId);
                }
                else
                {
                    parent.DeleteRelationship(relId);
                }
            }
        }
Ejemplo n.º 3
0
        public void RelationshipPartGetRelationships()
        {
            CheckAutomaticParts2();
            PackagePart p = package.GetPart(relationshipUri);

            try
            {
                p.CreateRelationship(uris[0], TargetMode.Internal, "asdas");
                Assert.Fail("This should fail 1");
            }
            catch (InvalidOperationException)
            {
            }

            try
            {
                p.DeleteRelationship("aa");
                Assert.Fail("This should fail 2");
            }
            catch (InvalidOperationException)
            {
            }

            try
            {
                p.GetRelationship("id");
                Assert.Fail("This should fail 3");
            }
            catch (InvalidOperationException)
            {
            }

            try
            {
                p.GetRelationships();
                Assert.Fail("This should fail 4");
            }
            catch (InvalidOperationException)
            {
            }

            try
            {
                p.GetRelationshipsByType("type");
                Assert.Fail("This should fail 5");
            }
            catch (InvalidOperationException)
            {
            }

            try
            {
                p.RelationshipExists("id");
                Assert.Fail("This should fail 6");
            }
            catch (InvalidOperationException)
            {
            }
        }
Ejemplo n.º 4
0
        private void ClearRelationshipsAndPartFromPackagePart(PackagePart sourcePackagePart, string relationshipType)
        {
            PackageRelationshipCollection relationships = sourcePackagePart.GetRelationshipsByType(relationshipType);

            foreach (var relationship in relationships.ToList())
            {
                sourcePackagePart.DeleteRelationship(relationship.Id);

                if (aasxPackage.PartExists(relationship.TargetUri))
                {
                    aasxPackage.DeletePart(relationship.TargetUri);
                }
            }
        }
Ejemplo n.º 5
0
        private void ProcessRelationsips(object owner, PackageRelationshipCollection rels)
        {
            List <PackageRelationship> list = new List <PackageRelationship>();

            foreach (PackageRelationship item in rels)
            {
                list.Add(item);
            }
            if (owner is Package)
            {
                Package package = (Package)owner;
                foreach (PackageRelationship packageRelationship in list)
                {
                    package.DeleteRelationship(packageRelationship.Id);
                }
                using (List <PackageRelationship> .Enumerator enumerator2 = list.GetEnumerator())
                {
                    while (enumerator2.MoveNext())
                    {
                        PackageRelationship packageRelationship2 = enumerator2.Current;
                        package.CreateRelationship(packageRelationship2.TargetUri, packageRelationship2.TargetMode, _xpsConstants.ConvertRelationshipType(packageRelationship2.RelationshipType), packageRelationship2.Id);
                    }
                    return;
                }
            }
            if (owner is PackagePart)
            {
                PackagePart packagePart = (PackagePart)owner;
                foreach (PackageRelationship packageRelationship3 in list)
                {
                    packagePart.DeleteRelationship(packageRelationship3.Id);
                }
                using (List <PackageRelationship> .Enumerator enumerator2 = list.GetEnumerator())
                {
                    while (enumerator2.MoveNext())
                    {
                        PackageRelationship packageRelationship4 = enumerator2.Current;
                        packagePart.CreateRelationship(packageRelationship4.TargetUri, packageRelationship4.TargetMode, _xpsConstants.ConvertRelationshipType(packageRelationship4.RelationshipType), packageRelationship4.Id);
                    }
                    return;
                }
            }
            throw new ArgumentException("Owner must be a Package or a PackagePart instance.");
        }
        public bool SaveAs(string fn, bool writeFreshly = false, PreferredFormat prefFmt = PreferredFormat.None, MemoryStream useMemoryStream = null)
        {
            Console.WriteLine("SaveAs: " + fn);
            if (fn.ToLower().EndsWith(".xml"))
            {
                // save only XML
                this.fn = fn;
                try
                {
                    using (var s = new StreamWriter(this.fn))
                    {
                        // TODO: use aasenv serialzers here!
                        var serializer = new XmlSerializer(typeof(AdminShell.AdministrationShellEnv));
                        var nss        = new XmlSerializerNamespaces();
                        nss.Add("xsi", System.Xml.Schema.XmlSchema.InstanceNamespace);
                        nss.Add("aas", "http://www.admin-shell.io/aas/2/0");
                        nss.Add("IEC61360", "http://www.admin-shell.io/IEC61360/2/0");
                        serializer.Serialize(s, this.aasenv, nss);
                    }
                }
                catch (Exception ex)
                {
                    throw (new Exception(string.Format("While writing AAS {0} at {1} gave: {2}", fn, AdminShellUtil.ShortLocation(ex), ex.Message)));
                }
                return(true);
            }

            if (fn.ToLower().EndsWith(".json"))
            {
                // save only JSON
                // this funcitonality is a initial test
                this.fn = fn;
                try
                {
                    using (var sw = new StreamWriter(fn))
                    {
                        // TODO: use aasenv serialzers here!

                        sw.AutoFlush = true;

                        JsonSerializer serializer = new JsonSerializer()
                        {
                            NullValueHandling     = NullValueHandling.Ignore,
                            ReferenceLoopHandling = ReferenceLoopHandling.Serialize,
                            Formatting            = Newtonsoft.Json.Formatting.Indented
                        };
                        using (JsonWriter writer = new JsonTextWriter(sw))
                        {
                            serializer.Serialize(writer, this.aasenv);
                        }
                    }
                }
                catch (Exception ex)
                {
                    throw (new Exception(string.Format("While writing AAS {0} at {1} gave: {2}", fn, AdminShellUtil.ShortLocation(ex), ex.Message)));
                }
                return(true);
            }

            if (fn.ToLower().EndsWith(".aasx"))
            {
                // save package AASX
                try
                {
                    // we want existing contents to be preserved, but no possiblity to change file name
                    // therefore: copy file to new name, re-open!
                    // fn could be changed, therefore close "old" package first
                    if (this.openPackage != null)
                    {
                        // ReSharper disable EmptyGeneralCatchClause
                        try
                        {
                            this.openPackage.Close();
                            if (!writeFreshly)
                            {
                                if (this.tempFn != null)
                                {
                                    System.IO.File.Copy(this.tempFn, fn);
                                }
                                else
                                {
                                    System.IO.File.Copy(this.fn, fn);
                                }
                            }
                        }
                        catch { }
                        // ReSharper enable EmptyGeneralCatchClause
                        this.openPackage = null;
                    }

                    // approach is to utilize the existing package, if possible. If not, create from scratch
                    Package package = null;
                    if (useMemoryStream != null)
                    {
                        package = Package.Open(useMemoryStream, (writeFreshly) ? FileMode.Create : FileMode.OpenOrCreate);
                    }
                    else
                    {
                        package = Package.Open((this.tempFn != null) ? this.tempFn : fn, (writeFreshly) ? FileMode.Create : FileMode.OpenOrCreate);
                    }
                    this.fn = fn;

                    // get the origin from the package
                    PackagePart originPart = null;
                    var         xs         = package.GetRelationshipsByType("http://www.admin-shell.io/aasx/relationships/aasx-origin");
                    foreach (var x in xs)
                    {
                        if (x.SourceUri.ToString() == "/")
                        {
                            originPart = package.GetPart(x.TargetUri);
                            break;
                        }
                    }
                    if (originPart == null)
                    {
                        // create, as not existing
                        originPart = package.CreatePart(new Uri("/aasx/aasx-origin", UriKind.RelativeOrAbsolute), System.Net.Mime.MediaTypeNames.Text.Plain, CompressionOption.Maximum);
                        using (var s = originPart.GetStream(FileMode.Create))
                        {
                            var bytes = System.Text.Encoding.ASCII.GetBytes("Intentionally empty.");
                            s.Write(bytes, 0, bytes.Length);
                        }
                        package.CreateRelationship(originPart.Uri, TargetMode.Internal, "http://www.admin-shell.io/aasx/relationships/aasx-origin");
                    }

                    // get the specs from the package
                    PackagePart         specPart = null;
                    PackageRelationship specRel  = null;
                    xs = originPart.GetRelationshipsByType("http://www.admin-shell.io/aasx/relationships/aas-spec");
                    foreach (var x in xs)
                    {
                        specRel  = x;
                        specPart = package.GetPart(x.TargetUri);
                        break;
                    }

                    // check, if we have to change the spec part
                    if (specPart != null && specRel != null)
                    {
                        var name = System.IO.Path.GetFileNameWithoutExtension(specPart.Uri.ToString()).ToLower().Trim();
                        var ext  = System.IO.Path.GetExtension(specPart.Uri.ToString()).ToLower().Trim();
                        if ((ext == ".json" && prefFmt == PreferredFormat.Xml) ||
                            (ext == ".xml" && prefFmt == PreferredFormat.Json) ||
                            (name.StartsWith("aasenv-with-no-id")))
                        {
                            // try kill specpart
                            // ReSharper disable EmptyGeneralCatchClause
                            try
                            {
                                originPart.DeleteRelationship(specRel.Id);
                                package.DeletePart(specPart.Uri);
                            }
                            catch { }
                            finally { specPart = null; specRel = null; }
                            // ReSharper enable EmptyGeneralCatchClause
                        }
                    }

                    if (specPart == null)
                    {
                        // create, as not existing
                        var frn = "aasenv-with-no-id";
                        if (this.aasenv.AdministrationShells.Count > 0)
                        {
                            frn = this.aasenv.AdministrationShells[0].GetFriendlyName() ?? frn;
                        }
                        var aas_spec_fn = "/aasx/#/#.aas";
                        if (prefFmt == PreferredFormat.Json)
                        {
                            aas_spec_fn += ".json";
                        }
                        else
                        {
                            aas_spec_fn += ".xml";
                        }
                        aas_spec_fn = aas_spec_fn.Replace("#", "" + frn);
                        specPart    = package.CreatePart(new Uri(aas_spec_fn, UriKind.RelativeOrAbsolute), System.Net.Mime.MediaTypeNames.Text.Xml, CompressionOption.Maximum);
                        originPart.CreateRelationship(specPart.Uri, TargetMode.Internal, "http://www.admin-shell.io/aasx/relationships/aas-spec");
                    }

                    // now, specPart shall be != null!
                    if (specPart.Uri.ToString().ToLower().Trim().EndsWith("json"))
                    {
                        using (var s = specPart.GetStream(FileMode.Create))
                        {
                            JsonSerializer serializer = new JsonSerializer();
                            serializer.NullValueHandling     = NullValueHandling.Ignore;
                            serializer.ReferenceLoopHandling = ReferenceLoopHandling.Serialize;
                            serializer.Formatting            = Newtonsoft.Json.Formatting.Indented;
                            using (var sw = new StreamWriter(s))
                            {
                                using (JsonWriter writer = new JsonTextWriter(sw))
                                {
                                    serializer.Serialize(writer, this.aasenv);
                                }
                            }
                        }
                    }
                    else
                    {
                        using (var s = specPart.GetStream(FileMode.Create))
                        {
                            var serializer = new XmlSerializer(typeof(AdminShell.AdministrationShellEnv));
                            var nss        = new XmlSerializerNamespaces();
                            nss.Add("xsi", System.Xml.Schema.XmlSchema.InstanceNamespace);
                            nss.Add("aas", "http://www.admin-shell.io/aas/2/0");
                            nss.Add("IEC61360", "http://www.admin-shell.io/IEC61360/2/0");
                            serializer.Serialize(s, this.aasenv, nss);
                        }
                    }

                    // there might be pending files to be deleted (first delete, then add, in case of identical files in both categories)
                    foreach (var psfDel in pendingFilesToDelete)
                    {
                        // try find an existing part for that file ..
                        var found = false;

                        // normal files
                        xs = specPart.GetRelationshipsByType("http://www.admin-shell.io/aasx/relationships/aas-suppl");
                        foreach (var x in xs)
                        {
                            if (x.TargetUri == psfDel.uri)
                            {
                                // try to delete
                                specPart.DeleteRelationship(x.Id);
                                package.DeletePart(psfDel.uri);
                                found = true;
                                break;
                            }
                        }

                        // thumbnails
                        xs = package.GetRelationshipsByType("http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail");
                        foreach (var x in xs)
                        {
                            if (x.TargetUri == psfDel.uri)
                            {
                                // try to delete
                                package.DeleteRelationship(x.Id);
                                package.DeletePart(psfDel.uri);
                                found = true;
                                break;
                            }
                        }

                        if (!found)
                        {
                            throw (new Exception($"Not able to delete pending file {psfDel.uri} in saving package {fn}"));
                        }
                    }

                    // after this, there are no more pending for delete files
                    pendingFilesToDelete.Clear();

                    // write pending supplementary files
                    foreach (var psfAdd in pendingFilesToAdd)
                    {
                        // make sure ..
                        if ((psfAdd.sourceLocalPath == null && psfAdd.sourceGetBytesDel == null) || psfAdd.location != AdminShellPackageSupplementaryFile.LocationType.AddPending)
                        {
                            continue;
                        }

                        // normal file?
                        if (psfAdd.specialHandling == AdminShellPackageSupplementaryFile.SpecialHandlingType.None ||
                            psfAdd.specialHandling == AdminShellPackageSupplementaryFile.SpecialHandlingType.EmbedAsThumbnail)
                        {
                            // try find an existing part for that file ..
                            PackagePart filePart = null;
                            if (psfAdd.specialHandling == AdminShellPackageSupplementaryFile.SpecialHandlingType.None)
                            {
                                xs = specPart.GetRelationshipsByType("http://www.admin-shell.io/aasx/relationships/aas-suppl");
                                foreach (var x in xs)
                                {
                                    if (x.TargetUri == psfAdd.uri)
                                    {
                                        filePart = package.GetPart(x.TargetUri);
                                        break;
                                    }
                                }
                            }
                            if (psfAdd.specialHandling == AdminShellPackageSupplementaryFile.SpecialHandlingType.EmbedAsThumbnail)
                            {
                                xs = package.GetRelationshipsByType("http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail");
                                foreach (var x in xs)
                                {
                                    if (x.SourceUri.ToString() == "/" && x.TargetUri == psfAdd.uri)
                                    {
                                        filePart = package.GetPart(x.TargetUri);
                                        break;
                                    }
                                }
                            }

                            if (filePart == null)
                            {
                                // determine mimeType
                                var mimeType = psfAdd.useMimeType;
                                // reconcile mime
                                if (mimeType == null && psfAdd.sourceLocalPath != null)
                                {
                                    mimeType = AdminShellPackageEnv.GuessMimeType(psfAdd.sourceLocalPath);
                                }
                                // still null?
                                if (mimeType == null)
                                {
                                    // see: https://stackoverflow.com/questions/6783921/which-mime-type-to-use-for-a-binary-file-thats-specific-to-my-program
                                    mimeType = "application/octet-stream";
                                }

                                // create new part and link
                                filePart = package.CreatePart(psfAdd.uri, mimeType, CompressionOption.Maximum);
                                if (psfAdd.specialHandling == AdminShellPackageSupplementaryFile.SpecialHandlingType.None)
                                {
                                    specPart.CreateRelationship(filePart.Uri, TargetMode.Internal, "http://www.admin-shell.io/aasx/relationships/aas-suppl");
                                }
                                if (psfAdd.specialHandling == AdminShellPackageSupplementaryFile.SpecialHandlingType.EmbedAsThumbnail)
                                {
                                    package.CreateRelationship(filePart.Uri, TargetMode.Internal, "http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail");
                                }
                            }

                            // now should be able to write
                            using (var s = filePart.GetStream(FileMode.Create))
                            {
                                if (psfAdd.sourceLocalPath != null)
                                {
                                    var bytes = System.IO.File.ReadAllBytes(psfAdd.sourceLocalPath);
                                    s.Write(bytes, 0, bytes.Length);
                                }

                                if (psfAdd.sourceGetBytesDel != null)
                                {
                                    var bytes = psfAdd.sourceGetBytesDel();
                                    if (bytes != null)
                                    {
                                        s.Write(bytes, 0, bytes.Length);
                                    }
                                }
                            }
                        }
                    }

                    // after this, there are no more pending for add files
                    pendingFilesToAdd.Clear();

                    // flush and close
                    package.Flush();
                    this.openPackage = null;
                    package.Close();

                    // if in temp fn, close the package, copy to original fn, re-open the package
                    if (this.tempFn != null)
                    {
                        try
                        {
                            package.Close();
                            System.IO.File.Copy(this.tempFn, this.fn, overwrite: true);
                            this.openPackage = Package.Open(this.tempFn, FileMode.OpenOrCreate);
                        }
                        catch (Exception ex)
                        {
                            throw (new Exception(string.Format("While write AASX {0} indirectly at {1} gave: {2}", fn, AdminShellUtil.ShortLocation(ex), ex.Message)));
                        }
                    }
                }
                catch (Exception ex)
                {
                    throw (new Exception(string.Format("While write AASX {0} at {1} gave: {2}", fn, AdminShellUtil.ShortLocation(ex), ex.Message)));
                }
                return(true);
            }

            // Don't know to handle
            throw (new Exception(string.Format($"Not able to handle {fn}.")));
        }
Ejemplo n.º 7
0
        internal sealed override void DeleteRelationship(string id)
        {
            ThrowIfObjectDisposed();

            PackagePart.DeleteRelationship(id);
        }
Ejemplo n.º 8
0
        public void Sanitize(string packagePath)
        {
            try
            {
                //Open the package
                using (Package package = Package.Open(packagePath, FileMode.Open, FileAccess.ReadWrite))
                {

                    //Get the document part
                    Uri uriDocument = new Uri(docUri, UriKind.Relative);
                    PackagePart documentPart = package.GetPart(uriDocument);

                    //Load the document part into a stream
                    Stream partStream = documentPart.GetStream(FileMode.Open, FileAccess.ReadWrite);

                    //Add the namespace manager to reference the Word namespace
                    NameTable nameTable = new NameTable();
                    XmlNamespaceManager manager = new XmlNamespaceManager(nameTable);
                    manager.AddNamespace("w", wordSpace);

                    //Create a temporary XML document from the stream
                    //so we can manipulate the XML elements
                    XmlDocument tempDoc = new XmlDocument(nameTable);
                    tempDoc.Load(partStream);

                    //Remove deleted text from temporary XML document
                    XmlNodeList delNodes = tempDoc.SelectNodes("//w:del", manager);
                    foreach (XmlNode delNode in delNodes)
                    {
                        delNode.ParentNode.RemoveChild(delNode);
                    }

                    //Promote the inserted text in temporary XMl document
                    //so it appears normally in the Word document
                    XmlNodeList insNodes = tempDoc.SelectNodes("//w:ins", manager);
                    foreach (XmlNode insNode in insNodes)
                    {
                        foreach (XmlNode childNode in insNode.ChildNodes)
                        {
                            insNode.ParentNode.InsertBefore(childNode, insNode);
                        }

                        insNode.ParentNode.RemoveChild(insNode);
                    }

                    //Remove comments text from temporary XML document
                    //Must remove several different elements to accomplish this
                    XmlNodeList commentStartNodes = tempDoc.SelectNodes(
                                                    "//w:commentRangeStart", manager);
                    foreach (XmlNode commentStartNode in commentStartNodes)
                    {
                        commentStartNode.ParentNode.RemoveChild(commentStartNode);
                    }

                    XmlNodeList commentEndNodes = tempDoc.SelectNodes(
                                                  "//w:commentRangeEnd", manager);
                    foreach (XmlNode commentEndNode in commentEndNodes)
                    {
                        commentEndNode.ParentNode.RemoveChild(commentEndNode);
                    }

                    XmlNodeList commentRefNodes = tempDoc.SelectNodes(
                                                  "//w:commentReference", manager);
                    foreach (XmlNode commentRefNode in commentRefNodes)
                    {
                        commentRefNode.ParentNode.RemoveChild(commentRefNode);
                    }

                    //Save the temporary XMl document changes back to the document part
                    documentPart.GetStream().SetLength(0);
                    tempDoc.Save(documentPart.GetStream());

                    //delete the relationship with the comments part
                    Uri uriComments = new Uri("/word/comments.xml", UriKind.Relative);
                    PackagePart commentsPart = package.GetPart(uriComments);

                    PackageRelationshipCollection relationships = documentPart.GetRelationships();

                    foreach (PackageRelationship relationship in relationships)
                    {
                        if (relationship.TargetUri.ToString() == "comments.xml")
                        {
                            documentPart.DeleteRelationship(relationship.Id);
                            break;
                        }
                    }

                    //Delete comments part from package
                    package.DeletePart(uriComments);

                    //Save the package changes
                    package.Flush();
                    package.Close();

                }
            }
            catch (Exception x)
            {
                LogMessage(x.Message, EventLogEntryType.Error);
            }
        }
Ejemplo n.º 9
0
        private void Apply(Package package, string localFilename, bool installed)
        {
            using (Package setPkg = Package.Open(localFilename, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
            {
                // Extract information about the target set
                PackageRelationship defRelationship =
                    setPkg.GetRelationshipsByType("http://schemas.octgn.org/set/definition").First();
                PackagePart definition = setPkg.GetPart(defRelationship.TargetUri);
                Set         set;
                using (XmlReader reader = XmlReader.Create(definition.GetStream(), XmlSettings))
                {
                    reader.ReadToFollowing("set"); // <?xml ... ?>
                    set = new Set(localFilename, reader, _game.Repository);
                    // Check if the set game matches the patch
                    if (set.Game != _game)
                    {
                        return;
                    }
                }

                // Check if there is a patch for this set
                string relationId = "S" + set.Id.ToString("N");
                if (!package.RelationshipExists(relationId))
                {
                    return;
                }

                PackagePart patchPart = package.GetPart(package.GetRelationship(relationId).TargetUri);
                XDocument   patchDoc;
                using (Stream stream = patchPart.GetStream())
                    patchDoc = XDocument.Load(stream);

                // Check if the set is at least the required version for patching
                if (set.Version < patchDoc.Root.Attr <Version>("minVersion"))
                {
                    return;
                }
                if (set.Version > patchDoc.Root.Attr <Version>("maxVersion"))
                {
                    return;
                }

                if (installed)
                {
                    _game.DeleteSet(_game.Sets.Single(s => s.PackageName == localFilename));
                }

                // Process the set
                if (patchDoc.Root != null)
                {
                    foreach (XElement action in patchDoc.Root.Elements())
                    {
                        switch (action.Name.LocalName)
                        {
                        case "new":
                        {
                            var         targetUri      = new Uri(action.Attr <string>("targetUri"), UriKind.Relative);
                            var         relationshipId = action.Attr <string>("relationshipId");
                            var         contentType    = action.Attr <string>("contentType");
                            PackagePart part           = setPkg.PartExists(targetUri)
                                                           ? setPkg.GetPart(targetUri)
                                                           : setPkg.CreatePart(targetUri, contentType,
                                                                               CompressionOption.Normal);
                            if (part != null)
                            {
                                using (Stream targetStream = part.GetStream(FileMode.Create, FileAccess.Write))
                                    using (
                                        Stream srcStream =
                                            package.GetPart(patchPart.GetRelationship(relationshipId).TargetUri).
                                            GetStream())
                                        srcStream.CopyTo(targetStream);
                            }
                            break;
                        }

                        case "newrel":
                        {
                            var partUri          = new Uri(action.Attr <string>("partUri"), UriKind.Relative);
                            var relationshipId   = action.Attr <string>("relationshipId");
                            var targetUri        = new Uri(action.Attr <string>("targetUri"), UriKind.Relative);
                            var relationshipType = action.Attr <string>("relationshipType");

                            PackagePart part = setPkg.GetPart(partUri);
                            if (part.RelationshipExists(relationshipId))
                            {
                                part.DeleteRelationship(relationshipId);
                            }
                            part.CreateRelationship(targetUri, TargetMode.Internal, relationshipType,
                                                    relationshipId);
                            break;
                        }

                        default:
                            throw new InvalidFileFormatException("Unknown patch action: " + action.Name);
                        }
                    }
                }
            }

            OnProgress(string.Format("{0} patched.", Path.GetFileName(localFilename)));

            if (installed)
            {
                try
                {
                    _game.InstallSet(localFilename);
                }
                catch (Exception ex)
                {
                    OnProgress(string.Format("{0} can't be re-installed.\nDetails: {1}", localFilename, ex.Message),
                               true);
                }
            }
        }