convertir xml a dataset c#
XmlReader-Necesito editar un elemento y producir uno nuevo (5)
Lo arreglé usando la siguiente codificación de cinta adhesiva
public XmlReader FixUpReader(XmlReader reader)
{
reader.MoveToContent();
string xml = reader.ReadOuterXml();
string dslVersion = GetDSLVersion();
string Id = GetID();
string processedValue = string.Format("<ExampleElement dslVersion=/"{1}/" Id=/"{2}/" ", dslVersion, Id);
xml = xml.Replace("<ExampleElement ", processedValue);
MemoryStream ms = new MemoryStream(System.Text.Encoding.ASCII.GetBytes(xml));
XmlReaderSettings settings = new XmlReaderSettings();
XmlReader myReader = XmlReader.Create(ms);
myReader.MoveToContent();
return myReader;
}
Me siento sucio por hacerlo de esta manera, pero está funcionando ...
Estoy anulando un método que tiene un XmlReader que se transfiere, necesito encontrar un elemento específico, agregar un atributo y luego crear un nuevo XmlReader o simplemente reemplazar el existente con el contenido modificado. Estoy usando C # 4.0
He investigado el uso de XElement (Linq) pero parece que no puedo manipular un elemento existente y agregar un atributo y valor.
Sé que el XmlWriter tiene WriteAttributeString, que sería fantástico, pero una vez más, no estoy seguro de cómo encaja todo
Me gustaría poder hacer algo como --- ¡Esto es un pseudocódigo!
public XmlReader DoSomethingWonderful(XmlReader reader)
{
Element element = reader.GetElement("Test");
element.SetAttribute("TestAttribute","This is a test");
reader.UpdateElement(element);
return reader;
}
No se puede hacer esto fácilmente con XmlReader
, al menos no sin leer todo el documento XML del lector, continuar con él y luego crear un nuevo XmlReader
partir del resultado. XmlReader
embargo, XmlReader
no XmlReader
uso de XmlReader
, es decir, la posibilidad de transmitir documentos de gran tamaño.
Podrías derivar de XmlReader
, reenviando la mayoría de las llamadas al lector existente, pero interceptándolas cuando sea necesario para agregar atributos adicionales, etc. ... pero sospecho que ese código sería realmente bastante complejo y frágil.
Prefiero cargar el xml en el objeto XmlDocument
y usar la colección de Attributes
para modificar el valor y llamar al método Save
para actualizar este valor. El siguiente código funciona para mí.
public static void WriteElementValue ( string sName, string element, string value)
{
try
{
var node = String.Format("//elements/element[@name=''{0}'']", sName);
var doc = new XmlDocument { PreserveWhitespace = true };
doc.Load(configurationFileName);
var nodeObject = doc.SelectSingleNode(node);
if (nodeObject == null)
throw new XmlException(String.Format("{0} path does not found any matching
node", node));
var elementObject = nodeObject[element];
if (elementObject != null)
{
elementObject.Attributes["value"].Value = value;
}
doc.Save(configurationFileName);
}
catch (Exception ex)
{
throw new ExitLevelException(ex, false);
}
}
También he observado que cuando usas XmlWriter o XmlSerializer los espacios en blanco no se conservan correctamente, esto puede ser molesto a veces
string newvalue = "10";
string presentvalue = "";
string newstr = "";
XmlReader xmlr = XmlReader.Create(new StringReader(str));
while (xmlr.Read())
{
if (xmlr.NodeType == XmlNodeType.Element)
{
if (xmlr.Name == "priority")
{
presentvalue = xmlr.ReadElementContentAsString();
newstr = str.Replace(presentvalue, newvalue);
}
}
}
// newstr se puede volver a escribir en el archivo ... que es el xml editado
XmlReader / Writer son secuencias de acceso secuenciales. Tendrá que leer en un extremo, procesar la transmisión como lo desee y escribirla en el otro extremo. La ventaja es que no necesita leer todo en la memoria y crear un DOM, que es lo que obtendría con cualquier enfoque basado en XmlDocument.
Este método debería ayudarlo a comenzar:
private static void PostProcess(Stream inStream, Stream outStream)
{
var settings = new XmlWriterSettings() { Indent = true, IndentChars = " " };
using (var reader = XmlReader.Create(inStream))
using (var writer = XmlWriter.Create(outStream, settings)) {
while (reader.Read()) {
switch (reader.NodeType) {
case XmlNodeType.Element:
writer.WriteStartElement(reader.Prefix, reader.Name, reader.NamespaceURI);
writer.WriteAttributes(reader, true);
//
// check if this is the node you want, inject attributes here.
//
if (reader.IsEmptyElement) {
writer.WriteEndElement();
}
break;
case XmlNodeType.Text:
writer.WriteString(reader.Value);
break;
case XmlNodeType.EndElement:
writer.WriteFullEndElement();
break;
case XmlNodeType.XmlDeclaration:
case XmlNodeType.ProcessingInstruction:
writer.WriteProcessingInstruction(reader.Name, reader.Value);
break;
case XmlNodeType.SignificantWhitespace:
writer.WriteWhitespace(reader.Value);
break;
}
}
}
}
Esto no es tan limpio como obtener tu propio XmlWriter, pero creo que es mucho más fácil.
[EDITAR]
Un ejemplo de cómo abriría dos transmisiones a la vez podría ser algo como esto:
using (FileStream readStream = new FileStream(@"c:/myFile.xml", FileMode.OpenOrCreate, FileAccess.Read, FileShare.Write)) {
using (FileStream writeStream = new FileStream(@"c:/myFile.xml", FileMode.OpenOrCreate, FileAccess.Write)) {
PostProcess(readStream, writeStream);
}
}