leer - Cómo lidiar con XML en C#
leer xml c# linq (11)
¿Cuál es la mejor manera de tratar con documentos XML, XSD, etc. en C # 2.0?
Qué clases usar, etc. ¿Cuáles son las mejores prácticas de análisis y creación de documentos XML, etc.
EDIT: sugerencias de .Net 3.5 también son bienvenidas.
101 muestras de Linq
http://msdn.microsoft.com/en-us/library/bb387098.aspx
y Linq a muestras XML
http://msdn.microsoft.com/en-us/vbasic/bb688087.aspx
Y creo que Linq simplifica XML.
Depende del tamaño; para xml de tamaño pequeño a mediano, un DOM como XmlDocument (cualquier XmlDocument 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 Create ) 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, señalando que es un poco más fácil diseñar contenido con LINQ-a-XML (XDocument) que el antiguo XmlDocument.
Sin embargo, para xml enorme, un DOM puede consumir demasiada memoria, en cuyo caso es posible que necesite usar XmlReader / XmlWriter directamente.
Finalmente, para manipular xml, puede usar XslCompiledTransform (una capa xslt).
La alternativa para 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 .
El medio principal de leer y escribir 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>");
Cargando 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);
La forma más fácil / rápida de leer un documento XML es usando 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 usarlo.
Validar documentos XML contra 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 (UPDATE 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 de Linq para seleccionar los datos exactos que necesita. Con la adición de los inicializadores de objetos, puede crear una consulta que incluso devuelva objetos de su propia definición directamente en la consulta misma.
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
En primer lugar, conozca las nuevas clases XDocument y XElement , ya que son una mejora con respecto a la familia XmlDocument anterior.
- Ellos trabajan con LINQ
- Son más rápidos y más livianos
Sin embargo , es posible que deba seguir utilizando las clases antiguas para trabajar con el código heredado, especialmente los proxies generados previamente. 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 de inicio.
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>
La respuesta de Cookey es buena ... pero aquí hay instrucciones detalladas sobre cómo crear un objeto fuertemente tipado de un XSD (o XML) y serializar / deserializar en unas pocas líneas de código:
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 que XmlDocument
.
La desventaja de usar XPathDocument
es que no puede usar los conocidos métodos SelectNodes
y SelectSingleNode
de XmlNode
. En su lugar, debe usar las herramientas que proporciona IXPathNavigable
: use CreateNavigator
para crear un XPathNavigator
, y use XPathNavigator
para crear XPathNodeIterator
para iterar sobre las listas de nodos que encuentre a través de XPath. Esto generalmente requiere unas pocas líneas de código más que los métodos XmlDocument
.
Pero: las clases XmlDocument
y XmlNode
implementan IXPathNavigable
, por lo que cualquier código que escriba para usar esos métodos en un XPathDocument
también funcionará en un XmlDocument
. Si te acostumbras a escribir en contra de IXPathNavigable
, tus métodos pueden funcionar contra cualquier objeto. (Esta es la razón por la cual FxCop marca el uso de XmlNode
y XmlDocument
en las firmas de métodos).
Lamentablemente, XDocument
y XElement
(y XNode
y XObject
) no implementan IXPathNavigable
.
Otra cosa que no está presente en la respuesta de XmlReader
es XmlReader
. Por lo general, utiliza XmlReader
para evitar la sobrecarga de analizar la secuencia XML en un modelo de objetos antes de comenzar a procesarlo. En su lugar, utiliza un XmlReader
para procesar la secuencia 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, la secuencia de elementos XML sin elemento de envolvente que devuelve la opción FOR XML RAW de SQL Server.
El código que escribe utilizando XmlReader
generalmente está muy XmlReader
al formato del XML que está leyendo. El uso de XPath permite que su código se acople mucho más libremente al XML, por lo que generalmente es la respuesta correcta. Pero cuando necesitas usar XmlReader
, realmente lo necesitas.
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 en un proyecto .NET de VB. En .NET 3.5, VB .NET tiene XML Literals, lo que hace que manejar 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.
Si crea un conjunto de datos tipeados en el diseñador, obtendrá automáticamente un xsd, un objeto fuertemente tipado, y puede cargar y guardar el xml con una línea de código.
Si está trabajando en .NET 3.5 y no tiene miedo del código experimental, puede consultar LINQ to XSD ( http://blogs.msdn.com/xmlteam/archive/2008/02/21/linq-to-xsd-alpha-0-2.aspx ) que generará clases .NET desde 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 se ajuste a las reglas de XSD.
Definitivamente sugiero tener un XSD para cualquier documento XML con el que trabajes:
- Le permite aplicar reglas en el XML
- Permite a otros ver cómo está estructurado / estructurado el XML
- Puede ser utilizado para la validación de XML
Me parece que Liquid XML Studio es una gran herramienta para generar XSD y ¡es gratis!
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();