Autor Beitrag
Skywalker19
Hält's aus hier
Beiträge: 12



BeitragVerfasst: Mo 21.11.05 11:49 
möchte eine XML-Datei einlesen, die folgende Struktur hat:

ausblenden 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:

ausblenden 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 user profile iconChristian S.: C#-und Code-Tags hinzugefügt
Moderiert von user profile iconChristian S.: Topic aus C# - Die Sprache verschoben am Mo 21.11.2005 um 11:23
MathiasSimmack
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Mo 21.11.05 13:38 
user profile iconSkywalker19 hat folgendes geschrieben:
Was mach ich falsch?

Einiges.
  1. 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.
  2. 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.
  3. 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.
  4. 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 Threadstarter
Hält's aus hier
Beiträge: 12



BeitragVerfasst: Mo 21.11.05 17:08 
danke erstmal!
die ersten beiden Fehler sind behoben aber was muss ich nun genau beim dritten Problem machen?
MathiasSimmack
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Mo 21.11.05 17:41 
.NET Framework SDK: XmlNamespaceManager.
Skywalker19 Threadstarter
Hält's aus hier
Beiträge: 12



BeitragVerfasst: Mo 21.11.05 21: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.
MathiasSimmack
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Di 22.11.05 00: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:
ausblenden 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:
ausblenden C#-Quelltext
1:
XmlNode node = settings.SelectSingleNode("//settings/bla:text1", nsmanager);					

Und das war´s. Wenn du dem Knoten jetzt noch Inhalt gibst
ausblenden 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 Threadstarter
Hält's aus hier
Beiträge: 12



BeitragVerfasst: Di 22.11.05 09: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 Threadstarter
Hält's aus hier
Beiträge: 12



BeitragVerfasst: Di 22.11.05 10: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?
MathiasSimmack
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Di 22.11.05 11: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:
ausblenden C#-Quelltext
1:
2:
3:
4:
XmlElement node = xmldoc.CreateElement("text1");
node.SetAttribute("Text", textBox1.Text);

// Ergebnis: <text1 Text="Hallo, Welt!"/>


2. Als Knoteninhalt:
ausblenden C#-Quelltext
1:
2:
3:
4:
XmlElement node = xmldoc.CreateElement("text1");
node.InnerText  = textBox1.Text;

// Ergebnis: <text1>Hallo, Welt!</text1>


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:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
XmlElement node         = xmldoc.CreateElement("text1");
XmlCDataSection content = xmldoc.CreateCDataSection(textBox1.Text);
node.AppendChild(content);

// Ergebnis: <text1><![CDATA[Hallo, & Welt! <bla>]]></text1>
Skywalker19 Threadstarter
Hält's aus hier
Beiträge: 12



BeitragVerfasst: Di 22.11.05 12:27 
besten Dank! jetzt funzt alles! *freu* ^^
Robert_G
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 416


Delphi32 (D2005 PE); Chrome/C# (VS2003 E/A, VS2005)
BeitragVerfasst: Di 22.11.05 13:35 
hmm...
Geht auch ganz anders. ;)
  • Du lässt dir ein Schema (bzw 3 durch diese kranken Extraschemata) anlegen:
    ausblenden 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>


    ausblenden 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>


    ausblenden 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):
    ausblenden 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:
    ausblenden volle Höhe 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:
    //dadurch sieht der Serilizer den internal constructor
    [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() { }// den sieht nur der Serializer, nicht deine App :-)

        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:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
settings settings = settings.Load("Settings.xml");

settings.text1 += "a(&, <, >, usw.)";
settings.text2 += "b(&, <, >, usw.)";

settings.Save();




user profile iconMathiasSimmack 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:
ausblenden C#-Quelltext
1:
2:
3:
4:
XmlElement node         = xmldoc.CreateElement("text1");
XmlCDataSection content = xmldoc.CreateCDataSection(textBox1.Text);
node.AppendChild(content);
// Ergebnis: <text1><![CDATA[Hallo, & Welt! <bla>]]></text1>
Nope, solche Sache lasse ich lieber vom Framework entscheiden. Beim Beispiel von oben wird diese XML erzeugt: ;)
ausblenden 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 user profile iconChristian S.: Code-Tags repariert
MathiasSimmack
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Mi 23.11.05 08: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 Threadstarter
Hält's aus hier
Beiträge: 12



BeitragVerfasst: Mi 23.11.05 09:43 
glaub auch das is bissel aufwendig in der Form und richtig, war auch eher ein Versehen ^^
Robert_G
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 416


Delphi32 (D2005 PE); Chrome/C# (VS2003 E/A, VS2005)
BeitragVerfasst: Mi 23.11.05 11: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
Hält's aus hier
Beiträge: 1



BeitragVerfasst: Mi 14.05.08 16: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=".... schema-instance"

Was kommt jetzt anstatt von bla dort beim NamespaceManager bzw. beim xPath rein?

Hier ist der Code:

ausblenden volle Höhe 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);
               // /CorticonResponse/Messages/Message/text                           

              int i = 1;

              foreach (XmlNode myNode in nodes)
              {
                  ResultBox.AppendText(i++ + "." + myNode.InnerText);
              }

              /*Zweiter Knoten adBKMURL auslesen:*/

              XmlNode bkmNode = myXMLDoc.SelectSingleNode("/CorticonResponse/WorkDocuments/OEM/bla:adBKMURL", nsmanager);
              // /CorticonResponse/WorkDocuments/OEM/adBKMURL
             
              BKMBox.Text = bkmNode.InnerText; //hier ist der fehler
              // BKMBox.Text = myXMLDoc.InnerText;
            

          }
          catch (Exception ex) 
          { ResultBox.Text = ex.StackTrace; }


Moderiert von user profile iconChristian S.: Code- durch C#-Tags ersetzt