Para aquellos que también intentan encontrar una solución más viable, ignoren esto. Es una antigua biblioteca .NET. En su lugar, use XDocument y se ahorrará arrancarse los ojos de frustración
AER
Respuestas:
177
El medio principal de lectura y escritura en C # 2.0 se realiza a través de la clase XmlDocument . Puede cargar la mayoría de sus configuraciones directamente en XmlDocument a través del XmlReader que acepta.
Cargando XML directamente
XmlDocument document = new XmlDocument();
document.LoadXml("<People><PersonName='Nick' /><PersonName='Joe' /></People>");
Cargar XML desde un archivo
XmlDocument document = new XmlDocument();
document.Load(@"C:\Path\To\xmldoc.xml");
// Or using an XmlReader/XmlTextReader
XmlReader reader = XmlReader.Create(@"C:\Path\To\xmldoc.xml");
document.Load(reader);
Encuentro que la forma más fácil / rápida de leer un documento XML es utilizando XPath.
Leer un documento XML usando XPath (usando XmlDocument que nos permite editar)
XmlDocument document = new XmlDocument();
document.LoadXml("<People><Person Name='Nick' /><Person Name='Joe' /></People>");
// Select a single node
XmlNode node = document.SelectSingleNode("/People/Person[@Name = 'Nick']");
// Select a list of nodes
XmlNodeList nodes = document.SelectNodes("/People/Person");
Si necesita trabajar con documentos XSD para validar un documento XML, puede usar esto.
Validación de XML contra XSD en cada nodo (ACTUALIZACIÓN 1)
XmlReaderSettings settings = new XmlReaderSettings();
settings.ValidateType = ValidationType.Schema;
settings.Schemas.Add("", pathToXsd); // targetNamespace, pathToXsd
settings.ValidationEventHandler += new ValidationEventHandler(settings_ValidationEventHandler);
XmlReader reader = XmlReader.Create(pathToXml, settings);
while (reader.Read()) { }
privatevoidsettings_ValidationEventHandler(object sender, ValidationEventArgs args)
{
// e.Message, e.Severity (warning, error), e.Error// or you can access the reader if you have access to it// reader.LineNumber, reader.LinePosition.. etc
}
En .NET 3.5, usa XDocument para realizar tareas similares. Sin embargo, la diferencia es que tiene la ventaja de realizar consultas Linq para seleccionar los datos exactos que necesita. Con la adición de inicializadores de objetos, puede crear una consulta que incluso devuelva objetos de su propia definición directamente en la consulta.
XDocument doc = XDocument.Load(pathToXml);
List<Person> people = (from xnode in doc.Element("People").Elements("Person")
selectnew Person
{
Name = xnode.Attribute("Name").Value
}).ToList();
(ACTUALIZACIÓN 2)
Una buena forma en .NET 3.5 es usar XDocument para crear XML a continuación. Esto hace que el código aparezca en un patrón similar al resultado deseado.
XDocument doc =
new XDocument(
new XDeclaration("1.0", Encoding.UTF8.HeaderName, String.Empty),
new XComment("Xml Document"),
new XElement("catalog",
new XElement("book", new XAttribute("id", "bk001"),
new XElement("title", "Book Title")
)
)
);
Es posible que desee señalar que está utilizando XDocument en el último ejemplo, ya que XDocument es bastante diferente a XmlDocument
Aaron Powell
2
Corrección; no hay C # 3.5; te refieres a .NET 3.5 y C # 3.0
Marc Gravell
Ah, y los [inicializadores de objetos] "sobre la marcha" funcionarían prácticamente igual con C # 3.0 y XmlDocument; sin embargo, sigue siendo una buena respuesta (+1)
Marc Gravell
Vale la pena mencionar que si está cargando un documento para consultarlo con XPath (y no para editar), entonces usar un XPathDocument será mucho más eficiente
Oliver Hallam
¿Esta validación de esquema se realiza nodo por nodo? Si no es así, ¿hay alguna forma de hacerlo nodo por nodo?
Malik Daud Ahmad Khokhar
30
Depende del tamaño; para xml de tamaño pequeño a mediano, un DOM como XmlDocument (cualquier versión de C # / .NET) o XDocument (.NET 3.5 / C # 3.0) es el ganador obvio. Para usar xsd, puede cargar xml usando un XmlReader , y un XmlReader acepta (para crear ) un XmlReaderSettings . Los objetos XmlReaderSettings tienen una propiedad Schemas que se puede usar para realizar la validación xsd (o dtd).
Para escribir xml, se aplican las mismas cosas, teniendo en cuenta que es un poco más fácil diseñar contenido con LINQ-to-XML (XDocument) que con XmlDocument anterior.
Sin embargo, para xml de gran tamaño, un DOM puede consumir demasiada memoria, en cuyo caso es posible que deba usar XmlReader / XmlWriter directamente.
Finalmente, para manipular xml, es posible que desee utilizar XslCompiledTransform (una capa xslt).
La alternativa a trabajar con xml es trabajar con un modelo de objetos; puede usar xsd.exe para crear clases que representen un modelo compatible con xsd, y simplemente cargar el xml como objetos , manipularlo con OO y luego serializar esos objetos nuevamente; haces esto con XmlSerializer .
Manipular (agregar / suministrar elementos) un documento XML grande (40k líneas). Cual es la mejor manera? Solía usar LINQ-to-XML.
Neyoh
12
La respuesta de nyxtom es muy buena. Le agregaría un par de cosas:
Si necesita acceso de solo lectura a un documento XML, XPathDocumentes un objeto mucho más liviano que XmlDocument.
La desventaja de usar XPathDocumentes que no se puede utilizar el familiar SelectNodesy SelectSingleNodemétodos de XmlNode. En su lugar, debe usar las herramientas que IXPathNavigableproporciona: use CreateNavigatorpara crear un XPathNavigator, y use XPathNavigatorpara crear XPathNodeIterators para iterar sobre las listas de nodos que encuentre a través de XPath. Esto generalmente requiere algunas líneas más de código que los XmlDocumentmétodos.
Pero: las clases XmlDocumenty XmlNodese implementan IXPathNavigable, por lo que cualquier código que escriba para usar esos métodos en un XPathDocumenttambién funcionará en un XmlDocument. Si te acostumbras a escribir en contra IXPathNavigable, tus métodos pueden funcionar contra cualquier objeto. (Esta es la razón por la que FxCop marca el uso de XmlNodey XmlDocumenten las firmas de métodos).
Lamentablemente, XDocumenty XElement( XNodey XObject) no se implementan IXPathNavigable.
Otra cosa que no está presente en la respuesta de nyxtom es XmlReader. Por lo general, se usa XmlReaderpara evitar la sobrecarga de analizar el flujo XML en un modelo de objeto antes de comenzar a procesarlo. En su lugar, utiliza un XmlReaderpara procesar el flujo de entrada un nodo XML a la vez. Esta es esencialmente la respuesta de .NET a SAX. Le permite escribir código muy rápido para procesar documentos XML muy grandes.
XmlReader también proporciona la forma más sencilla de procesar fragmentos de documentos XML, por ejemplo, el flujo de elementos XML sin ningún elemento adjunto que devuelve la opción FOR XML RAW de SQL Server.
El código que escribe utilizando XmlReadergeneralmente está muy estrechamente acoplado al formato del XML que está leyendo. El uso de XPath permite que su código esté mucho más acoplado al XML, por lo que generalmente es la respuesta correcta. Pero cuando lo necesita XmlReader, realmente lo necesita.
En primer lugar, conozca las nuevas clases XDocument y XElement , porque son una mejora con respecto a la familia XmlDocument anterior.
Trabajan con LINQ
Son más rápidos y ligeros
Sin embargo , es posible que deba seguir usando las clases antiguas para trabajar con código heredado, en particular los proxies generados anteriormente. En ese caso, deberá familiarizarse con algunos patrones para interoperar entre estas clases de manejo de XML.
Creo que su pregunta es bastante amplia y requeriría demasiado en una sola respuesta para dar detalles, pero esta es la primera respuesta general en la que pensé y sirve como un comienzo.
Si crea un conjunto de datos escrito en el diseñador, automáticamente obtiene un xsd, un objeto fuertemente tipado, y puede cargar y guardar el xml con una línea de código.
He tenido un gran éxito con DataSet's. También son muy amigables con las bases de datos.
Usuario1
1
Mi opinión personal, como programador de C #, es que la mejor manera de tratar con XML en C # es delegar esa parte del código a un proyecto de VB .NET. En .NET 3.5, VB .NET tiene XML Literals, lo que hace que el manejo de XML sea mucho más intuitivo. Vea aquí, por ejemplo:
No vale la pena cambiar a vb solo para XML literal. XML solo se ocupa de literales. Si el xml se pasa como parámetro, el soporte literal XML no le brinda muchos beneficios. En cambio, la sintaxis heredada de vb.net arruinará la feliz experiencia de programación de C #.
Gqqnbig
0
nyxtom,
¿No deberían coincidir "doc" y "xdoc" en el Ejemplo 1?
XDocument **doc** = XDocument.Load(pathToXml);
List<Person> people = (from xnode in **xdoc**.Element("People").Elements("Person")
selectnew Person
{
Name = xnode.Attribute("Name").Value
}).ToList();
Envié una edición para aprobación de la respuesta a la que se refiere, sin embargo, esto realmente debería haber sido un comentario, no una respuesta.
David Thompson
Gracias David. De acuerdo, no me permitiría comentar en ese momento. No estoy seguro de por qué.
mokumaxCraig
0
La respuesta de Cookey es buena ... pero aquí hay instrucciones detalladas sobre cómo crear un objeto fuertemente tipado a partir de un XSD (o XML) y serializar / deserializar en unas pocas líneas de código:
Si alguna vez necesita convertir datos entre XmlNode<=> XNode<=> XElement
(por ejemplo, para usar LINQ), estas Extensiones pueden ser útiles para usted:
XmlDocument MyXmlDocument = new XmlDocument();
MyXmlDocument.Load("MyXml.xml");
XElement MyXElement = MyXmlDocument.GetXElement(); // Convert XmlNode to XElementList<XElement> List = MyXElement.Document
.Descendants()
.ToList(); // Now you can use LINQ
...
Respuestas:
El medio principal de lectura y escritura en C # 2.0 se realiza a través de la clase XmlDocument . Puede cargar la mayoría de sus configuraciones directamente en XmlDocument a través del XmlReader que acepta.
Cargando XML directamente
XmlDocument document = new XmlDocument(); document.LoadXml("<People><Person Name='Nick' /><Person Name='Joe' /></People>");
Cargar XML desde un archivo
XmlDocument document = new XmlDocument(); document.Load(@"C:\Path\To\xmldoc.xml"); // Or using an XmlReader/XmlTextReader XmlReader reader = XmlReader.Create(@"C:\Path\To\xmldoc.xml"); document.Load(reader);
Encuentro que la forma más fácil / rápida de leer un documento XML es utilizando XPath.
Leer un documento XML usando XPath (usando XmlDocument que nos permite editar)
XmlDocument document = new XmlDocument(); document.LoadXml("<People><Person Name='Nick' /><Person Name='Joe' /></People>"); // Select a single node XmlNode node = document.SelectSingleNode("/People/Person[@Name = 'Nick']"); // Select a list of nodes XmlNodeList nodes = document.SelectNodes("/People/Person");
Si necesita trabajar con documentos XSD para validar un documento XML, puede usar esto.
Validación de documentos XML con esquemas XSD
XmlReaderSettings settings = new XmlReaderSettings(); settings.ValidateType = ValidationType.Schema; settings.Schemas.Add("", pathToXsd); // targetNamespace, pathToXsd XmlReader reader = XmlReader.Create(pathToXml, settings); XmlDocument document = new XmlDocument(); try { document.Load(reader); } catch (XmlSchemaValidationException ex) { Trace.WriteLine(ex.Message); }
Validación de XML contra XSD en cada nodo (ACTUALIZACIÓN 1)
XmlReaderSettings settings = new XmlReaderSettings(); settings.ValidateType = ValidationType.Schema; settings.Schemas.Add("", pathToXsd); // targetNamespace, pathToXsd settings.ValidationEventHandler += new ValidationEventHandler(settings_ValidationEventHandler); XmlReader reader = XmlReader.Create(pathToXml, settings); while (reader.Read()) { } private void settings_ValidationEventHandler(object sender, ValidationEventArgs args) { // e.Message, e.Severity (warning, error), e.Error // or you can access the reader if you have access to it // reader.LineNumber, reader.LinePosition.. etc }
Escribir un documento XML (manualmente)
XmlWriter writer = XmlWriter.Create(pathToOutput); writer.WriteStartDocument(); writer.WriteStartElement("People"); writer.WriteStartElement("Person"); writer.WriteAttributeString("Name", "Nick"); writer.WriteEndElement(); writer.WriteStartElement("Person"); writer.WriteStartAttribute("Name"); writer.WriteValue("Nick"); writer.WriteEndAttribute(); writer.WriteEndElement(); writer.WriteEndElement(); writer.WriteEndDocument(); writer.Flush();
(ACTUALIZACIÓN 1)
En .NET 3.5, usa XDocument para realizar tareas similares. Sin embargo, la diferencia es que tiene la ventaja de realizar consultas Linq para seleccionar los datos exactos que necesita. Con la adición de inicializadores de objetos, puede crear una consulta que incluso devuelva objetos de su propia definición directamente en la consulta.
XDocument doc = XDocument.Load(pathToXml); List<Person> people = (from xnode in doc.Element("People").Elements("Person") select new Person { Name = xnode.Attribute("Name").Value }).ToList();
(ACTUALIZACIÓN 2)
Una buena forma en .NET 3.5 es usar XDocument para crear XML a continuación. Esto hace que el código aparezca en un patrón similar al resultado deseado.
XDocument doc = new XDocument( new XDeclaration("1.0", Encoding.UTF8.HeaderName, String.Empty), new XComment("Xml Document"), new XElement("catalog", new XElement("book", new XAttribute("id", "bk001"), new XElement("title", "Book Title") ) ) );
crea
<!--Xml Document--> <catalog> <book id="bk001"> <title>Book Title</title> </book> </catalog>
Todo lo demás falla, puede consultar este artículo de MSDN que tiene muchos ejemplos que he discutido aquí y más. http://msdn.microsoft.com/en-us/library/aa468556.aspx
fuente
Depende del tamaño; para xml de tamaño pequeño a mediano, un DOM como XmlDocument (cualquier versión de C # / .NET) o XDocument (.NET 3.5 / C # 3.0) es el ganador obvio. Para usar xsd, puede cargar xml usando un XmlReader , y un XmlReader acepta (para crear ) un XmlReaderSettings . Los objetos XmlReaderSettings tienen una propiedad Schemas que se puede usar para realizar la validación xsd (o dtd).
Para escribir xml, se aplican las mismas cosas, teniendo en cuenta que es un poco más fácil diseñar contenido con LINQ-to-XML (XDocument) que con XmlDocument anterior.
Sin embargo, para xml de gran tamaño, un DOM puede consumir demasiada memoria, en cuyo caso es posible que deba usar XmlReader / XmlWriter directamente.
Finalmente, para manipular xml, es posible que desee utilizar XslCompiledTransform (una capa xslt).
La alternativa a trabajar con xml es trabajar con un modelo de objetos; puede usar xsd.exe para crear clases que representen un modelo compatible con xsd, y simplemente cargar el xml como objetos , manipularlo con OO y luego serializar esos objetos nuevamente; haces esto con XmlSerializer .
fuente
La respuesta de nyxtom es muy buena. Le agregaría un par de cosas:
Si necesita acceso de solo lectura a un documento XML,
XPathDocument
es un objeto mucho más liviano queXmlDocument
.La desventaja de usar
XPathDocument
es que no se puede utilizar el familiarSelectNodes
ySelectSingleNode
métodos deXmlNode
. En su lugar, debe usar las herramientas queIXPathNavigable
proporciona: useCreateNavigator
para crear unXPathNavigator
, y useXPathNavigator
para crearXPathNodeIterator
s para iterar sobre las listas de nodos que encuentre a través de XPath. Esto generalmente requiere algunas líneas más de código que losXmlDocument
métodos.Pero: las clases
XmlDocument
yXmlNode
se implementanIXPathNavigable
, por lo que cualquier código que escriba para usar esos métodos en unXPathDocument
también funcionará en unXmlDocument
. Si te acostumbras a escribir en contraIXPathNavigable
, tus métodos pueden funcionar contra cualquier objeto. (Esta es la razón por la que FxCop marca el uso deXmlNode
yXmlDocument
en las firmas de métodos).Lamentablemente,
XDocument
yXElement
(XNode
yXObject
) no se implementanIXPathNavigable
.Otra cosa que no está presente en la respuesta de nyxtom es
XmlReader
. Por lo general, se usaXmlReader
para evitar la sobrecarga de analizar el flujo XML en un modelo de objeto antes de comenzar a procesarlo. En su lugar, utiliza unXmlReader
para procesar el flujo de entrada un nodo XML a la vez. Esta es esencialmente la respuesta de .NET a SAX. Le permite escribir código muy rápido para procesar documentos XML muy grandes.XmlReader
también proporciona la forma más sencilla de procesar fragmentos de documentos XML, por ejemplo, el flujo de elementos XML sin ningún elemento adjunto que devuelve la opción FOR XML RAW de SQL Server.El código que escribe utilizando
XmlReader
generalmente está muy estrechamente acoplado al formato del XML que está leyendo. El uso de XPath permite que su código esté mucho más acoplado al XML, por lo que generalmente es la respuesta correcta. Pero cuando lo necesitaXmlReader
, realmente lo necesita.fuente
XPathNavigator CreateNavigator(this XNode node)
para crear unXPathNavigator
desde unXNode
(que incluye la clase derivadaXDocument
).En primer lugar, conozca las nuevas clases XDocument y XElement , porque son una mejora con respecto a la familia XmlDocument anterior.
Sin embargo , es posible que deba seguir usando las clases antiguas para trabajar con código heredado, en particular los proxies generados anteriormente. En ese caso, deberá familiarizarse con algunos patrones para interoperar entre estas clases de manejo de XML.
Creo que su pregunta es bastante amplia y requeriría demasiado en una sola respuesta para dar detalles, pero esta es la primera respuesta general en la que pensé y sirve como un comienzo.
fuente
101 muestras de Linq
http://msdn.microsoft.com/en-us/library/bb387098.aspx
y Linq to XML samples
http://msdn.microsoft.com/en-us/vbasic/bb688087.aspx
Y creo que Linq facilita XML.
fuente
Si está trabajando en .NET 3.5 y no le teme al código experimental, puedes consultar LINQ to XSD ( http://blogs.msdn.com/xmlteam/archive/2008/02/21/linq-to- xsd-alpha-0-2.aspx ) que generará clases .NET a partir de un XSD (incluidas las reglas integradas del XSD).
Luego tiene la capacidad de escribir directamente en un archivo y leer desde un archivo, asegurándose de que cumpla con las reglas XSD.
Definitivamente sugiero tener un XSD para cualquier documento XML con el que trabaje:
¡Encuentro que Liquid XML Studio es una gran herramienta para generar XSD y es gratis!
fuente
Escribir XML con la clase XmlDocument
//itemValues is collection of items in Key value pair format //fileName i name of XML file which to creatd or modified with content private void WriteInXMLFile(System.Collections.Generic.Dictionary<string, object> itemValues, string fileName) { string filePath = "C:\\\\tempXML\\" + fileName + ".xml"; try { if (System.IO.File.Exists(filePath)) { XmlDocument doc = new XmlDocument(); doc.Load(filePath); XmlNode rootNode = doc.SelectSingleNode("Documents"); XmlNode pageNode = doc.CreateElement("Document"); rootNode.AppendChild(pageNode); foreach (string key in itemValues.Keys) { XmlNode attrNode = doc.CreateElement(key); attrNode.InnerText = Convert.ToString(itemValues[key]); pageNode.AppendChild(attrNode); //doc.DocumentElement.AppendChild(attrNode); } doc.DocumentElement.AppendChild(pageNode); doc.Save(filePath); } else { XmlDocument doc = new XmlDocument(); using(System.IO.FileStream fs = System.IO.File.Create(filePath)) { //Do nothing } XmlNode rootNode = doc.CreateElement("Documents"); doc.AppendChild(rootNode); doc.Save(filePath); doc.Load(filePath); XmlNode pageNode = doc.CreateElement("Document"); rootNode.AppendChild(pageNode); foreach (string key in itemValues.Keys) { XmlNode attrNode = doc.CreateElement(key); attrNode.InnerText = Convert.ToString(itemValues[key]); pageNode.AppendChild(attrNode); //doc.DocumentElement.AppendChild(attrNode); } doc.DocumentElement.AppendChild(pageNode); doc.Save(filePath); } } catch (Exception ex) { } } OutPut look like below <Dcouments> <Document> <DocID>01<DocID> <PageName>121<PageName> <Author>Mr. ABC<Author> <Dcoument> <Document> <DocID>02<DocID> <PageName>122<PageName> <Author>Mr. PQR<Author> <Dcoument> </Dcouments>
fuente
Si crea un conjunto de datos escrito en el diseñador, automáticamente obtiene un xsd, un objeto fuertemente tipado, y puede cargar y guardar el xml con una línea de código.
fuente
Mi opinión personal, como programador de C #, es que la mejor manera de tratar con XML en C # es delegar esa parte del código a un proyecto de VB .NET. En .NET 3.5, VB .NET tiene XML Literals, lo que hace que el manejo de XML sea mucho más intuitivo. Vea aquí, por ejemplo:
Descripción general de LINQ to XML en Visual Basic
(Asegúrese de configurar la página para que muestre el código VB, no el código C #).
Escribiría el resto del proyecto en C #, pero manejaría el XML en un proyecto VB referenciado.
fuente
nyxtom,
¿No deberían coincidir "doc" y "xdoc" en el Ejemplo 1?
XDocument **doc** = XDocument.Load(pathToXml); List<Person> people = (from xnode in **xdoc**.Element("People").Elements("Person") select new Person { Name = xnode.Attribute("Name").Value }).ToList();
fuente
La respuesta de Cookey es buena ... pero aquí hay instrucciones detalladas sobre cómo crear un objeto fuertemente tipado a partir de un XSD (o XML) y serializar / deserializar en unas pocas líneas de código:
Instrucciones
fuente
Si alguna vez necesita convertir datos entre
XmlNode
<=>XNode
<=>XElement
(por ejemplo, para usar LINQ), estas Extensiones pueden ser útiles para usted:
public static class MyExtensions { public static XNode GetXNode(this XmlNode node) { return GetXElement(node); } public static XElement GetXElement(this XmlNode node) { XDocument xDoc = new XDocument(); using (XmlWriter xmlWriter = xDoc.CreateWriter()) node.WriteTo(xmlWriter); return xDoc.Root; } public static XmlNode GetXmlNode(this XElement element) { using (XmlReader xmlReader = element.CreateReader()) { XmlDocument xmlDoc = new XmlDocument(); xmlDoc.Load(xmlReader); return xmlDoc; } } public static XmlNode GetXmlNode(this XNode node) { return GetXmlNode(node); } }
Uso:
XmlDocument MyXmlDocument = new XmlDocument(); MyXmlDocument.Load("MyXml.xml"); XElement MyXElement = MyXmlDocument.GetXElement(); // Convert XmlNode to XElement List<XElement> List = MyXElement.Document .Descendants() .ToList(); // Now you can use LINQ ...
fuente