How to serialize multiple objects into an existing XmlDocument, without having the namespaces on each component?

后端 未结 2 1487
耶瑟儿~
耶瑟儿~ 2020-12-22 01:16

How to serialize multiple objects into a existing XmlDocument in .Net/C#?

I have a XmlDocument, which already contains data. I have multiple objects. Now I want to s

相关标签:
2条回答
  • 2020-12-22 01:33

    This will serialize objects and append them to a XmlDocument. While de-/serializing the code will resolve the namespaces. @Alex: Thanks for the example with XPathNavigator.

    void test2()
    {
        XmlDocument doc = new XmlDocument();
        XmlNode root = doc.AppendChild(doc.CreateElement("root"));
    
        doc.DocumentElement.SetAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
        doc.DocumentElement.SetAttribute("xmlns:xsd", "http://www.w3.org/2001/XMLSchema");
    
        serializeAppend(root, new object[] { 1, "two", 3.0 });  // serialize object and append it to XmlNode
        var obj = deserialize<object[]>(root.ChildNodes[0]);    // deserialize XmlNode to object
    }
    T deserialize<T>(XmlNode node)
    {
        XPathNavigator nav = node.CreateNavigator();
        using (var reader = nav.ReadSubtree())
        {
            var serializer = new XmlSerializer(typeof(T));
            return (T)serializer.Deserialize(reader);
        }
    }
    void serializeAppend(XmlNode parentNode, object obj)
    {
        XPathNavigator nav = parentNode.CreateNavigator();
        using (var writer = nav.AppendChild())
        {
            var serializer = new XmlSerializer(obj.GetType());
            writer.WriteWhitespace("");
            serializer.Serialize(writer, obj);
            writer.Close();
        }
    }
    
    0 讨论(0)
  • 2020-12-22 01:45

    The code below will fulfill the requirement in the OP, to have a clean XML. It will remove all tributes from all elements, but it will add a type attribute to the anyType elements, so the original type could still be distinguish for each element.

    static void Main(string[] args)
    {
        object[] components = new object[] { new Component_1(), new Component_1() };
    
        var doc = new XmlDocument();
        doc.Load("source.xml");
        var project = doc.GetElementsByTagName("project")[0];
    
        var nav = project.CreateNavigator();
    
        var emptyNamepsaces = new XmlSerializerNamespaces(new[] { 
            XmlQualifiedName.Empty
        });
    
        foreach (var component in components)
        {
            using (var writer = nav.AppendChild())
            {
                var serializer = new XmlSerializer(component.GetType());
                writer.WriteWhitespace("");
                serializer.Serialize(writer, component
                    , emptyNamepsaces
                    );
                writer.Close();
            }
        }
    
        foreach (XmlNode node in doc.GetElementsByTagName("anyType"))
        {
            string attributeType = "";
            foreach (XmlAttribute xmlAttribute in node.Attributes)
            {
                if (xmlAttribute.LocalName == "type")
                { 
                attributeType=xmlAttribute.Value.Split(':')[1];
                }
            }
            node.Attributes.RemoveAll();
            node.CreateNavigator().CreateAttribute("","type","",attributeType);
        }
        doc.Save("output.xml");
    
    }
    

    If you want to deserialize the XML, you'll have to create a dictionary:

    static Dictionary<string, Type> _typeCache;
    

    add the expected XML types mapped to corresponding Type values to it:

    _typeCache = new Dictionary<string, Type>();
    _typeCache.Add("string", typeof(System.String));
    _typeCache.Add("int", typeof(System.Int32));
    _typeCache.Add("dateTime", typeof(System.DateTime));
    

    and replace each XmlNode in the array by converting it to it's expected type accordingly:

    Component_1 c = Deserialize<Component_1>(project.ChildNodes[0].OuterXml);
    
    for (int i = 0; i < c.objectArray.Length; i++)
    {
        var type = _typeCache[(((System.Xml.XmlNode[])(c.objectArray[i]))[0]).Value];
        var item = Convert.ChangeType((((System.Xml.XmlNode[])(c.objectArray[i]))[1]).Value, type);
        c.objectArray[i] = item;
    }
    
    Console.WriteLine(c.objectArray[0].GetType()); // -> System.String
    
    0 讨论(0)
提交回复
热议问题