Entwickler-Ecke

IO, XML und Registry - Wert aus xml vergleichen


ninJa_neon - Sa 26.06.10 18:47
Titel: Wert aus xml vergleichen
Hallo,

ich habe in c# ein xml-File geschrieben, dass die Daten eines Widerstandes speichert:


XML-Daten
1:
2:
3:
4:
5:
<Widerstand>
    <ZAHL>47</ZAHL>
    <WERT>47R</WERT>
    <BEST>423203 -62</BEST>
  </Widerstand>


usw.

In meinem Programm gibt der User einen Wert ein, z.B. 50, dieser Wert soll dann mit allen Zahlen (<ZAHL>) verglichen werden. Wenn das Programm dann den passenden Widerstand mit dem nächsten Wert gefunden hat möchte ich <Wert> und <Best> in einer listview ausgeben. Habe gerade erst mit xml angefangen und hoffe, dass mir jemand helfen kann.

mfg

Moderiert von user profile iconChristian S.: XML-Tags hinzugefügt


danielf - Sa 26.06.10 19:50

Hallo und :welcome:,

für Xml gibt es ein sprachenunabhängige Abfragesprache namens XPath. Dies kannst du verwenden um deinen Entsprechenden Widerstand zu finden.

Die .NET Implementierung für Xml findest du als XmlDocument (alt) und XDocument (Linq). Verwende XDocument, das ist schneller und konfortabler.

Um eine Xml-Document damit einzulesen genügt:

C#-Quelltext
1:
XDocument doc = XDocument.Load("deine.xml");                    


Um ein Element anhand eines XPath-Ausdruck zu finden musst du den Namespace using System.Xml.XPath; einbinden. Dann gibt es einige Erweiterungsmethoden wie zum Beispiel: XPathSelectElement. Mit dieser kannst du mit einem XPath Ausdruck ein Element auswählen. XPath ist zu umfangreich dass ich es dir hier erklären möchte.
Deshalb verweise ich hier auf folgende Links:
http://de.wikipedia.org/wiki/XPath
http://de.selfhtml.org/xml/darstellung/xpathsyntax.htm
http://www.w3schools.com/xpath/default.asp

Der Befehl könnte dann so aussehen:

C#-Quelltext
1:
doc.XPathSelectElement("/Widerstand[ZAHL='47']");                    


Viel Erfolg & Gruß,

Moderiert von user profile iconChristian S.: C#-Tag repariert


ninJa_neon - So 27.06.10 16:02

Ich habe versucht das Problem mit folgendem Code zu lösen:


C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
int wert = Convert.ToInt32(txtBox_R_Wert.Text);
            string strwert = Convert.ToString(wert);
            string listWert, listBest;

            var doc = new XPathDocument(@"F:\INFORMATIK\Csharp\PROJEKT_2010\XML\W6_MFR_0p1.xml");
            foreach (XPathNavigator navigator in doc.CreateNavigator().Select("/W6_Metallschichtwiderstand_0p1/Widerstand[@id=\"47\"]/child"))
            {
                listWert=Convert.ToString(navigator.InnerXml + navigator.GetAttribute("WERT"""));
                listBest=Convert.ToString(navigator.InnerXml + navigator.GetAttribute("BEST"""));
            }


...und die xml abgeändert:


XML-Daten
1:
2:
3:
4:
<Widerstand id="47">
    <child WERT="47R"></child>
    <child BEST="423203 -62"></child>
  </Widerstand>


Irgendwie funktioniert das ganze aber nicht und ich habe keine Ahnung warum :(

danke erstmal für die Hilfe!

Moderiert von user profile iconChristian S.: C#-Tags hinzugefügt
Moderiert von user profile iconChristian S.: XML-Tags hinzugefügt


Kha - So 27.06.10 17:01

Definiere bitte "funktioniert nicht".

Wenn XPath dir nicht sowieso schon bekannt ist, gibt es zumindest bei diesem Problem eigentlich keinen Grund, dich zusätzlich zur restlichen XElement-API damit beschäftigen zu müssen:

C#-Quelltext
1:
2:
3:
4:
5:
foreach (XElement widerstand in doc.Elements("Widerstand"))
  if ((int)widerstand.Element("ZAHL") == 42) {
    ...
    break;
  }

Ich beziehe mich auf deine erste XML-Struktur, denn "ZAHL" kann zwar ruhig ein Attribut werden, aber insgesamt war die eindeutig hübscher ;) .


ninJa_neon - So 27.06.10 17:39

Letzte Frage: Wie bekomme ich jetzt noch, dass er beim Widerstand auch die dazugehörige Bestellnummer und Wert ausgibt?

mfg


Kha - So 27.06.10 22:19

Du beziehst dich auf meinen Vorschlag? Wenn ja, läuft das eigentlich ganz analog zum ZAHL-Element, das solltest du jetzt eigentlich übertragen können.

PS: Die fortgeschrittene Version, für die Zukunft ;) , wäre

C#-Quelltext
1:
XElement widerstand = root.Elements("Widerstand").Single(e => (int)e.Element("ZAHL") == 42);                    

Da ich normalerweise über XElement.Load gehe, soll root hier ein XElement sein. Deswegen ist auch mein Code im vorigen Beitrag nicht ganz korrekt: Ist doc ein XDocument, muss die Wurzel wie jedes andere Element explizit mit einbezogen werden (wie im XPath). Für die meisten Aufgaben ist XDocument aber eben gar nicht nötig.


danielf - So 27.06.10 22:21

Also das Foreach benötigt man nicht. Xpath bietet ja bereits die Möglichkeit (siehe mein Code oben).

Wenn du dein gewünschtes Element hast, kannst du über element.Element("ZAHL").Value bzw. element.Element("Wert").Value die entsprechenden werte auslesen. Ich berufe mich dabei auf den ersten Xml-Format. Das Zweite macht nämlich keinen Sinn. In der Regel sollte man auf Attribuite eher verzichten - ausgenommen solche wie ID natürlich.

Früher habe ich auch gerne Attribute genommen, weil es "einfacher" waren darauf zuzugreifen und sie eindeutig sind und es schöner aussieht und und und... allerdings habe ich die Erfahrung gemacht, das die Erweiterbarkeit darunter leidet. Der Zugriff ist nicht wirklich schwieriger und die lesbarkeit auch nicht.

Deshalb würde ich nehmen:

XML-Daten
1:
2:
3:
4:
5:
6:
<resistances>
   <resistance id="50">
      <value>50</value>
      <best>432432 - 52</best>
   <resistance>
</resistances>


Gruß