【问题标题】:Manipulating Word 2007 Document XML in C#在 C# 中操作 Word 2007 文档 XML
【发布时间】:2011-06-15 04:30:52
【问题描述】:

我正在尝试在 C# 中操作 Word 2007 文档的 XML。我已经设法找到并操作了我想要的节点,但现在我似乎无法弄清楚如何将它保存回来。这是我正在尝试的:

// Open the document  from memoryStream
Package pkgFile = Package.Open(memoryStream, FileMode.Open, FileAccess.ReadWrite);
PackageRelationshipCollection pkgrcOfficeDocument = pkgFile.GetRelationshipsByType(strRelRoot);

foreach (PackageRelationship pkgr in pkgrcOfficeDocument)
{
    if (pkgr.SourceUri.OriginalString == "/")
    {
        Uri uriData = new Uri("/word/document.xml", UriKind.Relative);

        PackagePart pkgprtData = pkgFile.GetPart(uriData);

        XmlDocument doc = new XmlDocument();
        doc.Load(pkgprtData.GetStream());

        NameTable nt = new NameTable();
        XmlNamespaceManager nsManager = new XmlNamespaceManager(nt);
        nsManager.AddNamespace("w", nsUri);

        XmlNodeList nodes = doc.SelectNodes("//w:body/w:p/w:r/w:t", nsManager);

        foreach (XmlNode node in nodes)
        {
            if (node.InnerText == "{{TextToChange}}")
            {
                node.InnerText = "success";
            }
        }


        if (pkgFile.PartExists(uriData))
        {
            // Delete template "/customXML/item1.xml" part
            pkgFile.DeletePart(uriData);
        }
        PackagePart newPkgprtData = pkgFile.CreatePart(uriData, "application/xml");
        StreamWriter partWrtr = new StreamWriter(newPkgprtData.GetStream(FileMode.Create, FileAccess.Write));

        doc.Save(partWrtr);
        partWrtr.Close();
    }
}   

pkgFile.Close();

我收到错误消息“内存流不可扩展”。有什么想法吗?

【问题讨论】:

  • 想知道是否有更好的方法来做到这一点......

标签: c# asp.net .net xml ms-word


【解决方案1】:

我建议您使用Open XML SDK 而不是自己破解格式。

【讨论】:

    【解决方案2】:

    使用 OpenXML SDK 2.0,我这样做:

    public void SearchAndReplace(Dictionary<string, string> tokens)
    {
        using (WordprocessingDocument doc = WordprocessingDocument.Open(_filename, true))
            ProcessDocument(doc, tokens);
    }
    
    private string GetPartAsString(OpenXmlPart part)
    {
        string text = String.Empty;
        using (StreamReader sr = new StreamReader(part.GetStream()))
        {
            text = sr.ReadToEnd();
        }
        return text;
    }
    
    private void SavePart(OpenXmlPart part, string text)
    {
        using (StreamWriter sw = new StreamWriter(part.GetStream(FileMode.Create)))
        {
            sw.Write(text);
        }
    }
    
    private void ProcessDocument(WordprocessingDocument doc, Dictionary<string, string> tokenDict)
    {
        ProcessPart(doc.MainDocumentPart, tokenDict);
        foreach (var part in doc.MainDocumentPart.HeaderParts)
        {
            ProcessPart(part, tokenDict);
        }
        foreach (var part in doc.MainDocumentPart.FooterParts)
        {
            ProcessPart(part, tokenDict);
        }
    }
    
    private void ProcessPart(OpenXmlPart part, Dictionary<string, string> tokenDict)
    {
        string docText = GetPartAsString(part);
    
        foreach (var keyval in tokenDict)
        {
            Regex expr = new Regex(_starttag + keyval.Key + _endtag);
            docText = expr.Replace(docText, keyval.Value);
        }
    
        SavePart(part, docText);
    }
    

    从此您可以编写一个 GetPartAsXmlDocument,用它做您想做的事,然后使用 SavePart(part, xmlString) 将其流回。

    希望这会有所帮助!

    【讨论】:

      【解决方案3】:
      【解决方案4】:

      问题似乎是 doc.Save(partWrtr),它是使用 newPkgprtData 构建的,它是使用 pkgFile 构建的,它从内存流中加载...因为您是从内存流中加载的,所以它试图将文档保存回来到同一个内存流。这会导致您看到的错误。

      不要将其保存到内存流中,而是尝试将其保存到新文件或新的内存流中。

      【讨论】:

      • 这些是我的想法...知道我应该怎么做吗?
      • MemoryStream msSave = new MemoryStream(); doc.Save(msSave);
      • 也许更好,因为您在 asp.net 中: doc.Save(Response.OutputStream) 会将其直接写入 HTTP 响应流。
      【解决方案5】:

      获得“内存流不可扩展”问题的简短答案是: 不要从 memoryStream 打开文档。 所以在这方面,前面的答案是正确的,只需打开一个文件。

      从 MemoryStream 打开编辑文档(根据我的经验)很容易导致“内存流不可扩展”。 我想当进行需要扩展内存流的编辑时会出现该消息。 我发现我可以做一些编辑,但不能做任何增加尺寸的事情。 因此,f.ex 删除自定义 xml 部分是可以的,但添加一个和一些数据则不行。

      所以如果你真的需要打开一个内存流,你必须弄清楚如何打开一个可扩展的 MemoryStream,如果你想添加它。 我有这个需求,希望能找到解决办法。

      斯坦-托尔·埃达尔

      PS:刚刚注意到“2011 年 1 月 26 日 15:18”的答案。 不要认为这是所有情况下的答案。 尝试此操作时出现错误:

           var ms = new MemoryStream(bytes);
           using (WordprocessingDocument wd = WordprocessingDocument.Open(ms, true))
           {
              ...
              using (MemoryStream msData = new MemoryStream())
              {
                 xdoc.Save(msData);
                 msData.Position = 0;
                 ourCxp.FeedData(msData); // Memory stream is not expandable.
      

      【讨论】:

        猜你喜欢
        • 2011-03-19
        • 1970-01-01
        • 1970-01-01
        • 2017-04-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多