CustomXmlPart samples

I would like to insert a CustomXmlPart and then be able to read it. Is there any sample code showing how to use these classes?

@pmarangoni

Thanks for your inquiry. Please use Document.CustomXmlParts property to get or set the collection of Custom XML Data Storage Parts. You do not normally need to create instances of this class. You can access custom XML data stored in a document via the CustomXmlParts property.

CustomXmlPart class represents a Custom XML Data Storage Part (custom XML data within a package). Plaese use CustomXmlPart.Data property to get or set the XML content of this Custom XML Data Storage Part.

Please check the following code example. Hope this helps you.

Document doc = new Document();

String xmlData = "<Node1>" +
                    "<Node2>" +
                    "   <Node3>Sample text here</Node3>" +
                    "   <Node4>Sample text for n4</Node4>" +
                    "</Node2>" +
                    "</Node1>";

CustomXmlPart myXml = new CustomXmlPart();
myXml.Data = Encoding.ASCII.GetBytes(xmlData);
myXml.Id = "someId";
                 
doc.CustomXmlParts.Add(myXml);

doc.Save(MyDir + "out.docx");

Best Regards,
Tahir Manzoor

Okay, thanks, I managed to get that working. I have a new issue with the Custom XML Data though. If I save the Word document with a new filename, it seems that the Custom XML Data is removed. Is there any way to persist the XML?

@pmarangoni,

Thanks for your inquiry. To ensure a timely and accurate response, please attach the following resources here for testing:

  • Your input Word document.
  • Please attach the output Word file that shows the undesired behavior.
  • Please create a standalone console application (source code without compilation errors) that helps us to reproduce your problem on our end and attach it here for testing.

As soon as you get these pieces of information ready, we’ll start investigation into your issue and provide you more information. Thanks for your cooperation.

Best Regards,
Tahir Manzoor

I think you may have misunderstood my problem.

First of all, I am using Aspose.Word within an asp.net mvc web application. I use it to add some Custom XML to the document. That XML stays with the document as long as the document is not changed. If you rename the Word document using Word (not Aspose) and then use Aspose to check for the XML, it is no longer retrievable. This may be a Microsoft Word issue.

I will try to build a sample to reproduce the problem.

WordDoc.zip (9.2 KB)
Here is some sample code. After running this once, run it again to see that it adds the extra XML. THEN, open the document with Microsoft Word and rename the file. Then update the code to use the new name. You will then see that the Custom XML Part is no longer there:

using Aspose.Words;
using Aspose.Words.Markup;
using System;
using System.Xml;

namespace AsposeWordsTest
{
    class Program
    {
        static void Main(string[] args)
        {
            Aspose.Words.License license = new Aspose.Words.License();

            try
            {
                license.SetLicense("Aspose.Words.lic");
            }
            catch (Exception ex)
            {
                Console.WriteLine("\nThere was an error setting the license: " + ex.Message);
            }

            string fileName = "TestDoc.docx";

            Document doc = new Document(fileName);

            CustomXmlPart xmlLog = doc.CustomXmlParts.GetById("4dd9f51c-f469-4051-82c6-b12cc0d951a8");

            if(xmlLog == null)
            {
                Console.WriteLine("CustomXmlPart was not found.");
                Console.WriteLine("Adding CustomXmlPart now.");

                string xmlUserInfo = "<OutlineLog><Upload><ID>1000</ID><UserId>500</UserId><UploadDate>" + DateTime.Now.ToString() + "</UploadDate></Upload></OutlineLog>";
                xmlLog = new CustomXmlPart();
                xmlLog.Data = System.Text.Encoding.UTF8.GetBytes(xmlUserInfo);
                xmlLog.Id = "4dd9f51c-f469-4051-82c6-b12cc0d951a8";
                doc.CustomXmlParts.Add(xmlLog);
                doc.Save(fileName);
                Console.WriteLine("Added CustomXmlPart successfully.");
            }
            else
            {
                Console.WriteLine("CustomXmlPart WAS found.");
                Console.WriteLine("Adding new data to CustomXmlPart now.");

                XmlDocument outlineLogDoc = new XmlDocument();
                outlineLogDoc.LoadXml(System.Text.Encoding.UTF8.GetString(xmlLog.Data));

                if (outlineLogDoc.SelectSingleNode("/OutlineLog/UnauthorizedUser") == null)
                {
                    XmlNode originalUserID = outlineLogDoc.SelectSingleNode("/OutlineLog/Upload/UserId");
                    XmlNode originalUploadID = outlineLogDoc.SelectSingleNode("/OutlineLog/Upload/ID");
                    XmlNode originalUserUploadDate = outlineLogDoc.SelectSingleNode("/OutlineLog/Upload/UploadDate");

                    string newXmlUserInfo = "<OutlineLog><Upload><ID>" + originalUploadID.InnerText + "</ID><UserId>" + originalUserID.InnerText + "</UserId><UploadDate>" + originalUserUploadDate.InnerText + "</UploadDate></Upload><UnauthorizedUser><UserId>501</UserId><UploadDate>" + DateTime.Now.ToString() + "</UploadDate></UnauthorizedUser></OutlineLog>";

                    doc.CustomXmlParts.GetById("4dd9f51c-f469-4051-82c6-b12cc0d951a8").Data = System.Text.Encoding.UTF8.GetBytes(newXmlUserInfo);
                    doc.Save(fileName);
                }
                Console.WriteLine("New data added to existing CustomXmlPart successfully.");
            }
        }
    }
}

@pmarangoni,

Thanks for sharing the detail. We have tested the scenario and managed to reproduce the same issue at our side. For the sake of correction, we have logged this problem in our issue tracking system as WORDSNET-15586. You will be notified via this forum thread once this issue is resolved.

We apologize for your inconvenience.

Could this be due to the patent infringement suit filed by i4i against Microsoft? Does Word just remove Custom XML Data from the document automatically?

@pmarangoni,

It is to inform you that the issue which you are facing is actually not a bug in Aspose.Words. So, we have closed this issue (WORDSNET-15586) as ‘Not a Bug’.

The correct itemID of CustomXml in MS Word must be enclosed in braces and must be in uppercase. Otherwise, MS Word replaces itemId with a new value in a correct format. So, to solve the problem you should use the following itemId value “{4DD9F51C-F469-4051-82C6-B12CC0D951A8}”.

Document doc = new Document(fileName);

CustomXmlPart xmlLog = doc.CustomXmlParts.GetById("{4DD9F51C-F469-4051-82C6-B12CC0D951A8}");

if (xmlLog == null)
{
    Console.WriteLine("CustomXmlPart was not found.");
    Console.WriteLine("Adding CustomXmlPart now.");

    string xmlUserInfo = "<OutlineLog><Upload><ID>1000</ID><UserId>500</UserId><UploadDate>" + DateTime.Now.ToString() + "</UploadDate></Upload></OutlineLog>";
    xmlLog = new CustomXmlPart();
    xmlLog.Data = System.Text.Encoding.UTF8.GetBytes(xmlUserInfo);
    xmlLog.Id = "{4DD9F51C-F469-4051-82C6-B12CC0D951A8}";
    doc.CustomXmlParts.Add(xmlLog);
    doc.Save(fileName);

    Console.WriteLine("Added CustomXmlPart successfully.");
}
else
{
    Console.WriteLine("CustomXmlPart WAS found.");
    Console.WriteLine("Adding new data to CustomXmlPart now.");

    System.Xml.XmlDocument outlineLogDoc = new System.Xml.XmlDocument();
    outlineLogDoc.LoadXml(System.Text.Encoding.UTF8.GetString(xmlLog.Data));

    if (outlineLogDoc.SelectSingleNode("/OutlineLog/UnauthorizedUser") == null)
    {
        System.Xml.XmlNode originalUserID = outlineLogDoc.SelectSingleNode("/OutlineLog/Upload/UserId");
        System.Xml.XmlNode originalUploadID = outlineLogDoc.SelectSingleNode("/OutlineLog/Upload/ID");
        System.Xml.XmlNode originalUserUploadDate = outlineLogDoc.SelectSingleNode("/OutlineLog/Upload/UploadDate");

        string newXmlUserInfo = "<OutlineLog><Upload><ID>" + originalUploadID.InnerText + "</ID><UserId>" + originalUserID.InnerText + "</UserId><UploadDate>" + originalUserUploadDate.InnerText + "</UploadDate></Upload><UnauthorizedUser><UserId>501</UserId><UploadDate>" + DateTime.Now.ToString() + "</UploadDate></UnauthorizedUser></OutlineLog>";

        doc.CustomXmlParts.GetById("{4DD9F51C-F469-4051-82C6-B12CC0D951A8}").Data = System.Text.Encoding.UTF8.GetBytes(newXmlUserInfo);
        doc.Save(fileName);
    }
    Console.WriteLine("New data added to existing CustomXmlPart successfully.");
}

Best Regards,
Tahir Manzoor

Thank you Tahir, I will try that now.

Thank you so much! It works just as you said. I just needed to make the ID uppercase and wrap it with curly braces.