read - xml c# ejemplo
¿Cómo creo un XmlNode desde una llamada a XmlSerializer.Serialize? (4)
Estoy usando 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
al cual me permite extender los datos de configuración para mis propios fines sin modificar la biblioteca de clases original.
<?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 permita al usuario generar un nuevo archivo de configuración que incluya tanto la configuración de la biblioteca de clases como mi propia configuración, para que se creen nuevos objetos que no se leyeron 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 a 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 XmlNode
representados por un XmlNode
después de llamar a Serialize
. ¿Cuál es la mejor manera de serializar un objeto en un XmlNode
usando XmlSerializer
?
Gracias,
-kevin
btw-- Parece que una clase XmlNodeWriter
escrita por Chris Lovett estuvo disponible en un momento de Microsoft, pero los enlaces ahora están rotos. ¿Alguien sabe de una ubicación alternativa para obtener esta clase?
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.
Entonces, 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ías tomar la cadena creada por el 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 su configuración personalizada serializada.
¿Eso es todo lo que estás buscando?
Tomó un poco de trabajo, pero la ruta XPathNavigator funciona ... solo recuerda llamar. Cerrar 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);
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 haya una mejor manera, pero resuelve mi problema por el momento.
¡Ahora si pudiera encontrar el mítico XmlNodeWriter al que se hace referencia en varios blogs!