[英]Modifying Word Document XML using Packages
我試圖修改一個簡單的MS字模板XML。 我意識到有SDK可用,這可以使這個過程更容易,但我負責維護使用包,我被告知做同樣的事情。
我有一個基本的測試文檔,其中兩個占位符映射到以下XML:
<root>
<element>
Fubar
</element>
<second>
This is the second placeholder
</second>
</root>
我正在做的是使用單詞doc創建流,刪除現有的XML,獲取一些硬編碼的測試XML並嘗試將其寫入流。
這是我正在使用的代碼:
string strRelRoot = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument";
byte[] buffer = File.ReadAllBytes("dev.docx");
//stream with the template
MemoryStream stream = new MemoryStream(buffer, true);
//create a package using the stream
Package package = Package.Open(stream, FileMode.Open, FileAccess.ReadWrite);
PackageRelationshipCollection pkgrcOfficeDocument = package.GetRelationshipsByType(strRelRoot);
foreach (PackageRelationship pkgr in pkgrcOfficeDocument)
{
if (pkgr.SourceUri.OriginalString == "/")
{
Uri uriData = new Uri("/customXML/item1.xml", UriKind.Relative);
//remove the existing part
if (package.PartExists(uriData))
{
// Delete template "/customXML/item1.xml" part
package.DeletePart(uriData);
}
//create a new part
PackagePart pkgprtData = package.CreatePart(uriData, "application/xml");
//test data
string xml = @"<root>
<element>
Changed
</element>
<second>
The second placeholder changed
</second>
</root>";
//stream created from the xml string
MemoryStream fromStream = new MemoryStream();
UnicodeEncoding uniEncoding = new UnicodeEncoding();
byte[] fromBuffer = uniEncoding.GetBytes(xml);
fromStream.Write(fromBuffer, 0, fromBuffer.Length);
fromStream.Seek(0L, SeekOrigin.Begin);
Stream toStream = pkgprtData.GetStream();
//copy the xml to the part stream
fromStream.CopyTo(toStream);
//copy part stream to the byte stream
toStream.CopyTo(stream);
}
}
這是目前沒有修改文檔,雖然我覺得我接近解決方案。 任何建議將非常感謝。 謝謝!
編輯:為了cla,我得到的結果是文件沒有變化。 我沒有例外或類似,但文檔XML沒有被修改。
好的,所以不是我承諾的及時回復,但是這里去了!
這個問題有幾個方面。 示例代碼來自內存和文檔,不一定要編譯和測試。
在刪除包含模板XML的包部件之前,需要打開其流並讀取XML。 如果部件不存在,那么如何獲取XML取決於您。
我的示例代碼使用LINQ to XML API中的類,盡管您可以使用您喜歡的任何一組XML API。
XElement templateXml = null;
using (Stream stream = package.GetPart(uriData))
templateXml = XElement.Load(stream);
// Now you can delete the part.
此時,您在templateXml
中具有模板XML的內存表示形式。
templateXml.SetElementValue("element", "Replacement value of first placeholder");
templateXml.SetElementValue("second", "Replacement value of second placeholder");
如果您需要執行比此更高級的任何操作,請查看XElement上的方法,例如,閱讀原始內容以確定替換值。
這是您的原始代碼,經過修改和注釋。
// The very first thing to do is create the Package in a using statement.
// This makes sure it's saved and closed when you're done.
using (Package package = Package.Open(...))
{
// XML reading, substituting etc. goes here.
// Eventually...
//create a new part
PackagePart pkgprtData = package.CreatePart(uriData, "application/xml");
// Don't need the test data anymore.
// Assuming you need UnicodeEncoding, set it up like this.
var writerSettings = new XmlWriterSettings
{
Encoding = Encoding.Unicode,
};
// Shouldn't need a MemoryStream at all; write straight to the part stream.
// Note using statements to ensure streams are flushed and closed.
using (Stream toStream = pkgprtData.GetStream())
using (XmlWriter writer = XmlWriter.Create(toStream, writerSettings))
templateXml.Save(writer);
// No other copying should be necessary.
// In particular, your toStream.CopyTo(stream) appeared
// to be appending the part's data to the package's stream
// (the physical file), which is a bug.
} // This closes the using statement for the package, which saves the file.
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.