2016-05-25 7 views
1

私はWPF C#プログラムを手に入れました。そして、ある時点でオブジェクトをXMLにシリアル化する必要があります。他の場所では、私はこれを使用してきた:オブジェクトを親要素内のXMLにシリアル化

TextWriter writer = new StreamWriter(xmlFilePath); 
XmlSerializer xmlSerializer = new XmlSerializer(typeof(MYOBJECT_TYPE)); 

try 
{ 
    xmlSerializer.Serialize(writer, MYOBJECT); 

} 
catch (Exception ex) 
{ 
    MessageBox.Show("Exception occured while writing to Xml" + ex.Message); 
} 
finally 
{ 
    writer.Close(); 
} 

これは素晴らしいですが、これは私が私がシリアライズしたいすべてのオブジェクトの異なるXMLファイルを持っている必要がありますを意味します。どのようにしてこのメ​​ソッドを最小限の変更量で使用して、オブジェクトをXML の親要素にシリアル化するのですか?そうすれば、オブジェクトを後で逆シリアル化したいときに、私が望む要素を見つけ、その要素内のすべてを逆シリアル化することができます。

要求されたとして、ここCreateDefaultXml();です:

static void CreateDefaultXml() 
{ 
    XmlDocument doc = new XmlDocument(); 
    doc.LoadXml("<StoredObjects></StoredObjects>"); 
    XmlNode root = doc.DocumentElement; 
    try 
    { 
     doc.Save(xmlFilePath); 
    } 
    catch (Exception ex) 
    { 
     Console.WriteLine("Exception occured while creating Xml" + ex.InnerException); 
    } 
} 

EDIT:

現在のところ、これは私が持っているものである(しかし、それは例外There was an error generating the XML document.をスロー)

if (!File.Exists(xmlFilePath)) 
    CreateDefaultXml(); 

XDocument doc = XDocument.Load(xmlFilePath); 
var element = doc.Descendants("Object").Where(x => x.Attribute("Name").Value.Equals("objectName")).SingleOrDefault(); 

if (element == null) 
{ 
    element = new XElement("Object", new XAttribute("Name", objectName)); 
    doc.Element("StoredObjects").Add(element); 
} 

XmlWriter writer = element.CreateWriter(); 
XmlSerializer xmlSerializer = new XmlSerializer(typeof(MYOBJECT_TYPE)); 

try 
{ 
    xmlSerializer.Serialize(writer, MYOBJECT); 

} 
catch (Exception ex) 
{ 
    MessageBox.Show("Exception occured while writing to Xml: " + ex.Message); 
} 
finally 
{ 
    writer.Close(); 
    doc.Save(xmlFilePath); 
} 
+0

1)「形状」とは何ですか? 'shape.CreateWriter();'行では未定義です。 2) 'CreateDefaultXml();'を共有できますか? – dbc

+0

@dbc申し訳ありません。私は質問を更新しました – derekantrican

+1

'MessageBox.Show'を変更して' ex.InnerException'を表示し、 'System.InvalidOperationException:ConformanceLevel.Fragmentで作成されたライターに対してWriteStartDocumentを呼び出せません.' – derekantrican

答えて

0

ネストしたに直接シリアル化しようとしていますXDocumentの中のをXmlSerializerとします。残念ながら、XContainer.CreateWriter()と一緒にXmlSerializerを使用してLINQ-to-XML XElementに直接シリアル化する場合、実際には空のXDocumentにシリアル化してルート要素を作成する必要があります。 (なぜこの制限が存在するのかわかりませんが)これはあなたのニーズを満たしていないので、XDocumentにシリアル化してルートノードを削除し、そのノードを全体の要素階層に追加するのは簡単です。

また、すでにXMLデータが格納されているobjectNameを使用してデータベースにオブジェクトを追加する場合は、古いデータを削除する必要があります。

私はこれを達成するために拡張メソッドにコードをリファクタリング:今、あなたは例fiddle

doc.AddItem(MYOBJECT, objectName); 

以降

var MYOBJECT2 = doc.GetItem<MYOBJECT_TYPE>(objectName); 

を行うことができます

public static class XmlExtensions 
{ 
    public static T Deserialize<T>(this XContainer element, XmlSerializer serializer = null) 
    { 
     using (var reader = element.CreateReader()) 
     { 
      object result = (serializer ?? new XmlSerializer(typeof(T))).Deserialize(reader); 
      if (result is T) 
       return (T)result; 
     } 
     return default(T); 
    } 

    public static XElement SerializeToXElement<T>(this T obj, XmlSerializer serializer = null) 
    { 
     var doc = new XDocument(); 
     using (var writer = doc.CreateWriter()) 
      (serializer ?? new XmlSerializer(obj.GetType())).Serialize(writer, obj); 
     var element = doc.Root; 
     if (element != null) 
      element.Remove(); 
     return element; 
    } 

    public static XName ContainerElementName { get { return (XName)"Object"; } } 

    public static XName ContainerAttributeName { get { return (XName)"Name"; } } 

    public static XElement SetItem<T>(this XDocument doc, string attributeValue, T obj) 
    { 
     return doc.SetItem(ContainerElementName, ContainerAttributeName, attributeValue, obj); 
    } 

    static XElement SetItem<T>(this XDocument doc, XName containerElementName, XName containerAttributeName, string attributeValue, T obj) 
    { 
     if (doc == null || containerElementName == null || containerAttributeName == null || attributeValue == null) 
      throw new ArgumentNullException(); 
     if (doc.Root == null) 
      throw new ArgumentException("doc.Root == null"); 
     var container = doc.Root.Elements(containerElementName).Where(e => (string)e.Attribute(containerAttributeName) == attributeValue).SingleOrDefault(); 
     if (container == null) 
     { 
      container = new XElement(containerElementName, new XAttribute(containerAttributeName, attributeValue)); 
      doc.Root.Add(container); 
     } 
     else 
     { 
      // Remove old content. 
      container.RemoveNodes(); 
     } 

     var element = obj.SerializeToXElement(); 
     container.Add(element); 
     return element; 
    } 

    public static T GetItem<T>(this XDocument doc, string attributeValue) 
    { 
     return doc.GetItem<T>(ContainerElementName, ContainerAttributeName, attributeValue); 
    } 

    static T GetItem<T>(this XDocument doc, XName containerElementName, XName containerAttributeName, string attributeValue) 
    { 
     if (doc == null || containerElementName == null || containerAttributeName == null || attributeValue == null) 
      throw new ArgumentNullException(); 
     if (doc.Root == null) 
      throw new ArgumentException("doc.Root == null"); 
     var container = doc.Root.Elements(containerElementName).Where(e => (string)e.Attribute(containerAttributeName) == attributeValue).SingleOrDefault(); 
     if (container == null) 
      return default(T); 
     var element = container.Elements().SingleOrDefault(); 
     if (element == null) 
      return default(T); 
     return element.Deserialize<T>(); 
    } 

    public static XDocument CreateDefaultXDocument() 
    { 
     var xml = @"<StoredObjects></StoredObjects>"; 
     return XDocument.Parse(xml); 
    } 
} 

を。

関連する問題