2010-09-17 12 views
11

Mi plan es leer en un documento XML utilizando mi programa C#, buscar entradas particulares que me gustaría cambiar, y luego escribir el documento modificado. Sin embargo, me he deshecho porque es difícil diferenciar elementos, ya sea que comiencen o terminen usando XmlTextReader que estoy usando para leer en el archivo. Podría hacer un poco de consejo para ponerme en el camino correcto.mejor manera de leer, modificar y escribir XML

el documento es un documento HTML, así como se puede imaginar, es bastante complicado.

me gustaría buscar un identificador de elemento dentro del documento HTML, por lo que, por ejemplo, buscar esto y cambiar el src;

<img border="0" src="bigpicture.png" width="248" height="36" alt="" id="lookforthis" /> 
+0

¿Hay alguna razón en particular para hacer esto en C#? Parece exactamente el tipo de problema para el que XSLT fue diseñado. –

+0

El documento tiene tres llamadas XSLT a la configuración de divs en el documento. A menos que pueda cargar un archivo html externo a través de XSLT, en lugar de copiarlo, modifíquelo. – wonea

+0

He revisado el documento html y lo he arreglado para que funcione perfectamente, y se carga en una herramienta XML como jsXe sin errores – wonea

Respuesta

28

Si es realmente válido XML, y encajará fácilmente en la memoria, elegiría LINQ to XML (XDocument, XElement etc.) cada vez. Es de lejos la mejor API de XML que he usado. Es fácil formular consultas y también es fácil construir nuevos elementos.

Puede usar XPath cuando corresponda, o los métodos de ejes incorporados (Elements(), Descendants(), Attributes(), etc.). Si pudieras decirnos con qué bits específicos te está costando pasar, con gusto te ayudaría a encontrar la manera de expresarlos en LINQ to XML.

Si, por otro lado, este es HTML que no es XML válido, lo tendrá mucho más difícil, porque las API XML generalmente esperan trabajar con documentos XML válidos. Puede usar HTMLTidy primero, por supuesto, pero puede tener efectos no deseados.

Para su ejemplo específico:

XDocument doc = XDocument.Load("file.xml"); 
foreach (var img in doc.Descendants("img")) 
{ 
    // src will be null if the attribute is missing 
    string src = (string) img.Attribute("src"); 
    img.SetAttributeValue("src", src + "with-changes"); 
} 
+0

Bump XDocument para una gran justicia. – annakata

+1

¡Estoy de acuerdo! Tenía un par de aplicaciones antiguas que tenía que hacer de la manera difícil con el análisis y similares y L2X lo hace mucho más fácil y poderoso. –

+1

Jon, puede encontrar que HtmlAgilityPack es muy útil, en lugar de preocuparse por XML válido, puede usar APIs similares a XDocument en HTML sucio y real. –

0

Simplemente comienza por la lectura de la documentación de la Xml namespace on the MSDN. Entonces, si usted tiene preguntas más específicas, colocarlas aquí ...

1

Si tiene documentos más pequeños que caben en la memoria de los ordenadores puede utilizar XmlDocument. contrario, puede utilizar XmlReader para recorrer el documento.

Usando XmlReader puede averiguar los elementos escribir con:

while (xml.Read()) { 
    switch xml.NodeType { 
    case XmlNodeType.Element: 
     //Do something 
    case XmlNodeType.Text: 
     //Do something 
    case XmlNodeType.EndElement: 
     //Do something 
    } 
} 
4

son los documentos que se están procesando relativamente pequeño? De ser así, podría cargarlos en la memoria utilizando un objeto XmlDocument, modificarlo y volver a escribir los cambios.

XmlDocument doc = new XmlDocument(); 
doc.Load("path_to_input_file"); 
// Make changes to the document. 
using(XmlTextWriter xtw = new XmlTextWriter("path_to_output_file", Encoding.UTF8)) { 
    xtw.Formatting = Formatting.Indented; // optional, if you want it to look nice 
    doc.WriteContentTo(xtw); 
} 

Dependiendo de la estructura del XML de entrada, esto podría hacer que su código de análisis sea un poco más simple.

0

Un enfoque bastante fácil sería crear un nuevo XmlDocument, luego utilizar el método Load() para poblarlo. Una vez que tenga el documento, puede utilizar CreateNavigator() para obtener un objeto XPathNavigator que se puede utilizar para encontrar y alterar los elementos del documento. Finalmente, puede usar el método Save() en el XmlDocument para volver a escribir el documento modificado.

1

para la tarea en cuestión - (leer documento existente, escribir y modificar de una manera formalizada) me gustaría ir con XPathDocument carrera a través de un XslCompiledTransform.

Donde no puede formalizar, no tiene documentos preexistentes o generalmente necesita una lógica más adaptable, yo elegiría LINQ y XDocument como dice Skeet.

Básicamente si la tarea es transformación, entonces XSLT, si la tarea es manipulación, entonces LINQ.

1

Mi herramienta favorita para este tipo de cosas es HtmlAgilityPack. Lo uso para analizar documentos HTML complejos en colecciones consultables de LINQ. Es una herramienta extremadamente útil para consultar y analizar HTML (que a menudo no es XML válido).

para su problema, el código se vería así:

var htmlDoc = HtmlAgilityPack.LoadDocument(stringOfHtml); 
var images = htmlDoc.DocumentNode.SelectNodes("//img[id=lookforthis]"); 

if(images != null) 
{ 
    foreach (HtmlNode node in images) 
    { 
     node.Attributes.Append("alt", "added an alt to lookforthis images."); 
    } 
} 

htmlDoc.Save('output.html'); 
2

Aquí hay una herramienta que escribí para modificar el archivo de un proyecto de IAR EWARM (EWP), la adición de un enlazador definir al proyecto. Desde la línea de comando, lo ejecuta con 2 argumentos, los nombres de archivo de entrada y salida (* .ewp).

using System; 
    using System.Collections.Generic; 
    using System.Linq; 
    using System.Text; 
    using System.Xml; 

    namespace ewp_tool 
    { 
     class Program 
     { 
      static void Main(string[] args) 
      { 
       XmlDocument doc = new XmlDocument(); 
       doc.Load(args[0]); 

       XmlNodeList list = doc.SelectNodes("/project/configuration[name='Debug']/settings[name='ILINK']/data/option[name='IlinkConfigDefines']/state"); 
       foreach(XmlElement x in list) { 
        x.InnerText = "MAIN_APP=1"; 
       } 

       using (XmlTextWriter xtw = new XmlTextWriter(args[1], Encoding.UTF8)) 
       { 
        //xtw.Formatting = Formatting.Indented; // leave this out, it breaks EWP! 
        doc.WriteContentTo(xtw); 
       } 
      } 
     } 
    } 

La estructura del XML se parece a esto

<U+FEFF><?xml version="1.0" encoding="iso-8859-1"?> 
    <project> 
     <fileVersion>2</fileVersion> 
     <configuration> 
     <name>Debug</name> 
     <toolchain> 
      <name>ARM</name> 
     </toolchain> 
     <debug>1</debug> 

     ... 

     <settings> 
      <name>ILINK</name> 
      <archiveVersion>0</archiveVersion> 
      <data> 

      ... 

      <option> 
       <name>IlinkConfigDefines</name> 
       <state>MAIN_APP=0</state> 
      </option> 
Cuestiones relacionadas