2008-09-05 16 views
10

Estoy utilizando una biblioteca de clases que representa parte de su configuración en .xml. La configuración se lee utilizando el XmlSerializer. Afortunadamente, las clases que representan .xml usan el atributo XmlAnyElement en el cual me permite extender los datos de configuración para mis propios fines sin modificar la biblioteca de clases original.¿Cómo creo un XmlNode de una llamada a XmlSerializer.Serialize?

<?xml version="1.0" encoding="utf-8"?> 
<Config> 
    <data>This is some data</data> 
    <MyConfig> 
    <data>This is my data</data> 
    </MyConfig> 
</Config> 

Esto funciona bien para la deserialización. Puedo permitir que la biblioteca de clases deserialice el .xml de forma normal y puedo usar mis propias instancias XmlSerializer con un XmlNodeReader contra el XmlNode interno.

public class Config 
{ 
    [XmlElement] 
    public string data; 

    [XmlAnyElement] 
    public XmlNode element; 
} 

public class MyConfig 
{ 
    [XmlElement] 
    public string data; 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     using (Stream fs = new FileStream(@"c:\temp\xmltest.xml", FileMode.Open)) 
     { 
      XmlSerializer xser1 = new XmlSerializer(typeof(Config)); 
      Config config = (Config)xser1.Deserialize(fs); 

      if (config.element != null) 
      { 
       XmlSerializer xser2 = new XmlSerializer(typeof(MyConfig)); 
       MyConfig myConfig = (MyConfig)xser2.Deserialize(new XmlNodeReader(config.element)); 
      } 
     } 
    } 

Necesito crear una utilidad que permitirá al usuario generar un nuevo archivo de configuración que incluye tanto la configuración de la biblioteca de clases, así mi propia configuración, por lo que se crearán nuevos objetos que no se lee desde el. archivo xml La pregunta es ¿cómo puedo serializar los datos de nuevo en .xml?

Me doy cuenta de que tengo que llamar inicialmente al XmlSerializer.Serialize en mis datos antes de llamar al mismo método en la configuración de la biblioteca de clases. Sin embargo, esto requiere que mis datos estén representados por un XmlNode después de llamar al Serialize. ¿Cuál es la mejor manera de serializar un objeto en un XmlNode usando el XmlSerializer?

Gracias,

-Kevin

btw-- Parece una clase XmlNodeWriter escrito por Chris Lovett estaba disponible en un tiempo de Microsoft, pero los enlaces están rotos. ¿Alguien sabe de una ubicación alternativa para obtener esta clase?

Respuesta

9

Así que necesita que su clase contenga información de configuración personalizada, luego serialice esa clase a XML, luego convierta ese XML serializado en un nodo XML: ¿es eso correcto?

¿Podría tomar la cadena creada por XMLSerializer y envolverla en sus propias etiquetas XML?

XmlSerializer xs = new XmlSerializer(typeof(MyConfig)); 
StringWriter xout = new StringWriter(); 
xs.Serialize(xout, myConfig); 
XmlDocument x = new XmlDocument(); 
x.LoadXml("<myConfig>" + xout.ToString() + "</myConfig>"); 

Ahora x es un XmlDocument que contiene un elemento "<myconfig>", que tiene la configuración personalizada serializado en ella.

¿Eso es todo lo que estás buscando?

0

Una solución es serializar el objeto interno en una cadena y luego cargar la cadena en un XmlDocument donde puede encontrar el XmlNode que representa sus datos y adjuntarlo al objeto externo.

XmlSerializer xser1 = new XmlSerializer(typeof(Config)); 
XmlSerializer xser2 = new XmlSerializer(typeof(MyConfig)); 

MyConfig myConfig = new MyConfig(); 
myConfig.data = "My special data"; 

StringBuilder sb = new StringBuilder(); 
StringWriter sw = new StringWriter(sb); 
XmlWriter xw = new XmlTextWriter(sw); 
xser2.Serialize(xw, myConfig); 

XmlDocument doc = new XmlDocument(); 
doc.LoadXml(sb.ToString()); 

Config config = new Config(); 
config.data = "some new info"; 
config.element = doc.LastChild; 

xser1.Serialize(fs, config); 

Sin embargo, esta solución es engorrosa y espero que hay una manera mejor, pero se resuelve mi problema por ahora.

¡Ahora si pudiera encontrar el mítico XmlNodeWriter al que se hace referencia en varios blogs!

0

Al menos un recurso señala esto como una alternativa a XmlNodeWriter: http://msdn.microsoft.com/en-us/library/5x8bxy86.aspx. De lo contrario, podría escribir MS utilizando el formulario que tienen en el nuevo reemplazo de la Biblioteca de códigos de MSDN para GotDotNet en busca de XmlNodeWriter.

3

Me tomó un poco de trabajo, pero la ruta XPathNavigator hace el trabajo ... sólo recuerda que llamar .Close en el XmlWriter, .Flush() no hace nada:

//DataContractSerializer serializer = new DataContractSerializer(typeof(foo)); 
XmlSerializer serializer = new XmlSerializer(typeof(foo)); 

XmlDocument doc = new XmlDocument(); 
XPathNavigator nav = doc.CreateNavigator(); 
XmlWriter writer = nav.AppendChild(); 
writer.WriteStartDocument(); 
//serializer.WriteObject(writer, new foo { bar = 42 }); 
serializer.Serialize(writer, new foo { bar = 42 }); 
writer.WriteEndDocument(); 
writer.Flush(); 
writer.Close(); 

Console.WriteLine(doc.OuterXml); 
+0

'doc.DocumentElement 'devuelve el' XmlNode' deseado. – tm1