Il modo migliore per leggere, modificare e scrivere XML

Il mio piano è di leggere in un documento XML usando il mio programma C #, cercare particolari voci che vorrei modificare e quindi scrivere il documento modificato. Tuttavia, mi sono sbloccato perché è difficile distinguere tra elementi, sia che inizino o finiscano usando XmlTextReader che sto usando per leggere nel file. Potrei fare un po ‘di consigli per mettermi sulla strada giusta.

Il documento è un documento HTML, quindi, come puoi immaginare, è piuttosto complicato.

Mi piacerebbe cercare un id elemento all’interno del documento HTML, quindi per esempio cerca questo e cambia l’src;

 

Se è effettivamente XML valido e si adatta facilmente alla memoria, sceglierei LINQ su XML ( XDocument , XElement ecc.) Ogni volta. È di gran lunga la più bella API XML che ho usato. È facile formare query e creare facilmente anche nuovi elementi.

È ansible utilizzare XPath laddove appropriato, oppure i metodi degli assi incorporati ( Elements() , Descendants() , Attributes() ecc.). Se potessi farci sapere quali sono le parti specifiche con cui ti stai divertendo, sarei felice di aiutarti a capire come esprimerle in LINQ in XML.

Se, d’altra parte, questo è HTML che non è XML valido, avrete un tempo molto più difficile – perché le API XML generiche prevedono di lavorare con documenti XML validi. Naturalmente è ansible utilizzare HTMLTidy , ovviamente, ma potrebbe avere effetti indesiderati.

Per il tuo esempio specifico:

 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"); } 

I documenti che stai elaborando sono relativamente piccoli? In tal caso, è ansible caricarli in memoria utilizzando un object XmlDocument, modificarlo e scrivere nuovamente le modifiche.

 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); } 

A seconda della struttura dell’XML di input, ciò potrebbe rendere il tuo codice di analisi un po ‘più semplice.

Ecco uno strumento che ho scritto per modificare un file EWARM (ewp) del progetto IAR, aggiungendo un linker che definisce il progetto. Dalla riga di comando, lo si esegue con 2 argomenti, i nomi dei file di input e output (* .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 struttura dell’XML ha questo aspetto

  < ?xml version="1.0" encoding="iso-8859-1"?>  2  Debug  ARM  1 ...  ILINK 0  ...  

Se si dispone di documenti più piccoli che si adattano alla memoria del computer, è ansible utilizzare XmlDocument . Altrimenti puoi usare XmlReader per scorrere il documento.

Usando XmlReader puoi scoprire il tipo di elementi usando:

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

Per il compito in mano – (leggi documenti esistenti, scrivi e modifica in modo formale), io vado con XPathDocument a correre su XslCompiledTransform .

Dove non puoi formalizzare, non hai documenti preesistenti o in genere hai bisogno di più logica adtriggers, io andrei con LINQ e XDocument come dice Skeet.

Fondamentalmente se l’attività è la trasformazione allora XSLT, se l’attività è la manipolazione allora LINQ.

Il mio strumento preferito per questo genere di cose è HtmlAgilityPack . Lo uso per analizzare documenti HTML complessi in raccolte interrogabili LINQ. È uno strumento estremamente utile per interrogare e analizzare HTML (che spesso non è XML valido).

Per il tuo problema, il codice sarà simile a:

 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'); 

Un approccio abbastanza semplice sarebbe quello di creare un nuovo XmlDocument , quindi utilizzare il metodo Load() per popolarlo. Una volta ottenuto il documento, è ansible utilizzare CreateNavigator() per ottenere un object XPathNavigator che è ansible utilizzare per trovare e modificare elementi nel documento. Infine, puoi usare il metodo Save() su XmlDocument per scrivere di nuovo il documento modificato.

Inizia semplicemente leggendo la documentazione dello spazio dei nomi Xml su MSDN . Quindi se hai domande più specifiche, pubblicale qui …