Entwickler-Ecke
IO, XML und Registry - XML Datei einlesen
Skywalker19 - Mo 21.11.05 10:49
Titel: XML Datei einlesen
möchte eine XML-Datei einlesen, die folgende Struktur hat:
Quelltext
1: 2: 3: 4: 5:
| <xml version="1.0" encoding="utf-8"?> <settings> <text1 xmlns="gggg" /> <text2 xmlns="hhhh" /> </settings> |
mein bisheriger Code dazu ist der hier:
C#-Quelltext
1: 2: 3: 4:
| XmlDocument settings = new XmlDocument(); settings.LoadXml("settings.xml"); XmlNode node = settings.SelectSingleNode("//settings/text1"); textBox1.Text = node.InnerText; |
aber in Zeile 3 bekomm ich eine System.XML.Exception ausgewurfen :(
Was mach ich falsch?
Moderiert von
Christian S.: C#-und Code-Tags hinzugefügtModeriert von
Christian S.: Topic aus C# - Die Sprache verschoben am Mo 21.11.2005 um 11:23
Delete - Mo 21.11.05 12:38
Titel: Re: XML Datei einlesen
Skywalker19 hat folgendes geschrieben: |
| Was mach ich falsch? |
Einiges.
- Grund für deine Exception ist die Verwendung von LoadXml. Damit lädst du direkt XML-Code und nicht den Inhalt deiner XML-Datei. Du brauchst also Load.
- Wenn du das änderst, bekommst du die nächste Exception. Grund: Du hast in der ersten Zeile der XML-Datei das Fragezeichen vorn, nach dem öffnenden Tag, vergessen.
- Wenn du das änderst, erhältst du die dritte Exception, weil deine XML-Datei das xmlns-Attribut für einen fremden Namespace benutzt. "SelectSingleNode" findet daher nichts, node ist null.
- Erst wenn du das Problem löst, siehst du den Inhalt des Knotens im Eingabefeld. Das heißt, eigentlich siehst du nichts, denn der Knoten hat ja keinen Inhalt. ;)
Skywalker19 - Mo 21.11.05 16:08
danke erstmal!
die ersten beiden Fehler sind behoben aber was muss ich nun genau beim dritten Problem machen?
Delete - Mo 21.11.05 16:41
.NET Framework SDK: XmlNamespaceManager.
Skywalker19 - Mo 21.11.05 20:32
ja also das xmlns hat es ja standartmäßig beim speichern der Datei hinzugefügt.
aber was muss ich da jetzt genau beim Laden angeben?
hab bisher:
XmlNamespaceManager nsmanager = new XmlNamespaceManager(settings.NameTable);
und dann muss ich doch irgendwas mit
nsmanager.AddNamespace
hinzufügen oder ?
blick da noch nicht ganz durch, hab leider auch noch keine Ahnung von XML.
Delete - Mo 21.11.05 23:05
Du bist aber auf dem richtigen Weg. Du musst dem Befehl
SelectSingleNode sagen, dass es sich bei dem gesuchten Knoten um einen mit einem anderen Namespace handelt. Das machst du bei XPath, indem du ein Präfix voranstellst. Dessen Namen kannst du dir auch selbst ausdenken:
C#-Quelltext
1:
| nsmanager.AddNamespace("bla", "gggg"); |
Beim Einlesen stellst du dieses Präfix
bla: nun vor den eigentlichen Namen des Knotens, und du musst auch den
XmlNamespaceManager verwenden:
C#-Quelltext
1:
| XmlNode node = settings.SelectSingleNode("//settings/bla:text1", nsmanager); |
Und das war´s. Wenn du dem Knoten jetzt noch Inhalt gibst
Quelltext
1:
| <text1 xmlns="gggg">Hallo, Welt!</text1> |
dann siehst du im Eingabefeld auch was.
Übrigens, wenn du vorhast, Einstellungen deines Programms in einer XML-Datei zu speichern, dann solltest du mal einen Blick auf die Serialization/Deserialization werfen. Das ist nämlich richtig genial. Du erstellst eine Klasse mit den Eigenschaften, die dein Programm benötigt (Höhe, Breite, Position, was weiß ich ...), und dank
XmlSerializer erzeugt CSharp daraus automatisch eine XML-Datei. Und umgekehrt: Ein Befehl liest die XML-Datei wieder ein, und du hast Zugriff auf die gespeicherten Eigenschaften.
Skywalker19 - Di 22.11.05 08:56
gut danke funktionert, aber eins noch:
das "gggg" ist ja schon Text aus meiner Textbox, den es da speichert. Gibt es keine Möglichkeit darauf zuzugreifen? Sonst muss ich wieder meine Speicherfunktion umschreiben...
Skywalker19 - Di 22.11.05 09:03
oder besser gefragt:
<text1 xmlns="gggg">Hallo, Welt!</text1>
Wie kann ich in dieser Zeile den Text (Hallo Welt) beim speichern der XML anlegen?
Delete - Di 22.11.05 10:41
Das habe ich mir gedacht, ;).
xmlns ist ein Attributname, der grundsätzlich für Namespace-Deklarationen verwendet wird. Aus dem Grund scheitert dann auch deine Leseroutine. Es gibt drei Varianten, einen Text richtig in einem XML-Knoten zu speichern.
1. Entweder als Attribut:
C#-Quelltext
1: 2: 3: 4:
| XmlElement node = xmldoc.CreateElement("text1"); node.SetAttribute("Text", textBox1.Text);
|
2. Als Knoteninhalt:
C#-Quelltext
1: 2: 3: 4:
| XmlElement node = xmldoc.CreateElement("text1"); node.InnerText = textBox1.Text;
|
3. Die absolut beste Variante ist aber die Verwendung einer <![CDATA[ ]]>-Sektion, weil du damit sicherstellst, dass auch Sonderzeichen, die normalerweise in XML nichts zu suchen haben (&, <, >, usw.) gespeichert werden. In dem Fall geht es aber grundsätzlich nur als Inhalt des Knotens und
nicht als Attribut:
C#-Quelltext
1: 2: 3: 4: 5:
| XmlElement node = xmldoc.CreateElement("text1"); XmlCDataSection content = xmldoc.CreateCDataSection(textBox1.Text); node.AppendChild(content);
|
Skywalker19 - Di 22.11.05 11:27
besten Dank! jetzt funzt alles! *freu* ^^
Robert_G - Di 22.11.05 12:35
hmm...
Geht auch
ganz anders. ;)
- Du lässt dir ein Schema (bzw 3 durch diese kranken Extraschemata) anlegen:
Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19:
| <?xml version="1.0" encoding="utf-8"?> <xs:schema elementFormDefault="qualified" targetNamespace="SkywalkersSchema.xsd" xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:import namespace="gggg" schemaLocation="SkywalkersSchema.gggg.xsd" /> <xs:import namespace="hhhh" schemaLocation="SkywalkersSchema.hhhh.xsd"/> <xs:element name="settings"> <xs:complexType> <xs:sequence> <xs:element xmlns:q1="gggg" ref="q1:text1" /> <xs:element xmlns:q2="hhhh" ref="q2:text2" /> </xs:sequence> </xs:complexType> </xs:element> </xs:schema> |
Quelltext
1: 2: 3: 4: 5: 6: 7:
| <?xml version="1.0" encoding="utf-8"?> <xs:schema xmlns:tns="gggg" elementFormDefault="qualified" targetNamespace="gggg" xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:element name="text1" type="xs:string" /> </xs:schema> |
Quelltext
1: 2: 3: 4: 5: 6: 7:
| <?xml version="1.0" encoding="utf-8"?> <xs:schema xmlns:tns="hhhh" elementFormDefault="qualified" targetNamespace="hhhh" xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:element name="text2" type="xs:string"/> </xs:schema> |
- Aus diesem Schema kannst du dir Klassen anlegen lassen (hier ist es nur eine):
Quelltext
1:
| xsd SkywalkersSchema.xsd /l:C# /n:DeinNamespace /c |
- /l ist die Sprache
- /n ist der Name space der generierten Klassen
- /c sagt du willst classes anstatt einem DataSet
- Weil Xsd so nett war und das ganz als partial class angelegt hat, können wir diese nun noch etwas ausschmücken:
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46:
| [assembly: System.Runtime.CompilerServices.InternalsVisibleTo("System.Xml")] namespace DeinNamespace { public partial class settings {
string fileName;
protected string FileName { get { return fileName; } set { fileName = value; } }
public static settings Load(string fileName) { using (XmlReader reader = new XmlTextReader(fileName)) { XmlSerializer serializer = new XmlSerializer(typeof(settings)); settings settings = serializer.Deserialize(reader) as settings; settings.FileName = fileName; return settings; } }
internal settings() { } public void Save(string fileName) { using (XmlWriter writer = new XmlTextWriter(fileName, Encoding.UTF8)) { XmlSerializer serializer = new XmlSerializer(GetType()); serializer.Serialize(writer, this); } }
public void Save() { if (!string.IsNullOrEmpty(FileName)) Save(FileName); else throw new NullReferenceException("mööp"); } } } |
Hier noch ein bleistift, wie man es benutzt:
C#-Quelltext
1: 2: 3: 4: 5: 6:
| settings settings = settings.Load("Settings.xml");
settings.text1 += "a(&, <, >, usw.)"; settings.text2 += "b(&, <, >, usw.)";
settings.Save(); |
MathiasSimmack hat folgendes geschrieben: |
3. Die absolut beste Variante ist aber die Verwendung einer <![CDATA[ ]]>-Sektion, weil du damit sicherstellst, dass auch Sonderzeichen, die normalerweise in XML nichts zu suchen haben (&, <, >, usw.) gespeichert werden. In dem Fall geht es aber grundsätzlich nur als Inhalt des Knotens und nicht als Attribut:
C#-Quelltext 1: 2: 3: 4:
| XmlElement node = xmldoc.CreateElement("text1"); XmlCDataSection content = xmldoc.CreateCDataSection(textBox1.Text); node.AppendChild(content); | |
Nope, solche Sache lasse ich lieber vom Framework entscheiden. Beim Beispiel von oben wird diese XML erzeugt: ;)
Quelltext
1: 2: 3: 4: 5: 6: 7:
| <?xml version="1.0" encoding="utf-8"?> <settings xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="SkywalkersSchema.xsd"> <text1 xmlns="gggg">a(&, <, >, usw.)</text1> <text2 xmlns="hhhh">b(&, <, >, usw.)</text2> </settings> |
Das Framework bleibt up-to-date was die XML Syntax betrifft. Wenn ich sowas fest in den Code einbaue läuft es vllt nächstes Jahr nichtmehr. Außerdem müsste ich es selbst in den Code einbauen... :mrgreen:
Moderiert von
Christian S.: Code-Tags repariert
Delete - Mi 23.11.05 07:28
Ist das nicht etwas Overkill? ;) Wenn ich das richtig sehe, dann war es eh bloß ein Versehen des Beitragserstellers, dass er xmlns benutzt hat.
Skywalker19 - Mi 23.11.05 08:43
glaub auch das is bissel aufwendig in der Form und richtig, war auch eher ein Versehen ^^
Robert_G - Mi 23.11.05 10:32
Oh ich dachte das war nur ein gekürzter Bleistift...
Normal halte ich autogenerierte Container und Serialisierung als nette Möglichkeit realtiv flexibel zu Änderungen in den Daten zu bleiben. ;)
ven000m - Mi 14.05.08 15:23
Hallo,
ich habe genau das gleiche Problem wie Skywalker.
Allerdings funktioniert es bei mir noch nicht: Folgendes ist bei mir der Fall, ich erhalte einen XML Stream von einem Webservice zurück.
Davon möchte ich bestimmte Knoten an bestimmte Steuerelemente meines Forms zurückschreiben, ich suche schon den ganzen Tag nach diesem Thread und wäre super dankbar wenn ich damit heute auch abschließen könnte und weitermachen könnte.
Da ich nicht soo versiert bin, wären direkte Code-Beispiele echt toll!
Ich interessiere mich für zwei Knoten:
// text und //adBKMURL
Der Namespace meines XML Streams lautet wie folgt:
xmlns="urn:Corticon" xmlns:xsi="
http://.... schema-instance"
Was kommt jetzt anstatt von bla dort beim NamespaceManager bzw. beim xPath rein?
Hier ist der Code:
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37:
| try{
Corticon.CcServerMessagingAxisService myWebHandler = new Corticon.CcServerMessagingAxisService();
MessageBox.Show(request); string response=myWebHandler.executeRPC(request); MessageBox.Show(response);
XmlDocument myXMLDoc = new XmlDocument(); myXMLDoc.Load(response);
XmlNamespaceManager nsmanager = new XmlNamespaceManager(myXMLDoc.NameTable); nsmanager.AddNamespace("bla","ggg");
XmlNodeList nodes = myXMLDoc.SelectNodes("/CorticonResponse/Messages/Message/bla:text", nsmanager); int i = 1;
foreach (XmlNode myNode in nodes) { ResultBox.AppendText(i++ + "." + myNode.InnerText); }
XmlNode bkmNode = myXMLDoc.SelectSingleNode("/CorticonResponse/WorkDocuments/OEM/bla:adBKMURL", nsmanager); BKMBox.Text = bkmNode.InnerText;
} catch (Exception ex) { ResultBox.Text = ex.StackTrace; } |
Moderiert von
Christian S.: Code- durch C#-Tags ersetzt
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2026 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!