dotnet OpenXML SDK 新增 CoreFilePropertiesPart 的方法

lindexi發表於2024-09-12

本文記錄在 OpenXML SDK 2.15 版本下,為 PPTX 檔案新增 CoreFilePropertiesPart 的方法,透過本文的方法可以正確且簡單的新增 core.xml 檔案到 PPTX 檔案裡

當前的 OpenXML SDK 存在已知問題,那就是預設情況下生成不包含 core.xml 檔案,請參閱 https://github.com/dotnet/Open-XML-SDK/issues/1093

在 OpenXML SDK 裡面提供了 AddCoreFilePropertiesPart 方法可以用來新增 CoreFilePropertiesPart 的內容。但是對其呼叫有要求,比如說在 PresentationDocument 的 PackageProperties 屬性賦值之前進行呼叫,如以下程式碼,則會出現 System.Xml.XmlException:“Root element is missing.” 異常

        public void CreatePackage(string filePath)
        {
            using PresentationDocument package = PresentationDocument.Create(filePath, PresentationDocumentType.Presentation);

            var document = package;

            if (document.CoreFilePropertiesPart is null)
            {
                document.AddCoreFilePropertiesPart();
            }

            SetPackageProperties(package);
        }

        private void SetPackageProperties(OpenXmlPackage document)
        {
            document.PackageProperties.Creator = "dexi lin";
            document.PackageProperties.Title = "PowerPoint 簡報";
            document.PackageProperties.Revision = "1";
            document.PackageProperties.Created = System.Xml.XmlConvert.ToDateTime("2024-01-24T09:19:23Z", System.Xml.XmlDateTimeSerializationMode.RoundtripKind);
            document.PackageProperties.Modified = System.Xml.XmlConvert.ToDateTime("2024-01-24T09:19:34Z", System.Xml.XmlDateTimeSerializationMode.RoundtripKind);
            document.PackageProperties.LastModifiedBy = "dexi lin";
        }

以上程式碼進入到設定 PackageProperties.Creator 屬性時,將會收到 System.Xml.XmlException:“Root element is missing.” 異常。這是因為預期的 CoreFilePropertiesPart 已經存在,但是裡面沒有任何內容

這時候網上的許多方法都是推薦採用如下或類似的程式碼寫入 CoreFilePropertiesPart 的內容

            if (document.CoreFilePropertiesPart is null)
            {
                var coreFilePropertiesPart = document.AddCoreFilePropertiesPart();

                using (XmlTextWriter writer = new XmlTextWriter(coreFilePropertiesPart.GetStream(FileMode.Create), System.Text.Encoding.UTF8))
                {
                    writer.WriteRaw("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<coreProperties xmlns:dc=\"http://purl.org/dc/elements/1.1/\" xmlns:dcterms=\"http://purl.org/dc/terms/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns=\"http://schemas.openxmlformats.org/package/2006/metadata/core-properties\"></coreProperties>");
                    writer.Flush();
                }
            }

            SetPackageProperties(package);

儘管以上程式碼能夠正常工作,但程式碼不好看

如果你不小心抄錯了 EXCEL 的程式碼,那你將會遇到 System.Xml.XmlException:“Unrecognized root element in Core Properties part. Line 2, position 2.” 錯誤哈

下面我推薦給大家一個簡單的程式碼方法,那就是在 SetPackageProperties 完成之後再呼叫 AddCoreFilePropertiesPart 方法,也就是將 SetPackageProperties 方法先呼叫,程式碼如下

        public void CreatePackage(string filePath)
        {
            using PresentationDocument package = PresentationDocument.Create(filePath, PresentationDocumentType.Presentation);

            var document = package;

            SetPackageProperties(package);

            if (document.CoreFilePropertiesPart is null)
            {
                document.AddCoreFilePropertiesPart();
            }
        }

        private void SetPackageProperties(OpenXmlPackage document)
        {
            document.PackageProperties.Creator = "dexi lin";
            document.PackageProperties.Title = "PowerPoint 簡報";
            document.PackageProperties.Revision = "1";
            document.PackageProperties.Created = System.Xml.XmlConvert.ToDateTime("2024-01-24T09:19:23Z", System.Xml.XmlDateTimeSerializationMode.RoundtripKind);
            document.PackageProperties.Modified = System.Xml.XmlConvert.ToDateTime("2024-01-24T09:19:34Z", System.Xml.XmlDateTimeSerializationMode.RoundtripKind);
            document.PackageProperties.LastModifiedBy = "dexi lin";
        }

看起來十分簡單,只是將 SetPackageProperties 和 AddCoreFilePropertiesPart 的呼叫順序調換即可

如果 SetPackageProperties 等是生成的程式碼,不想修改順序,可以在 AddCoreFilePropertiesPart 方法呼叫之前,隨意對 PackageProperties 的屬性進行賦值,如下面程式碼

        public void CreatePackage(string filePath)
        {
            using PresentationDocument package = PresentationDocument.Create(filePath, PresentationDocumentType.Presentation);

            var document = package;

            if (document.CoreFilePropertiesPart is null)
            {
                document.PackageProperties.Creator = "xxxxx"; // 隨意
                document.AddCoreFilePropertiesPart();
            }

            CreateParts(package);
        }

透過以上的方法即可成功建立 core.xml 檔案到 PPTX 檔案裡面。如果你使用本文的方法沒有建立成功,那我推薦你使用下面的方法拉取本文的程式碼,跑一下程式碼試試

本文以上程式碼放在githubgitee 歡迎訪問

可以透過如下方式獲取本文的原始碼,先建立一個空資料夾,接著使用命令列 cd 命令進入此空資料夾,在命令列裡面輸入以下程式碼,即可獲取到本文的程式碼

git init
git remote add origin https://gitee.com/lindexi/lindexi_gd.git
git pull origin f4a8f9c5265f3e52f3b9f93bb6570c9e73dc41c4

以上使用的是 gitee 的源,如果 gitee 不能訪問,請替換為 github 的源。請在命令列繼續輸入以下程式碼

git remote remove origin
git remote add origin https://github.com/lindexi/lindexi_gd.git
git pull origin f4a8f9c5265f3e52f3b9f93bb6570c9e73dc41c4

獲取程式碼之後,進入 WefejurkawFekejiyi 資料夾

更多關於 CoreFilePropertiesPart 請參閱 ECMA 376 文件的 15.2.12.1 章內容

更多關於 OpenXML 相關知識,請參閱 Office 使用 OpenXML SDK 解析文件部落格目錄

相關文章