1

単純な MS Word テンプレート XML を変更しようとしています。このプロセスを簡単にする SDK が利用可能であることは認識していますが、私が担当しているのはパッケージを使用するタスクであり、同じことをするように言われました。

次の XML にマップされた 2 つのプレースホルダーを含む基本的なテスト ドキュメントがあります。

<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);

    }
}

解決策に近づいているように感じますが、これは現在ドキュメントを変更していません。アドバイスをいただければ幸いです。ありがとう!

編集:明確にするために、私が得ている結果は、ドキュメントが変更されていないことです。例外などは発生しませんが、ドキュメントの XML は変更されません。

4

1 に答える 1

3

OK、私が約束したタイムリーな応答ではありませんが、ここに行きます!

問題にはいくつかの側面があります。サンプル コードはメモリとドキュメントからのものであり、必ずしもコンパイルおよびテストされているわけではありません。


テンプレート 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.

この時点で、テンプレート XML のメモリ内表現が にありますtemplateXml


プレースホルダーに値を代入します

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.
于 2012-07-12T11:29:26.570 に答える