2010-09-17 10 views
11

Mein Plan ist, ein XML-Dokument mit meinem C# -Programm einzulesen, nach bestimmten Einträgen zu suchen, die ich ändern möchte, und dann das geänderte Dokument auszugeben. Ich habe mich jedoch davon getrennt, weil es schwierig ist, zwischen Elementen zu unterscheiden, ob sie nun mit XmlTextReader starten oder enden, mit denen ich in der Datei lese. Ich könnte mit ein paar Ratschlägen helfen, um mich auf den richtigen Weg zu bringen.Die beste Methode zum Lesen, Ändern und Schreiben von XML

Das Dokument ist ein HTML-Dokument, so wie Sie sich vorstellen können, ist es ziemlich kompliziert.

Ich würde gerne nach einer Element-ID innerhalb des HTML-Dokuments suchen, also zum Beispiel suchen und ändern Sie die src;

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

Gibt es einen bestimmten Grund, dies in C# zu tun? Es klingt genau nach Art von Problem, für das XSLT entwickelt wurde. –

+0

Das Dokument enthält drei XSLT-Aufrufe für divs, die im Dokument eingerichtet wurden. Es sei denn, ich könnte eine externe HTML-Datei über XSLT laden, anstatt sie zu kopieren, und sie dann ändern. – wonea

+0

Ich habe das HTML-Dokument durchgelaufen, und es aufgeräumt, so dass es perfekt funktioniert, und es in ein XML-Tool wie jsXe ohne Fehler lädt – wonea

Antwort

28

Wenn es tatsächlich gültiges XML ist und leicht in den Speicher passt, würde ich jedes Mal LINQ to XML (XDocument, XElement etc) wählen. Es ist bei weitem die schönste XML-API, die ich verwendet habe. Es ist einfach, Abfragen zu erstellen und auch neue Elemente zu erstellen.

Sie können XPath verwenden, wo dies angebracht ist, oder die integrierten Achsenmethoden (Elements(), Descendants(), Attributes() usw.). Wenn Sie uns wissen lassen könnten, mit welchen spezifischen Problemen Sie Schwierigkeiten haben, würde ich mich freuen, herauszufinden, wie Sie diese in LINQ to XML ausdrücken können.

Wenn dies andererseits HTML ist, das ist nicht gültige XML, haben Sie eine viel härtere Zeit - weil XML-APIs im Allgemeinen erwarten, mit gültigen XML-Dokumenten zu arbeiten. Sie könnten natürlich zuerst HTMLTidy verwenden, aber das kann unerwünschte Effekte haben.

Für Ihr konkretes Beispiel:

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 für große Gerechtigkeit. – annakata

+1

Ich stimme herzlich zu! Ich hatte ein paar ältere Apps, die ich mit Parsing und dergleichen auf die harte Tour machen musste und L2X macht es so viel einfacher und leistungsfähiger. –

+1

Jon, Sie können HtmlAgilityPack sehr nützlich finden, anstatt sich um gültige XML Gedanken zu machen, können Sie ähnliche APIs wie XDocument für schmutziges, reales HTML verwenden. –

0

Starten Sie einfach durch die Dokumentation des Xml namespace on the MSDN lesen. Dann, wenn Sie spezifischere Fragen haben, stellen Sie sie hier ...

1

Wenn Sie kleinere Dokumente haben, die in Computerspeicher passen, können Sie XmlDocument verwenden. Andernfalls können Sie XmlReader verwenden, um das Dokument zu durchlaufen.

XmlReader verwenden Sie können die Elemente herausfinden Typ mit:

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

Sind die Dokumente, die Sie relativ klein verarbeiten? Wenn dies der Fall ist, können Sie sie mithilfe eines XmlDocument-Objekts in den Speicher laden, ändern und die Änderungen zurückschreiben.

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

Abhängig von der Struktur der Eingabe-XML könnte dies Ihren Parsing-Code ein wenig einfacher machen.

0

Ein ziemlich einfacher Ansatz wäre, ein neues XmlDocument zu erstellen, dann verwenden Sie die Load() Methode, um es zu füllen. Sobald Sie das Dokument haben, können Sie CreateNavigator() verwenden, um ein XPathNavigator Objekt zu erhalten, mit dem Sie Elemente im Dokument suchen und ändern können. Schließlich können Sie die Save() Methode auf dem XmlDocument verwenden, um das geänderte Dokument wieder zu schreiben.

1

Für die Aufgabe in der Hand - (lesen doc bestehenden, Schreiben und Ändern in formalisierter Weise) I mit XPathDocument Laufe durch ein XslCompiledTransform gehen würde.

Wo Sie nicht formalisieren können, keine bereits vorhandenen Dokumente haben oder allgemein mehr adaptive Logik benötigen, würde ich mit LINQ und XDocument gehen, wie Skeet sagt.

Grundsätzlich, wenn die Aufgabe Transformation ist dann XSLT, wenn die Aufgabe Manipulation ist dann LINQ.

1

Mein Lieblingswerkzeug für diese Art der Sache ist HtmlAgilityPack. Ich verwende es, um komplexe HTML-Dokumente in LINQ-abfragbare Sammlungen zu analysieren. Es ist ein äußerst nützliches Werkzeug zum Abfragen und Analysieren von HTML (welches oft kein gültiges XML ist).

Für Ihr Problem, würde sich der Code wie:

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

Hier ist ein Werkzeug, das ich schrieb ein IAR EWARM Projekt (EWP) Datei zu ändern, das Hinzufügen eines Linkers an das Projekt definieren. Von der Befehlszeile aus führen Sie es mit 2 Argumenten, den Eingabe- und Ausgabedateinamen (* .ewp), aus.

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

Die Struktur des XML sieht wie folgt aus

<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> 
Verwandte Themen