Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

  • »
  • Community
  • |
  • Diskussionsforum
Wert in XML-Datei suchen und auslesen
Sasa
myCSharp.de - Member



Dabei seit:
Beiträge: 7
Herkunft: Paderborn

Themenstarter:

Wert in XML-Datei suchen und auslesen

beantworten | zitieren | melden

Hallo,

es geht um eine XML-Datei, die mehrere Einträge, wie diesen hier enthält:
<Airport country='United States' state='' city='San Francisco' name='San Francisco Intl.' lat='26.7887477840029' lon='14.2414503521609' alt='479.9583125' ident='USS19'>

Ich möchte aus der XML-Datei den Wert auslesen, der hinter ident steht (also in diesem Fall USS19) auslesen.
Allerdings mit einem Knackpunkt: In der Datei stehen mehrere idents, und ich möchte nur den letzten, ganz unten in der Datei stehenden, ausgelesen haben.

Irgendwelche Ideen? Für ein Codebeispiel wäre ich natürlich extrem dankbar!

Grüsse
Sascha
private Nachricht | Beiträge des Benutzers
frisch
myCSharp.de - Member

Avatar #avatar-1724.gif


Dabei seit:
Beiträge: 2.082
Herkunft: Coburg / Oberfranken

beantworten | zitieren | melden

Hallo Sasa,

schau dir mal XmlDocument, XmlAttribute und dazu die Value an.

kleiner Tipp: SelectSingleNode bzw. SelectNodes
Es ist toll jemand zu sein, der nichts von der persönlichen Meinung Anderer hält. - frisch-live.de
private Nachricht | Beiträge des Benutzers
LaTino
myCSharp.de - Experte

Avatar #avatar-4122.png


Dabei seit:
Beiträge: 3.003
Herkunft: Thüringen

beantworten | zitieren | melden

Einfacher:


System.Xml.XmlDocument doc = new System.Xml.XmlDocument();
doc.load("myXml.xml");
string lastIdent = doc.FirstChild.LastChild.Attributes["ident"];

Kannst du machen, wenn du die Struktur genau kennst (falls da noch mehr Ebenen sind, einfach weiter hinunter hangeln...).

LaTino
"Furlow, is it always about money?"
"Is there anything else? I mean, how much sex can you have?"
"Don't know. I haven't maxed out yet."
(Furlow & Crichton, Farscape)
private Nachricht | Beiträge des Benutzers
Sasa
myCSharp.de - Member



Dabei seit:
Beiträge: 7
Herkunft: Paderborn

Themenstarter:

beantworten | zitieren | melden

Vielen Dank erst einmal! Das hilft mir schon mal weiter.
Allerdings bekomme ich mit LaTinos Codebeispiel eine Fehlermeldung zu dritten Zeile: "Implizite Konvertierung des Typs 'System.Xml.XmlAttribute' zu 'string' nicht möglich".

Sorry, dass ich euch mit solchen Fragen zu Basis-Wissen nerve. Ich hätte wohl am Anfang meines C#-Buches anfangen sollen und nicht in der Mitte. Momentan muss ich aber sehr schnell fertig werden und freue mich über jede weitere Hilfe umso mehr. X(

Grüsse
Sascha
private Nachricht | Beiträge des Benutzers
Coreyl
myCSharp.de - Member



Dabei seit:
Beiträge: 65

beantworten | zitieren | melden


string lastIdent = doc.FirstChild.LastChild.Attributes["ident"];
wird zu =>
string lastIdent = doc.FirstChild.LastChild.Attributes["ident"].toString();
private Nachricht | Beiträge des Benutzers
LaTino
myCSharp.de - Experte

Avatar #avatar-4122.png


Dabei seit:
Beiträge: 3.003
Herkunft: Thüringen

beantworten | zitieren | melden

Nicht ganz.


string lastIdent = doc.FirstChild.LastChild.Attributes["ident"].Value;

Sorry. Mir fehlt hier noch IntelliSense im Forum :D.

LaTino
"Furlow, is it always about money?"
"Is there anything else? I mean, how much sex can you have?"
"Don't know. I haven't maxed out yet."
(Furlow & Crichton, Farscape)
private Nachricht | Beiträge des Benutzers
Coreyl
myCSharp.de - Member



Dabei seit:
Beiträge: 65

beantworten | zitieren | melden

hm stimmt vergessen das der inhalt gesucht war
jo intellisense wär ganz nützlich
myc#3.de abwarten ^^
private Nachricht | Beiträge des Benutzers
VizOne
myCSharp.de - Member

Avatar #avatar-1563.gif


Dabei seit:
Beiträge: 1.373

beantworten | zitieren | melden

Man könnte hier auch gut XPath einsetzen:


XPathDocument doc = new XPathDocument(fileName);
XPathNavigator nav = doc.CreateNavigator();
XPathNavigator node = nav.SelectSingleNode("//Airport[position()=last()]/@ident");
string lastIdent = node.Value;

Grüße,
Andre

P.S.:
Wenn das ident-Attribute optional ist, musst du das hier verwenden:


"//Airport[@ident][position()=last()]/@ident"

Wenn du alternativ das letzte ident-Attribut suchst (egal welches Element), dann ginge:


"//*[@ident][position()=last()]/@ident"
als XPath.
private Nachricht | Beiträge des Benutzers
Sasa
myCSharp.de - Member



Dabei seit:
Beiträge: 7
Herkunft: Paderborn

Themenstarter:

beantworten | zitieren | melden

Arg! So viele Möglichkeiten! Jungs, ihr treibt mich noch zum Wahnsinn...
Sieht so aus, als wenn ich mich noch ein paar Monate hinter die Bücher setzen muss, denn über die MSDN werde ich zu den ganzen ChildForms überhaupt nicht schlau (sind die Texte da mit einem Software-Translator übersetzt worden?).

Die Struktur des XML-Dokuments sieht so aus:


Weil Airport ja weder das FirstChild, noch das LastChild ist (soweit ich das verstanden habe), habe ich es mal mit VizOne's Version versucht. Allerdings bekomme ich hier haufenweise Fehlermeldungen, dass XPath, XPathNavigator und XPathNavigator nicht gefunden wurden. Ein Include für System.Xml besteht aber. ?(

Grüsse
Sascha
private Nachricht | Beiträge des Benutzers
Coreyl
myCSharp.de - Member



Dabei seit:
Beiträge: 65

beantworten | zitieren | melden

1. System.Xml.Xpath ??
2.<Airport> kann lastchild sein (im <FSData> Tag!)
private Nachricht | Beiträge des Benutzers
Sasa
myCSharp.de - Member



Dabei seit:
Beiträge: 7
Herkunft: Paderborn

Themenstarter:

beantworten | zitieren | melden

Zitat
1. System.Xml.Xpath ??

Stimmt. Hatte ich auch schon probiert, bekomme dann aber weitere Fehlermeldungen. Hier noch der aktuelle Code:

			System.Xml.XPath.XPathDocument doc = new System.Xml.XPath.XPathDocument();
			doc.Load("AF2_CoastGuard.xml");
			System.Xml.XPath.XPathNavigator nav = doc.CreateNavigator();
			System.Xml.XPath.XPathNavigator node = nav.SelectSingleNode("//Airport[position()=last()]/@ident");
			string lastIdent = node.Value; 

Auf 'System.Xml.XPath.XPathDocument.XPathDocument()' ist der Zugriff aufgrund der Sicherheitsebene nicht möglich
Auf 'System.Xml.XPath.XPathDocument.Load(System.Xml.XmlReader)' ist der Zugriff aufgrund der Sicherheitsebene nicht möglich
'System.Xml.XPath.XPathNavigator' enthält keine Definition für 'SelectSingleNode'

Grüsse
Sascha
private Nachricht | Beiträge des Benutzers
VizOne
myCSharp.de - Member

Avatar #avatar-1563.gif


Dabei seit:
Beiträge: 1.373

beantworten | zitieren | melden

Benutzt du .NET 2? Davon war ich nämlich ausgegangen.

Grüße,
Andre
private Nachricht | Beiträge des Benutzers
Coreyl
myCSharp.de - Member



Dabei seit:
Beiträge: 65

beantworten | zitieren | melden

Folgender Code:


using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;

namespace sasaandxml
{
    class Program
    {
        static void Main(string[] args)
        {
            XmlDocument input = new XmlDocument();
            input.Load("C:/temp/doc.xml");
            string inhalt = input.SelectSingleNode("//Airport[position()=last()]/@ident").Value; //endet erst hier!
   //vorsicht! hier falsch auskommentiert wg codetag!
            Console.WriteLine(inhalt);
            Console.Read();
        }
    }
}

generiert bei folgender xml:

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<root>
<FSData>
<Airport country='United States' state='' city='San Francisco' name='San Francisco Intl.' lat='26.7887477840029' lon='14.2414503521609' alt='479.9583125' ident='USS19erster'>
</Airport>
<Airport country='United States' state='' city='San Francisco' name='San Francisco Intl.' lat='26.7887477840029' lon='14.2414503521609' alt='479.9583125' ident='USS19zwoter'>
<InnerTag>blub</InnerTag>
</Airport>
<Airport country='United States' state='' city='San Francisco' name='San Francisco Intl.' lat='26.7887477840029' lon='14.2414503521609' alt='479.9583125' ident='USS19letzter'>
<InnerTag>blub</InnerTag>
</Airport>
</FSData>
</root>
folgenden output:
USS19letzter
ergo: funktioniert
arbeite ohne xpathnavigator, nur aufm DOM und nutze xpath

p.s. die xml hab ich zum testen selbst zammegeschusstert, bin mir aber fast sicher das es direkt auf deine xml anwendbar sein wird
ansonsten dürfte dir das als hilfe genügen 8)
private Nachricht | Beiträge des Benutzers
VizOne
myCSharp.de - Member

Avatar #avatar-1563.gif


Dabei seit:
Beiträge: 1.373

beantworten | zitieren | melden

Ja, für .NET 1.1 gehts auch so. Wie gesagt, ich bin von .NET 2 ausgegangen und da ist das XPathDocument vorzuziehen, weil es viel "leichter" und schneller ist.

Grüße,
Andre
private Nachricht | Beiträge des Benutzers
Coreyl
myCSharp.de - Member



Dabei seit:
Beiträge: 65

beantworten | zitieren | melden

hm
schneller nun gut kann gut sein da wohl nicht das ganze dokument geladen wird sondern nur durchnavigiert wird ABER:

ist das element ganz unten, das dokument würde fast komplett geladen werden!

in meinem beispiel wird das dokument 1x gelesen 1x bearbeitet (durchsucht nach der node) (wobei ich mir nit sicher bin wie das xpathdokument erzeugt wird o.ä.)
ich brauche 3 zeilen code er min. 5, also was "leichter" ist sei dahingestellt
ausserdem funktioniert mein beispiel, das ist wohl das wichtigste (vorallem bei so einer trivialen aufgabe wie suche element x mit attribut y aus xy.xml)
ich persönlich bevorzuge das xmldocument...
p.s. trotz .net 2.0
private Nachricht | Beiträge des Benutzers
VizOne
myCSharp.de - Member

Avatar #avatar-1563.gif


Dabei seit:
Beiträge: 1.373

beantworten | zitieren | melden

Mit "leichter" meinte ich den Speicherverbrauch. Ich kann gegen deine persönlichen Vorzüge nichts sagen, aber ich möchte doch jedem empfehlen, zum Suchen innerhalb größerer XML Dokumente und beim Transformieren mittels XSLT ein XPathDocument zu verwenden.


Grüße,
Andre


http://jdixon.dotnetdevelopersjournal.com/xpath_performance_in_net.htm
http://jira.public.thoughtworks.org/browse/CCNET-103
http://support.microsoft.com/default.aspx?scid=kb;en-us;325689
etc.
private Nachricht | Beiträge des Benutzers
Sasa
myCSharp.de - Member



Dabei seit:
Beiträge: 7
Herkunft: Paderborn

Themenstarter:

beantworten | zitieren | melden

Danke euch allen. Hier jetzt der Code, mit dem es funktioniert:

			XmlDocument input2 = new XmlDocument();
			input2.Load("test.xml");
			string inhaltIdent = input2.SelectSingleNode("//Airport[position()=last()]/@ident").Value;

			inhaltIdent = inhaltIdent.Substring(2,3);
			float inhaltIdent2 = 0;
			inhaltIdent2=Convert.ToInt16(inhaltIdent)+1;
			string inhaltIdent3 = "";
			inhaltIdent3=Convert.ToString(inhaltIdent2);
			if (inhaltIdent3.Length < 2)
			{
				inhaltIdent3 = "00" + inhaltIdent3;
			}
			if (inhaltIdent3.Length < 3)
			{
				inhaltIdent3 = "0" + inhaltIdent3;
			}
private Nachricht | Beiträge des Benutzers
Yellow
myCSharp.de - Experte

Avatar #avatar-2347.png


Dabei seit:
Beiträge: 476

Verbesserungsvorschläge...

beantworten | zitieren | melden

Hallo Sasa,
erst mal Glückwunsch zum funktionierenden Code. Allerdings möchte ich Dir noch ein paar Verbesserungsvorschläge unterbreiten...


			inhaltIdent = inhaltIdent.Substring(2,3);
Hat sich da ein Tippfehler eingeschlichen? Müsste doch 3,2 heissen... aber nuja, damit legst Du Dich fest wie groß der numerische Teil deines Ident ist, da Du aber weiter unten 1 addierst, könnte ja sein, dass dur irgendwann bei mehr Stellen bist (99 -> 100).


float inhaltIdent2 = 0;
inhaltIdent2=Convert.ToInt16(inhaltIdent)+1;
string inhaltIdent3 = "";
inhaltIdent3=Convert.ToString(inhaltIdent2);
Weshalb verwendest Du hier einen float (bzw. single). Das macht keinen Sinn. Du konvertierst deine Variable in einen Integer, was für eine Ganzzahl auch sinnvoll ist. Die Zuweisung funktioniert auch, da du eine Ganzzahl in eine Gleitkommazahl konvertieren kannst, aber ich würde mir so etwas abgewöhnen, bei komplexerem Code kann das schnell zu Fehlern führen.

Zu:


if (inhaltIdent3.Length < 2)
  {
    inhaltIdent3 = "00" + inhaltIdent3;
   }
if (inhaltIdent3.Length < 3)
  {
    inhaltIdent3 = "0" + inhaltIdent3;
}
würde ich zu folgendem Ersatz vorschlagen:


inhaltIdent3 = InhaltIdent3.PadLeft(3,'0');

-yellow
Selbst ein Weg von tausend Meilen beginnt mit einem Schritt (chinesisches Sprichwort).

Mein Blog: Yellow's Blog auf sqlgut.de
private Nachricht | Beiträge des Benutzers