2017-11-16 4 views
0

Ich versuche, ein Word-Dokument mit einer Word-Vorlage in meiner C# -Anwendung mit openXML zu erstellen. Hier ist mein Code so weit:C# Word-Dokument mit openXML erstellen: XML Parsing Error (wenn Ersetzungszeichenfolge Leerzeichen enthält)

DirectoryInfo tempDir = new DirectoryInfo(Server.MapPath("~\\Files\\WordTemplates\\")); 

DirectoryInfo docsDir = new DirectoryInfo(Server.MapPath("~\\Files\\FinanceDocuments\\")); 

string ype = "test Merge"; //if ype string contains spaces then I get this error 
string sourceFile = tempDir + "\\PaymentOrderTemplate.dotx"; 
string destinationFile = docsDir + "\\" + "PaymentOrder.doc"; 

// Create a copy of the template file and open the copy 
File.Copy(sourceFile, destinationFile, true); 

// create key value pair, key represents words to be replace and 
//values represent values in document in place of keys. 
Dictionary<string, string> keyValues = new Dictionary<string, string>(); 
keyValues.Add("ype", ype);     
SearchAndReplace(destinationFile, keyValues); 
Process.Start(destinationFile); 

Und die SearchAndReplace funtion:

public static void SearchAndReplace(string document, Dictionary<string, string> dict) 
{ 
    using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(document, true)) 
    { 
     string docText = null; 

     using (StreamReader sr = new StreamReader(wordDoc.MainDocumentPart.GetStream())) 
     { 
      docText = sr.ReadToEnd(); 
     } 

     foreach (KeyValuePair<string, string> item in dict) 
     { 
      Regex regexText = new Regex(item.Key); 
      docText = regexText.Replace(docText, item.Value); 
     } 

     using (StreamWriter sw = new StreamWriter(
        wordDoc.MainDocumentPart.GetStream(FileMode.Create))) 
     { 
      sw.Write(docText); 
     } 
    } 
} 

Aber wenn ich versuche, die exportierte Datei ich diesen Fehler zu öffnen:

XML parsing error

Location: Part: /word/document.xml, line: 2, Column: 2142

Document.xml erste Zeilen:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 


<w:document xmlns:wpc="http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas" xmlns:cx="http://schemas.microsoft.com/office/drawing/2014/chartex" xmlns:cx1="http://schemas.microsoft.com/office/drawing/2015/9/8/chartex" xmlns:cx2="http://schemas.microsoft.com/office/drawing/2015/10/21/chartex" xmlns:cx3="http://schemas.microsoft.com/office/drawing/2016/5/9/chartex" xmlns:cx4="http://schemas.microsoft.com/office/drawing/2016/5/10/chartex" xmlns:cx5="http://schemas.microsoft.com/office/drawing/2016/5/11/chartex" xmlns:cx6="http://schemas.microsoft.com/office/drawing/2016/5/12/chartex" xmlns:cx7="http://schemas.microsoft.com/office/drawing/2016/5/13/chartex" xmlns:cx8="http://schemas.microsoft.com/office/drawing/2016/5/14/chartex" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:aink="http://schemas.microsoft.com/office/drawing/2016/ink" xmlns:am3d="http://schemas.microsoft.com/office/drawing/2017/model3d" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:wp14="http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing" xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:w14="http://schemas.microsoft.com/office/word/2010/wordml" xmlns:w15="http://schemas.microsoft.com/office/word/2012/wordml" xmlns:w16cid="http://schemas.microsoft.com/office/word/2016/wordml/cid" xmlns:w16se="http://schemas.microsoft.com/office/word/2015/wordml/symex" xmlns:wpg="http://schemas.microsoft.com/office/word/2010/wordprocessingGroup" xmlns:wpi="http://schemas.microsoft.com/office/word/2010/wordprocessingInk" xmlns:wne="http://schemas.microsoft.com/office/word/2006/wordml" xmlns:wps="http://schemas.microsoft.com/office/word/2010/wordprocessingShape" mc:Ignorable="w14 w15 w16se w16cid wp14"> 

<w:body> 

<w:tbl> 

<w:tblPr> 

<w:tblW w:w="10348" w:ttest Merge="dxa"/> 

<w:tblInd w:w="108" w:ttest Merge="dxa"/> 

<w:tblBorders> 

Bearbeiten Ich habe herausgefunden, dass das Problem aufgetreten ist, weil ich Mergelfelder in der Word-Vorlage verwendet habe. Wenn ich einfachen Text verwende, funktioniert es. Aber in diesem Fall wird es langsam sein, weil es jedes einzelne Wort in der Vorlage überprüfen muss und wenn Übereinstimmungen es ersetzen. Ist es möglich, es anders zu machen?

+0

Auch wenn Sie Art sind * neu * zu SO, bitte ich flehe dich an, deinen Code richtig zu bearbeiten. –

+0

Was ist in Zeile 2 des XML-Dokuments? – GrandMasterFlush

+0

@GrandMasterFlush Ich fand, dass, wenn die Ersetzung Zeichenfolge Leerzeichen enthält, bekomme ich diesen Fehler, sonst funktioniert es gut – aggicd

Antwort

1

Haftungsausschluss: Sie scheinen das OpenXML-SDK zu verwenden, da Ihr Code praktisch identisch mit dem hier gefundenen aussieht: https://msdn.microsoft.com/en-us/library/bb508261(v=office.12).aspx - Ich habe noch nie in meinem Leben dieses SDK verwendet und ich basiere diese Antwort auf einer begründeten Vermutung Was passiert

Es scheint, dass die Operation, die Sie an diesem Word-Dokument ausführen, Teile des Dokuments betrifft, die Sie nicht beabsichtigt haben.

Ich glaube, dass das Aufrufen von document.MainDocumentPart.GetStream() nur Ihnen mehr oder weniger direkten Roh-Zugriff auf das XML des Dokuments gibt, und Sie behandeln es dann als eine einfache XML-Datei, manipulieren es als Text und eine Liste von geraden Textersetzungen ausführen? Ich denke, es ist also wahrscheinlich die Ursache des Problems, weil Sie beabsichtigen Dokument Text zu bearbeiten, aber versehentlich xml Knotenstruktur im Prozess

Als ein Beispiel zu beschädigen, ist hier ein einfaches HTML-Dokument:

<html> 
<head><title>Damage report</title></head> 
<body> 
    <p>The soldier was shot once in the body and twice in the head</p> 
</body> 
</html> 

Sie entscheiden, eine Suche ausführen/ersetzen die Orte der Soldat wurde erschossen zu machen, ein bisschen mehr spezifisch:

var html = File.ReadAllText(@"c:\my.html"); 
html = html.Replace("body", "chest"); 
html = html.Replace("head", "forehead"); 
File.WriteAllText(@"c:\my.html"); 

Nur, was ist Ihr Dokument jetzt ruiniert:

<html> 
<forehead><title>Damage report</title></forehead> 
<chest> 
    <p>The soldier was shot once in the chest and twice in the forehead</p> 
</chest> 
</html> 

Ein Browser kann es nicht analysieren (na ja, es ist immer noch gültig, ich nehme an, aber es ist bedeutungslos), weil der Austausch einige Dinge kaputt gemacht hat.

Sie ersetzen "ype" mit "test Merge" aber dies scheint ein Vorkommen des Wortes zu clobbering "type" - etwas, das es ziemlich wahrscheinlich, scheint in den XML-Attribute oder Elementnamen erscheinen würde - und in "ttest Merge" drehen.

Um den Inhalt der Knotentexte eines XML-Dokuments korrekt zu ändern, sollte er aus Text in eine XML-Dokumentobjektmodelldarstellung geparst werden, die Knoten werden iteriert, die Texte geändert und das Ganze erneut in XML-Text serialisiert.Office-SDK scheint Möglichkeiten zu bieten, dies zu tun, weil Sie ein Dokument wie eine Sammlung von Klassenobjektinstanzen behandeln können, und sagen Dinge wie dieser Code-Schnipsel (auch von MSDN):

// Create a Wordprocessing document. 
using (WordprocessingDocument myDoc = WordprocessingDocument.Create(docName, WordprocessingDocumentType.Document)) 
{ 
    // Add a new main document part. 
    MainDocumentPart mainPart = myDoc.AddMainDocumentPart(); 
    //Create DOM tree for simple document. 
    mainPart.Document = new Document(); 
    Body body = new Body(); 
    Paragraph p = new Paragraph(); 
    Run r = new Run(); 
    Text t = new Text("Hello World!"); 
    //Append elements appropriately. 
    r.Append(t); 
    p.Append(r); 
    body.Append(p); 
    mainPart.Document.Append(body); 
    // Save changes to the main document part. 
    mainPart.Document.Save(); 
} 

Sie sollten suchen für Eine andere Möglichkeit, keinen Stream/direkten Low-Level-XML-Zugriff zu verwenden, um auf die Dokumentelemente zuzugreifen. So etwas wie diese:

https://blogs.msdn.microsoft.com/brian_jones/2009/01/28/traversing-in-the-open-xml-dom/ 
https://www.gemboxsoftware.com/document/articles/find-replace-word-csharp 

Oder vielleicht mit einer SO Frage wie diese im Zusammenhang Start: Search And Replace Text in OPENXML (Added file) (obwohl die Antwort, die Sie müssen im Inneren dieser Frage verknüpft etwas sein kann)