Parsen von XML Strings

Hallo zusammen,

ich spiele gerade mit dem REST-Client für den Arduino rum.
Ich komme mittlerweile an meine REST API ran und bekomme folgende Antwort:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?><item><type>DimmerItem</type><name>Buero_Licht_Durchgang</name><state>[b]0.0[/b]</state><link>http://192.168.178.1/rest/items/Buero_Licht_Durchgang</link></item>

Wichtig ist für mich der Wert state. Wie kann ich anhand dieses Wertes eine LED an oder ausschalten?
Danke euch.

Als was für einen Datentyp hast du diese Zeile? C-String/char Array?

ICwiener: Wichtig ist für mich der Wert state. Wie kann ich anhand dieses Wertes eine LED an oder ausschalten? Danke euch.

Liest Du die Zeile erst komplett in einen Puffer ein und möchtest die relevanten Daten dann hinterher aus dem Puffer herausschneiden?

Oder möchtest Du eintreffende Zeichen char für char parsen ohne irgendwas zwischenzuspeichern, außer den gewünschten state-Daten, sobald sie eintreffen?

Ich brauche eigentlich nur den Char-Wert. Wenn dieser nachher größer wie "0" ist, soll die LED angehen.

Wenn du einen C-String hast kann man es ganz primitiv so machen:

char str[] = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><item><type>DimmerItem</type><name>Buero_Licht_Durchgang</name><state>[b]1.0[/b]</state><link>http://192.168.178.1/rest/items/Buero_Licht_Durchgang</link></item>";
char* pch = strtok(str, "]");
pch = strtok(NULL, "[");

pch zeigt dann auf den string “1.0”

Das geht aber von zwei Bedingungen aus:
1.) Die Zahl steht immer innerhalb von b-tags
2.) Es kommt nie ein Tag mit eckigen Klammern vorher

Wenn das mal nicht zutrifft funktioniert es nicht

EDIT:
Hiermit kann man immerhin die Tags isolieren:

char* start = strstr(str, "<state>");            //pointer auf den Anfang von "<state>"
char* end = strstr(start, "</state>");        //pointer auf den Anfang von "</state>"
char substring [30];
memset(substring, 0, sizeof(substring));
strncpy(substring, start, end - start + 8);

Danach steht in substring das:

<state>[b]1.0[/b]</state>

Dann könnte man das machen:

char* pch = strpbrk(substring, "0123456789");   //Pointer auf das erste Auftauchen einer Ziffer
double d = atof(pch);    //array to float

Dabei ist es dann egal wo im string die Zahl steht und was danach kommt. Er sucht einfach die erste Ziffer und wandelt dann alles danach was einem Float-Wert entspricht.

Damit kannst du dir sogar oben den Schritt mit dem kopieren sparen und nur das machen:

char* start = strstr(str, "<state>");
char* pch = strpbrk(start, "0123456789");
double d = atof(pch);

Aber keine Sorge. Jurs wird dir sicher in Kürze die perfekte Lösung liefern, die unter allen erdenklichen Umständen funktioniert :slight_smile:

Jurs wird dir sicher in Kürze die perfekte Lösung liefern

Bis dahin kannst du rauskriegen, warum das xml-Element den Wert [b]0.0[/b] hat (und nicht einfach 0) ,
falls du Zugriff auf den erzeugenden web service hast…

Ansonsten (falls jurs nicht eine universelle xml-Parser “Demo” zaubert) , würde ich auch das xml-spezifische ignorieren und einen einfachen Text-Parser auf strstr - Basis wie Serenifly verwenden:

char * getState(const char* str)   // const :    str wird nicht verändert
{
   const char* start = strstr(str, "<state>");            //pointer auf den Anfang  "<state>"
   if (start == NULL) return NULL;  // FEHLER: kein "<state>" vorhanden
   start += 7;  // Anfang des Werts
   const char* end = strstr(start, "</state>");        //pointer auf den Anfang von "</state>"
   if (end == NULL) return NULL;   // FEHLER: kein "</state>" vorhanden
   static char result [30];   // Ergebnis als separate Kopie
   strncpy(result, start, end - start);
   return result;
}

Daran die Tags nicht mitzukopieren hatte ich auch schon gedacht :)

Dann muss das Array aber nicht 30 groß sein. Der Platz ist nur für die state-Tags da. Für die Zahl + b-Tags reichen auch 15.

EDIT: Vielleicht wollte er mit dem b-Tags nur die Zahl die braucht fett im Forum markieren. Und hat nicht bedacht, dass die Code-Tags diese Formatierung ignorieren...