Jak serializować wiele obiektów do istniejącego XmlDocument bez posiadania przestrzeni nazw w każdym komponencie?

Jak serializować wiele obiektów do istniejącego XmlDocument w .Net / C #?

Mam XmlDocument, który już zawiera dane. Mam wiele obiektów. Teraz chcę je serializować pojedynczo i dodawać do XmlDocument (AppendChild).

To jest takie, jakie powinno być:

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<project>
    <mySettings>...</mySettings>
    <component_1> anydata </component_1>
    ...
    <component_x> anydata </component_x>
</project>

Kiedy używam XmlSerializer, otrzymuję tę definicję dla każdego komponentu:

<component_1 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    anydata
</component_1>

Oto co otrzymuję, kiedy serializuję w łańcuch, a następnie tworzę XmlNode z łańcucha, który dołączam do mojego dokumentu:

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<project>
    <mySettings>...</mySettings>
    <component_1 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> anydata </component_1>
    ...
    <component_x xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> anydata </component_x>
</project>

Mogę usunąć przestrzeń nazw, wykonując następujące czynności:

XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("", "");
StringWriter xout = new StringWriter();
x.Serialize(xout, data, ns);

Ale wtedy otrzymuję przestrzenie nazw na dowolnym obiekcie wewnątrz tablicy obiektów. Ten obiekt:

public class component_1
{
    object[] arr;
}

zostanie serializowany do:

<component_1>
  <objectArray>
    <anyType xmlns:q1="http://www.w3.org/2001/XMLSchema" d3p1:type="q1:string" xmlns:d3p1="http://www.w3.org/2001/XMLSchema-instance">one</anyType>
    <anyType xmlns:q2="http://www.w3.org/2001/XMLSchema" d3p1:type="q2:string" xmlns:d3p1="http://www.w3.org/2001/XMLSchema-instance">two</anyType>
  </objectArray>
</component_1>

Czy można dodać wszystkie potrzebne przestrzenie nazw itp. Do mojego dokumentu, a następnie serializować obiekty do XmlNodes i dodawać je do mojego dokumentu, bez konieczności posiadania przestrzeni nazw w każdym komponencie?

UPDATE: Test funkcji () spowoduje serializację dwóch obiektów i dołączenie ich do dokumentu. Ostatnia linia spowoduje deserializację pierwszego obiektu.

using System;
using System.IO;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
...

public class Component_1
{
    public string Value = "Component_1.Value";
    public object[] objectArray = new object[] { "one", "two" };
}
void test()
{
    object[] components = new object[] { new Component_1(), new Component_1() };

    XmlDocument doc = new XmlDocument();
    XmlNode rootNode = doc.AppendChild(doc.CreateElement("project"));

    foreach (var component in components)
        rootNode.AppendChild(doc.ReadNode(XmlTextReader.Create(new StringReader(serialize(component, true)))));

    Console.WriteLine(doc.OuterXml);
    Console.WriteLine(deserialize<Component_1>(rootNode.ChildNodes[0].OuterXml).Value);
}
string serialize(object obj, bool namespaces)
{
    StringBuilder sb = new StringBuilder();
    XmlWriter writer = XmlWriter.Create(sb, new XmlWriterSettings() { OmitXmlDeclaration = true });
    (new XmlSerializer(obj.GetType())).Serialize(writer, obj, namespaces ? null : new XmlSerializerNamespaces(new XmlQualifiedName[] { new XmlQualifiedName("", "") }));
    return sb.ToString();
}
T deserialize<T>(string xmlString)
{
    return (T)(new XmlSerializer(typeof(T))).Deserialize(new StringReader(xmlString));
}

Być może możliwe jest dodanie przestrzeni nazw do dokumentu (rootNode) i utworzenie nowego ciągu znaków XmlNode z funkcją XmlDocument.ReadNode w celu rozwiązania przestrzeni nazw w łańcuchu przez przestrzenie nazw XmlDocument. Ale nie wiem jak.

AKTUALIZACJA 2:
Dzięki Alex Filipovici, wyjście serializacji jest dokładnie tym, czego chciałem.

void test2()
{
    object[] components = new object[] { new Component_1(), new Component_1() };

    var doc = new XmlDocument();

    var project = doc.AppendChild(doc.CreateElement("project"));

    doc.DocumentElement.SetAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
    doc.DocumentElement.SetAttribute("xmlns:xsd", "http://www.w3.org/2001/XMLSchema");

    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");

    Component_1 c = deserialize<Component_1>(project.ChildNodes[0].OuterXml);

    Console.WriteLine(c.objectArray[0].GetType()); // -> System.Xml.XmlNode[] !
}

wydajność:

<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Component_1>
    <Value>Component_1.Value</Value>
    <objectArray>
      <anyType type="string">one</anyType>
      <anyType type="string">two</anyType>
    </objectArray>
  </Component_1>
  <Component_1>
    <Value>Component_1.Value</Value>
    <objectArray>
      <anyType type="string">one</anyType>
      <anyType type="string">two</anyType>
    </objectArray>
  </Component_1>
</project>

Ale teraz deserializacja za pomocą powyższej funkcji „T desirialize (string xmlString)” nie powiedzie się. Tablica obiektów zawiera XmlNodes.

Czy można powiedzieć XmlSerializer, aby używał przestrzeni nazw z węzła projektu, czy też muszę je wstawić ponownie?

questionAnswers(2)

yourAnswerToTheQuestion