2011-01-25 4 views
4

J'essaie de manipuler le XML d'un document Word 2007 en C#. J'ai réussi à trouver et à manipuler le nœud que je veux mais maintenant je n'arrive pas à comprendre comment le sauvegarder. Voici ce que j'essaie:Manipulation de Word 2007 Document XML en C#

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

Je reçois l'erreur 'Le flux de mémoire n'est pas extensible'. Des idées?

+0

Vous vous demandez s'il y a une meilleure méthode de le faire ... – stephen776

Répondre

8

Je vous recommande d'utiliser Open XML SDK au lieu de pirater le format par vous-même.

1

Le problème semble être doc.Save (partWrtr), qui est construit en utilisant newPkgprtData, qui est construit en utilisant pkgFile, qui charge à partir d'un flux mémoire ... Parce que vous avez chargé depuis un flux mémoire, il essaie d'enregistrer le document retour à ce même flux de mémoire. Cela conduit à l'erreur que vous voyez.

Au lieu de l'enregistrer dans le flux de mémoire, essayez de l'enregistrer dans un nouveau fichier ou dans un nouveau flux de mémoire.

+0

ce sont mes pensées ...une idée de comment je devrais aller à ce sujet? – stephen776

+0

MemoryStream msSave = new MemoryStream(); doc.Save (msSave); – Peter

+0

Peut-être même mieux, puisque votre dans asp.net: doc.Save (Response.OutputStream) qui va l'écrire directement dans le flux de réponse HTTP. – Peter

2

utilisant SDK OpenXML 2.0, je fais ceci:

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

De cela, vous pouvez écrire un GetPartAsXmlDocument, faites ce que vous voulez avec elle, et puis diffuser en arrière avec savepart (partie xmlString).

Espérons que cela aide!

0

La réponse courte et simple à la question à l'obtention 'flux de mémoire non extensible' est: Ne pas ouvrir le document de memoryStream. Donc, à cet égard, la réponse précédente est correcte, ouvrez simplement un fichier à la place.

L'ouverture à partir de MemoryStream en éditant le document (dans mon expérience) conduit facilement à 'le flux de mémoire n'est pas extensible'. Je suppose que le message apparaît quand on édite ce qui nécessite le flux de mémoire pour se développer. J'ai trouvé que je peux faire quelques modifications mais pas n'importe quoi qui s'ajoute à la taille. Ainsi, si vous supprimez une partie xml personnalisée, cela ne pose aucun problème, mais ajoutez une et certaines données. Par conséquent, si vous avez réellement besoin d'ouvrir un flux mémoire, vous devez comprendre comment ouvrir un MemoryStream extensible si vous voulez ajouter un flux mémoire. J'en ai besoin et j'espère trouver une solution.

Stein-Tore Erdal

PS: juste remarqué la réponse de "26 '11 Jan à 15h18". Ne pense pas que c'est la réponse dans toutes les situations. Je reçois l'erreur lorsque vous essayez ceci:

 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. 
Questions connexes