Autor Beitrag
WalterZ
Hält's aus hier
Beiträge: 11



BeitragVerfasst: Mo 20.07.09 15:54 
Hallo Leute,

ich habe folgende XML-Datei(Auszug):



ausblenden XML-Daten
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:
<?xml version="1.0" standalone="yes"?>
<NewDataSet xmlns="http://tempuri.org/Telefonliste.xsd">
  <Adressen>
    <Name>Marx</Name>
    <Vorname>Monika</Vorname>
    <Ort>Wolfsburg</Ort>
    <TelNr>
  <erste>4711</erste>
  <zweite>4712</zweite>
   </TelNr>
    <Bild>sm.jpg</Bild>
  </Adressen>
  <Adressen>
    <Name>Habe</Name>
    <Vorname>Hans</Vorname>
    <Ort>Hannover</Ort>
    <TelNr>
    <erste>60505</erste>
  <zweite>60506</zweite>
    </TelNr>
    <Bild>sm2.jpg</Bild>
  </Adressen>
 
  
 </NewDataSet>


und dazu folgenden c#-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:
38:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Xml;



namespace WindowsFormsApplication15
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.Load("telefonliste.xml");
  
           XmlNodeList tables = xmlDoc.GetElementsByTagName("Adressen");
                     
            foreach (XmlNode table in tables)
           {
                      MessageBox.Show(table.InnerText);
               if (table.HasChildNodes)
                   foreach (XmlNode tablechild in table.ChildNodes)
                    {
                    MessageBox.Show(table.ChildNodes[0].InnerText);


}}}


Meine Frage:
Wieso werden bei der Asuführung die einzelnen Knoten-Texte mehrfach (dopplet) und einmal auch verkettet angezeigt?

Gruß
Walter

Moderiert von user profile iconKha: XML-Tags hinzugefügt
Moderiert von user profile iconKha: C#-Tags hinzugefügt
Kha
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: Mo 20.07.09 17:05 
:welcome:

Du benutzt tablechild ja gar nicht, also wird für jeden Knoten unter <Adresse> immer das gleiche ausgegeben, nämlich table.ChildNodes[0], der Inhalt von <Name>. Und der verkettete Inhalt entsteht durch table.InnerText.
Am besten schaust du es dir mal im Debugger an, dort sollte es klarer werden.

_________________
>λ=
WalterZ Threadstarter
Hält's aus hier
Beiträge: 11



BeitragVerfasst: Mo 20.07.09 20:37 
Danke für die Antwort, hilft schon weiter.

Nun habe ich aber ein neues Problem:

Ich habe die Abfrage um eine Ebene erweitert und frage außerdem nicht nach InnerText, sondern nach Namen.
In den Fällen, in denen ich in der XML-Datei keine dritte Ebene habe, wird in der MessageBox "#text" ausgegeben,
ansonsten funktionierts. Das bedeutet doch, dass meine if-Abfrage nicht korrekt funktioniert, oder ? Was ist falsch?

Gruß
Walter

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
private void button1_Click(object sender, EventArgs e)
        {

            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.Load("telefonliste.xml");
            XmlNodeList tables = xmlDoc.GetElementsByTagName("Adressen");

            foreach (XmlNode table in tables)
            {
              MessageBox.Show(table.InnerText);
                if (table.HasChildNodes)
                foreach (XmlNode tablechild in table.ChildNodes)
                 {
                   MessageBox.Show(tablechild.Name);
                     if (tablechild.HasChildNodes)
                     foreach (XmlNode table2child in tablechild.ChildNodes)
                      {
                        MessageBox.Show(table2child.Name);
}}}}


Moderiert von user profile iconChristian S.: C#-Tags hinzugefügt
WalterZ Threadstarter
Hält's aus hier
Beiträge: 11



BeitragVerfasst: Mo 20.07.09 20:42 
Und gleich noch eine Feststellung: Wenn ich wieder nach InnerText abfrage, kommt auch wieder die doppelte Anzeige in der MessageBox.

Walter
Kha
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: Mo 20.07.09 22:02 
user profile iconWalterZ hat folgendes geschrieben Zum zitierten Posting springen:
In den Fällen, in denen ich in der XML-Datei keine dritte Ebene habe, wird in der MessageBox "#text" ausgegeben,
ansonsten funktionierts.
Das Problem: <Name> besitzt ein Child, nämlich eben den Text "Marx". Aber was hast du eigentlich vor? Du scheinst die Datei "dynamisch erkunden" zu wollen, normalerweise sollte die Struktur aber wohl statisch sein und das Ganze eher so aussehen:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
foreach (XmlNode node in xmlDoc) {
  var adress = new Adress();
  adress.Name = node["Name"].Value;
  foreach (XmlNode phoneNode in node["TelNr"])
    adress.PhoneNrs.Add(phoneNode.Value);
  ...


Oder natürlich von der Xml-Serialization alles auf einen Schlag erledigen lassen ;) ...

_________________
>λ=
WalterZ Threadstarter
Hält's aus hier
Beiträge: 11



BeitragVerfasst: Mo 20.07.09 22:40 
Es ist richtig: Ich muss XML-Dateien abfragen, die von Dritten kommen und sehr unterschiedliche Strukturen aufweisen.
Diese Dateien enthalten unterschiedliche Anzahlen von Tabellen und innerhalb der Tabellen unterschiedliche Anzahl von Spalten und Spaltentexte. Ich muss aus den XML-Daten Tabellen erzeugen, deren Name und Spalteninhalt ich aus den XML-Daten entnehme. Dann kann ich diese Tabellen mit *.csv, *.dat, *.txt- Dateien füllen, die ebenfalls mitgeliefert werden, allerdings als reine Textdateien. Wie gesagt: Nur die URL ist in den XML-Daten hinterlegt, ansonsten handelt es sich um reine Textdateien ohne Spaltenüberschriften. Diese und die Namen der Tabellen muss ich der XML-Datei variabel entnehmen.

Walter
Kha
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: Mo 20.07.09 23:11 
Ok, Tabellen und Spalten. Aber was soll dann mit tiefer verschachtelten Elementen wie "TelNr" (oder noch tiefer) geschehen?

PS: Ich würde auf jeden Fall auf System.Xml.Linq.XElement umsteigen. Dort gäbe es genau das, was du brauchst: HasElements.

_________________
>λ=
WalterZ Threadstarter
Hält's aus hier
Beiträge: 11



BeitragVerfasst: Di 21.07.09 04:44 
Die Tabellen und Spalten liegen teilweise so tief. Ich werde der Empfehlung folgen und auf LINQ umsteigen. Hier habe ich allerdings noch keine Erfahrung.

Walter
danielf
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 1012
Erhaltene Danke: 24

Windows XP
C#, Visual Studio
BeitragVerfasst: Mi 22.07.09 08:47 
Hallo,

dann kannst du ja gern hier wieder fragen :)

Wollte dir auch raten auf Linq umzusteigen. Aber ist ja bereits geschehen. Werden den Thread mal mitverfolgen.

Gruß Daniel
WalterZ Threadstarter
Hält's aus hier
Beiträge: 11



BeitragVerfasst: Mi 12.08.09 22:03 
Hallo,

bei meinen ersten Versuchen mit XElement stellt sich zunächst folgende Frage:

Bei folgendem Code zeigt die MessageBox die XElemente-Values:

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
private void button1_Click(object sender, EventArgs e)
        {
                  XElement fromFile = XElement.Load("Telefonliste.xml");
                    foreach (XElement xelement in xmlDatei.Elements())
                 
                    MessageBox.Show(xelement.Value);
                }



Bei folgender Änderung des Codes bekomme ich an der MessageBox keine Ausgabe mehr: Warum ?

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
private void button1_Click(object sender, EventArgs e)
        {
                  XElement fromFile = XElement.Load("Telefonliste.xml");
                    foreach (XElement xelement in xmlDatei.Elements())
   if (xelement.Name == "erste")
                              
        

            MessageBox.Show(xelement.Value);
                }


Moderiert von user profile iconKha: C#-Tags hinzugefügt
Kha
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: Mi 12.08.09 23:34 
Hallo mal wieder :wave: .

Mit Elements fragst du nur die erste Ebene ab, also die zwei <Adressen>-Tags. Das Ergebnis der Methode wirst du wahrscheinlich an eine rekursive Methode übergeben müssen, aber für Genaueres bräuchten wir erst genauere Informationen darüber, was nun mit der Datei eigentlich geschehen soll.

_________________
>λ=
WalterZ Threadstarter
Hält's aus hier
Beiträge: 11



BeitragVerfasst: Do 13.08.09 02:46 
Damit man erkennt, was ich will, habe ich die Abfrage leicht verändert:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
private void button1_Click(object sender, EventArgs e)
        {
                  XElement fromFile = XElement.Load("Telefonliste.xml");
                    foreach (XElement xelement in xmlDatei.Elements())
   if (xelement.Name == "TelNr")
                              
        

        //    MessageBox.Show(xelement.Value);



hier mein Ziel:
Wenn das Tag Telefonnummer erkannt wird, dann lege eine DataTable an mit den Spaltenüberschriften "erste" und "zweite", vielleicht auch noch "dritte", "vierte"..... usw.


}


I

Moderiert von user profile iconKha: C#-Tags hinzugefügt
Kha
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: Do 13.08.09 19:02 
Alle <TelNr>-Tags in beliebiger Tiefe bekommst du über XElement.Descendants.

PS: Benutze doch bitte [cs]-Tags, um deinen Code lesbar zu machen.

_________________
>λ=
WalterZ Threadstarter
Hält's aus hier
Beiträge: 11



BeitragVerfasst: So 16.08.09 16:33 
Hallo, mit nachfolgendem Code bekomme ich das gewünschte Ergebnis:

foreach (var desc in fromFile.Descendants("TelNr").Elements() )
{listBox1.Items.Add (desc.Value);}

Nun aber gleich meine nächsten Fragen:
a)Wie kann ich statt der ListBox eine DataTable füllen ?
b)Kann ich das Ergebnis der ListBox vielleicht an die DataTable übergeben ?


Gruß
Walter
WalterZ Threadstarter
Hält's aus hier
Beiträge: 11



BeitragVerfasst: So 23.08.09 20:30 
Hallo, Leute

ich habe den Code nochmals verändert:

private void button1_Click(object sender, EventArgs e)

var fromFile = XElement.Load("Telefonliste.xml");

foreach (var desc in from item in fromFile.Descendants("TelNr") select item)
{
listBox1.Items.Add (desc.Name );

MessageBox.Show(desc.Element("erste" ).Value);
MessageBox.Show(desc.Element("zweite").Value);

foreach (var c in desc.Descendants("erste") )
{
MessageBox.Show(c.Value);
}
}

Die Ergebnisse werden zu Testzwecken sowohl in der ListBox als auch in der MessageBox gezeigt. Bei dem Ergebnis handelt es sich jetzt wohl um eine typisierte Liste.
Erneut meine Frage: Wie bekomme ich eine typisierte Liste in a) ein Dataset b) eine DataTabel c) eine DataGridView ??

Gruß
Walter