17.11.2011
Einlesen von XML und Zugriff mit XQuery
Hier wird beschrieben, wie XML-Content, d.h. eine XML-Datei oder eine URL, die XML liefert, eingelesen werden. Danach werden gezielt Werte mittels XQuery ausgelesen. Zu beachten ist, daß der XML-Content in ein NSXMLDocument
eingelesen werden und damit Probleme auftreten können, wenn die XML-Daten "zu groß" werden. In diesen Fall sollte ein eventbasierter Parser verwendet werden.
XML-Datei einlesen und ein Element mit XQuery auslesen
Als erstes soll eine XML-Datei vom lokalen Dateisystem eingelesen werden. Als Beispiel wird eine TCX-Datei verwendet, aus der die Länge der Wanderung (DistanceMeters
) bestimmt werden soll (So eine Datei kann man einfach bei GPSies exportieren.).
Hier ist ein Ausschnitt einer TCX-Datei zu sehen.
<?xml version="1.0" encoding="UTF-8"?> <TrainingCenterDatabase xmlns="http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2 http://www.garmin.com/xmlschemas/TrainingCenterDatabasev2.xsd"> <Folders> <Courses> <CourseFolder Name="GPSies"> <CourseNameRef> <Id>Rundwanderung</Id> </CourseNameRef> </CourseFolder> </Courses> </Folders> <Courses> <Course> <Name>Rundwanderung</Name> <Lap> <TotalTimeSeconds>4493.0</TotalTimeSeconds> <DistanceMeters>12481.917842577497</DistanceMeters> <BeginPosition> <LatitudeDegrees>50.21631480</LatitudeDegrees> <LongitudeDegrees>8.402616940</LongitudeDegrees> </BeginPosition> <EndPosition> <LatitudeDegrees>50.21724890</LatitudeDegrees> <LongitudeDegrees>8.402907420</LongitudeDegrees> </EndPosition> <Intensity>Active</Intensity> </Lap> <Track> <Trackpoint> <Time>2011-11-17T10:44:10Z</Time> <Position> <LatitudeDegrees>50.21631480</LatitudeDegrees> <LongitudeDegrees>8.402616940</LongitudeDegrees> </Position> <AltitudeMeters>509.00000</AltitudeMeters> <DistanceMeters>0.000</DistanceMeters> </Trackpoint> <Trackpoint> <Time>2011-11-17T10:44:23Z</Time> <Position> <LatitudeDegrees>50.21665140</LatitudeDegrees> <LongitudeDegrees>8.402668560</LongitudeDegrees> </Position> <AltitudeMeters>509.00000</AltitudeMeters> <DistanceMeters>37.608</DistanceMeters> </Trackpoint> ... </Track> </Course> </Courses> </TrainingCenterDatabase>
Der folgende Programmschnipsel zeigt, wie man eine Datei einliest und den gewünschten Wert ausliest und anzeigt.
NSString *filename = [@"~/Documents/Wanderung.tcx" stringByResolvingSymlinksInPath]; NSError *error = nil; NSString *xmlContent = [NSString stringWithContentsOfFile:filename encoding:NSUTF8StringEncoding error:&error]; NSXMLDocument *xmlDOM = [[NSXMLDocument alloc] initWithXMLString:xmlContent options:NSXMLNodePreserveAll error:&error] ; NSString *xquery = @"/TrainingCenterDatabase/Courses/Course/Lap/DistanceMeters"; NSArray *result = [xmlDOM objectsForXQuery:xquery error:&error]; NSXMLNode *firstNode = [result objectAtIndex:0]; NSLog(@"Length in meters: %@", [firstNode stringValue]);
Nachdem der Dateiname festgelegt wurde, wird der Inhalt der Datei mit stringWithContentsOfFile:encoding:error:
in einen NSString
eingelesen. Dabei ist darauf zu achten, daß die Datei nicht zu groß ist, weil der Inhalt komplett in den Speicher gelesen wird. Anschließend wird ein NSXMLDocument
mit dem NSString
initialisiert. Dafür wird die Methode initWithXMLString:options:error
verwendet. Aus dem Ausschnitt der TCX-Datei läßt sich der XPath, der in xquery
gespeichert wird, ableiten. Die Klasse NSXMLDocument
stellt die Methode objectsForXQuery:error
zur Verfügung, um die XQuery auszuführen. Die Methode liefert ein NSArray
zurück. In dem Beispiel wird einfach das erste Element vom Typ NSXMLNode
ausgelesen und anschließend der String-Wert ausgegeben.
Zu beachten ist, daß die Fehlerbehandlung in dem Beispiel weggelassen wurde! Normalerweise sollte man das Error-Element auswerten.
XML-Content von URL lesen und mit XQuery auf Elemente zugreifen
In diesem Beispiel werden die XML-Daten direkt von einer URL gelesen, wieder in einem NSString
zwischengespeichert und dann zur Initialisierung eines NSXMLDocuments
verwendet. Anschließend wird mit einer XQuery darauf zugegriffen und alle Titel der XML-Daten ausgelesen und auf der Konsole ausgegeben. Als Beispieldaten wurde der Heise-News-Feed verwendet.
Der einzige Unterschied zu dem Beispiel oben ist, daß hier die Methode stringWithContentsOfURL:encoding:error
verwendet wurde.
NSError *error = nil; NSString *xmlContent = [NSString stringWithContentsOfURL:[NSURL URLWithString:@"http://www.heise.de/newsticker/heise-atom.xml"] encoding:NSUTF8StringEncoding error:&error]; NSXMLDocument *xmlDOM = [[NSXMLDocument alloc] initWithXMLString:xmlContent options:NSXMLNodePreserveAll error:&error] ; NSString *xquery = [NSString stringWithFormat:@"/feed/entry/title"]; NSArray *result = [xmlDOM objectsForXQuery:xquery error:&error]; NSXMLNode* node; for (node in result) { NSLog(@"%@", [node stringValue]); }
Ein Ausschnitt aus den XML-Daten ist im Folgenden zu sehen:
<?xml version="1.0" encoding="utf-8"?> <feed xmlns="http://www.w3.org/2005/Atom"> <title>heise online News</title> <subtitle>Nachrichten nicht nur aus der Welt der Computer</subtitle> <link href="http://www.heise.de/newsticker/" /> <link rel="self" href="http://www.heise.de/newsticker/heise-atom.xml" /> <updated>2011-11-17T19:31:49+01:00</updated> <author> <name>heise online</name> </author> <id>http://www.heise.de/newsticker/</id> <entry> <title>EU-Parlament macht sich für die Netzneutralität stark</title> <link href="http://www.heise.de/newsticker/meldung/EU-Parlament-macht-sich-fuer-die-Netzneutralitaet-stark-1381116.html/from/atom10" /> <id>http://www.heise.de/newsticker/meldung/EU-Parlament-macht-sich-fuer-die-Netzneutralitaet-stark-1381116.html/from/atom10</id> <published>2011-11-17T19:30:00+01:00</published> <updated>2011-11-17T19:31:49+01:00</updated> </entry> <entry> <title>Erste Grafikbenchmarks von Nvidias Tegra 3</title> <link href="http://www.heise.de/newsticker/meldung/Erste-Grafikbenchmarks-von-Nvidias-Tegra-3-1381018.html/from/atom10" /> <id>http://www.heise.de/newsticker/meldung/Erste-Grafikbenchmarks-von-Nvidias-Tegra-3-1381018.html/from/atom10</id> <published>2011-11-17T19:10:00+01:00</published> <updated>2011-11-17T19:53:55+01:00</updated> </entry> </feed>