2014-01-25 44 views
1

我正在寫一些代碼,將創建一個Excel .xml文件。該文件是高度結構化的,並以一種不變的方式進行格式化,所以有大約3000行文件不會改變。在看到this question的回答後,我採用了這個解決方案來創建文件。XmlWriter與命名空間和.WriteNode()

的代碼如下

XmlWriterSettings writerSettings = new XmlWriterSettings(); 
writerSettings.Indent = true; 
XmlWriter writer = XmlWriter.Create("results.xml", writerSettings); 

writer.WriteStartDocument(); 
writer.WriteProcessingInstruction("mso-application", "progid=\"Excel.Sheet\""); 
writer.WriteStartElement("Workbook", "urn:schemas-microsoft-com:office:spreadsheet"); 
writer.WriteAttributeString("xmlns", "o", null, "urn:schemas-microsoft-com:office:office"); 
writer.WriteAttributeString("xmlns", "x", null, "urn:schemas-microsoft-com:office:excel"); 
writer.WriteAttributeString("xmlns", "ss", null, "urn:schemas-microsoft-com:office:spreadsheet"); 
writer.WriteAttributeString("xmlns", "html", null, "http://www.w3.org/TR/REC-html40"); 
string str = "<DocumentProperties xmlns=\"urn:schemas-microsoft-com:office:office\">\n <Author>Bananal</Author>\n <LastAuthor>PedroK</LastAuthor>\n <LastPrinted>2013-08-01T22:10:44Z</LastPrinted>\n <Created>2013-07-17T21:18:47Z</Created>\n <LastSaved>2013-12-16T17:44:10Z</LastSaved>\n <Version>14.00</Version>\n </DocumentProperties>"; 
XmlReaderSettings readerSettings = new XmlReaderSettings(); 
readerSettings.IgnoreWhitespace = true; 
XmlReader reader = XmlReader.Create(new StringReader(str), readerSettings); 
writer.WriteNode(reader, true); 
str = "<OfficeDocumentSettings xmlns=\"urn:schemas-microsoft-com:office:office\">\n <AllowPNG/>\n </OfficeDocumentSettings>"; 
reader = XmlReader.Create(new StringReader(str), readerSettings); 
writer.WriteNode(reader, true); 
str = "<ExcelWorkbook xmlns=\"urn:schemas-microsoft-com:office:excel\">\n <WindowHeight>12432</WindowHeight>\n <WindowWidth>23256</WindowWidth>\n <WindowTopX>0</WindowTopX>\n <WindowTopY>0</WindowTopY>\n <TabRatio>755</TabRatio>\n <ActiveSheet>9</ActiveSheet>\n <ProtectStructure>False</ProtectStructure>\n <ProtectWindows>False</ProtectWindows>\n </ExcelWorkbook>"; 
reader = XmlReader.Create(new StringReader(str), readerSettings); 
writer.WriteNode(reader, true); 
str = "<Styles>\n <Style ss:ID=\"Default\" ss:Name=\"Normal\">\n <Alignment ss:Vertical=\"Bottom\"/>\n <Borders/>\n <Font ss:FontName=\"Calibri\" x:Family=\"Swiss\" ss:Size=\"11\" ss:Color=\"#000000\"/>\n <Interior/>\n <NumberFormat/>\n <Protection/>\n </Style></Styles>" 
reader = XmlReader.Create(new StringReader(str), readerSettings); 
writer.WriteNode(reader, true); 

這樣,我已經儘可能有效地我能想到的一切批處理。這個效果很好,直到最後一段(關於<Styles>),其中writer.WriteNode()引發異常說'ss' is an undeclared namespace.我對命名空間的定義做了一些錯誤,還是有其他的東西我必須處理原始字符串以使其與.WriteNode()

+0

你*有*使用'XmlWriter'嗎?這看起來非常複雜,使用LINQ to XML很簡單。它也無助於你將XML直接嵌入到你的C#('Styles'元素)中,這意味着它根本就不是有效的C#... –

+0

哦,我的,是的,我糾正了錯字。複製和粘貼時這是錯誤的。原始版本不止有一個Style,但我刪除了其餘部分,因爲它與手頭上的問題無關,並且明顯忘記了放置引號。這種風格的數量實際上是問題的一部分。有數百個,我不知道Linq如何幫助我。這就是爲什麼我使用鏈接中提供的方法,因爲它允許我簡單地將它們全部扔進去,讓作者自己處理它們。 – Wasabi

+0

一般情況下不是LINQ,但是LINQ to XML - 在我看來,它只是一種更簡潔的創建XML的方式。特別是,如果您已經有一些您想要包含的XML,那麼解析它並添加適當的節點非常簡單。我不會建議在代碼中保留它*雖然 - 我可能有一個單獨加載的單獨的XML文件。 –

回答

1

如果您使用XML閱讀器,則提供的xml必須有效。如果在屬性或元素上使用名稱空間別名,則還需要限定名稱空間。

快速修復方案
你要添加的命名空間ssx你的風格標籤,像這樣:

str = "<Styles xmlns:ss=\"urn:schemas-microsoft-com:office:spreadsheet\" xmlns:x=\"urn:schemas-microsoft-com:office:excel\">\n <Style ss:ID=\"Default\" ss:Name=\"Normal\">\n <Alignment ss:Vertical=\"Bottom\"/>\n <Borders/>\n <Font ss:FontName=\"Calibri\" x:Family=\"Swiss\" ss:Size=\"11\" ss:Color=\"#000000\"/>\n <Interior/>\n <NumberFormat/>\n <Protection/>\n </Style></Styles>"; 
reader = XmlReader.Create(new StringReader(str), readerSettings); 
writer.WriteNode(reader, true); 

替代解決方案
提供必要給讀者的命名空間一個parserContext 。優點是你不必改變你現在擁有的xmlmarkup。

NameTable nt = new NameTable(); 
XmlNamespaceManager nsmgr = new XmlNamespaceManager(nt); 
nsmgr.AddNamespace("ss", "urn:schemas-microsoft-com:office:spreadsheet"); 
nsmgr.AddNamespace("x", "urn:schemas-microsoft-com:office:excel"); 

//Create the XmlParserContext (this can be reused in every reader!) 
XmlParserContext ctx = new XmlParserContext(null, nsmgr, null, XmlSpace.None); 

/* other code here */ 

str = "<Styles >\n <Style ss:ID=\"Default\" ss:Name=\"Normal\">\n <Alignment ss:Vertical=\"Bottom\"/>\n <Borders/>\n <Font ss:FontName=\"Calibri\" x:Family=\"Swiss\" ss:Size=\"11\" ss:Color=\"#000000\"/>\n <Interior/>\n <NumberFormat/>\n <Protection/>\n </Style></Styles>"; 
reader = XmlReader.Create(new StringReader(str), readerSettings, ctx); // NOTICE ctx here 
writer.WriteNode(reader, true); 

旁註
看起來你是生產用於通過Excel中使用的文件。你認爲The Open XML SDK

+0

我實際上並沒有意識到Open XML SDK(我對事物非常無知,我非常喜歡程序員)。我現在看看它,看起來很有趣。 – Wasabi

+0

它基本上是一個圍繞xmlstore的託管包裝,如果你有節點之間的關係有一些好處。我不認爲你的代碼最終會小得多...... – rene