2017-07-05 16 views
1

我想一個序列化對象追加到根元素,我本以爲這很簡單,但被證明是一個具有挑戰性的一點下方的現有XML文件追加對象到XML文件。C#使用序列

的問題是在AddShortcut方法,但我添加了一些更多的代碼的完整性。

我相信什麼,我需要做的是:

  1. 將文件加載到一個XmlDocument。
  2. 導航到我要下追加節點(這裏的節點名稱是快捷方式)。
  3. 創建一些類型的作家,然後序列化對象。
  4. 保存XmlDocument。

問題出在步驟2和3.我嘗試過不同的變化,但我認爲使用XPathNavigator以某種方式找到要追加的「根」節點是朝正確方向邁出的一步。

我也看着關於這個問題的堆棧溢出幾乎每一個問題。

歡迎任何建議。這裏是我的代碼

class XmlEngine 
{ 
    public string FullPath { get; set; } // the full path to the xmlDocument 
    private readonly XmlDocument xDoc; 

    public XmlEngine(string fullPath, string startElement, string[] rElements) 
    { 
     FullPath = fullPath; 
     xDoc = new XmlDocument(); 
     CreateXmlFile(FullPath, startElement, rElements);    
    } 

    public void CreateXmlFile(string path, string startElement, string[] rElements) 
    { 
    try 
    { 
     if (!File.Exists(path)) 
     { 
     // create a txt writer 
     XmlTextWriter wtr = new XmlTextWriter(path, System.Text.Encoding.UTF8); 

     // make sure the file is well formatted 
     wtr.Formatting = Formatting.Indented; 

     wtr.WriteProcessingInstruction("xml", "version='1.0' encoding='UTF-8'"); 
     wtr.WriteStartElement(startElement); 
     wtr.Close(); 

     // write the top level root elements 
     writeRootElements(path, rElements); 
     } 
    } 
    catch (Exception ex) 
    { 
     Console.WriteLine("Error: " + ex.Message); 
     Console.WriteLine("Could not create file: " + path); 
    } 
    } 

    public void AddShortcut(Shortcut s) 
    { 
    xDoc.Load(FullPath); 
    rootNode = xDoc.AppendChild(xDoc.CreateElement("Shortcuts")); 

    var serializer = new XmlSerializer(s.GetType()); 

    using (var writer = new StreamWriter(FullPath, true)) 
    { 
     XmlWriterSettings ws = new XmlWriterSettings(); 
     ws.OmitXmlDeclaration = true; 

     serializer.Serialize(writer, s); 
    } 

    xDoc.Save(FullPath); 

    } 

} 
+0

您是否在尋找像'XmlNodeExtensions.SerializeToXmlElement()'從[如何創建套序列化對象的C#(https://stackoverflow.com/a/29307126/3744182)? – dbc

+1

您可以考慮從'XmlDocument'切換到[LINQ到XML(https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/linq/linq-to-xml)和' XDocument'。這是一個更新的API,更容易使用,並可能在.Net核心等地方得到更好的支持。 – dbc

+0

感謝dbc。我看到了一些使用LINK到XML的解決方案,並想知道這是否會更好。我可能會嘗試,如果我可以很快序列化工作 – cbutler

回答

0
  1. 將文件加載到一個XmlDocument。
  2. 導航到我要下追加節點(這裏的節點名稱是快捷方式)。
  3. 創建一些類型的作家,然後序列化對象。
  4. 保存的XmlDocument

所以:

public void AddShortcut(Shortcut s) 
{ 
    // 1. load existing xml 
    xDoc.Load(FullPath); 
    // 2. create an XML node from object 
    XmlElement node = SerializeToXmlElement(s); 
    // 3. append that node to Shortcuts node under XML root 
    var shortcutsNode = xDoc.CreateElement("Shortcuts") 
    shortcutsNode.AppendChild(node); 
    xDoc.DocumentElement.AppendChild(shortcutsNode); 
    // 4. save changes 
    xDoc.Save(FullPath); 
} 

public static XmlElement SerializeToXmlElement(object o) 
{ 
    XmlDocument doc = new XmlDocument(); 
    using(XmlWriter writer = doc.CreateNavigator().AppendChild()) 
    { 
     new XmlSerializer(o.GetType()).Serialize(writer, o); 
    } 
    return doc.DocumentElement; 
} 

This post

+0

我認爲這很接近,但現在我在運行代碼時遇到異常。我的XML看起來像這樣:<?XML版本= 「1.0」 編碼= 「UTF-8」?> 。新節點應該快捷方式 – cbutler

+0

@cbutler - 更新了答案 – user270576

1

此示例代碼爲我工作:

XML:

<?xml version="1.0" encoding="UTF-8"?> 
<Launchpad> 
    <Shortcuts> 
    <Shortcut Id="1"> 
     <Type>Folder</Type> 
     <FullPath>C:\SomePath</FullPath> 
     <Name>SomeFolderName</Name> 
    </Shortcut> 
    </Shortcuts> 
</Launchpad> 

方法:

public void AddShortcut(Shortcut s) 
{ 
    xDoc.Load(FullPath); 
    var rootNode = xDoc.GetElementsByTagName("Shortcuts")[0]; 
    var nav = rootNode.CreateNavigator(); 
    var emptyNamepsaces = new XmlSerializerNamespaces(new[] { 
     XmlQualifiedName.Empty 
    }); 

    using (var writer = nav.AppendChild()) 
    { 
     var serializer = new XmlSerializer(s.GetType()); 
     writer.WriteWhitespace(""); 
     serializer.Serialize(writer, s, emptyNamepsaces); 
     writer.Close(); 
    }    
    xDoc.Save(FullPath); 
}