Moin,
hat irgendwer ne Ahnung, wie das XML parsen mittels expat, wie sie es im BP gemacht haben, funktioniert?
Ich werde weder aus deren Code schlau noch aus der expat-online-Dokumentation.
Oder weiß wer einen XML-Parser für C, der einfach handzuhaben ist? Ich versuche mich derzeit an LIBXML, aber auch das will nicht so recht.
XML parsen mit expat
Moderator: Flashy
-
- Bei Tony Rumsteher
- Beiträge: 44
- Registriert: 20 Mai 2003, 21:38
Ja, siehe untenRealist hat geschrieben: hat irgendwer ne Ahnung, wie das XML parsen mittels expat, wie sie es im BP gemacht haben, funktioniert? Ich werde weder aus deren Code schlau noch aus der expat-online-Dokumentation.
Kein Wunder, die beiden sind auch arg verwand miteinander ...Realist hat geschrieben:Oder weiß wer einen XML-Parser für C, der einfach handzuhaben ist? Ich versuche mich derzeit an LIBXML, aber auch das will nicht so recht.
(German Description follows: )
Schau Dir doch mal in .\Tactical\XML_ComboMergeInfo.cpp die Funktion
ReadInAttachmentComboMergeStats() an.
Das ist die einfachste, kleinste. Im groben Prinzip funktioniert das so:
Code: Alles auswählen
/*define Your own struct for the data from XML file */
struct {...} typedef attachmentcombomergeParseData;
...
/*create our Data object */
attachmentcombomergeParseData Data;
/*create a parser object */
XML_Parser parser = XML_ParserCreate(NULL);
erzeugt erstmal ein 'Objekt' parser. Dieses Objekt wird in den folgenden Funktionen überall als 1. Argument, quasi als Handle angegeben.
Dann wird ein Speicherblock in der Größe der XML-Datei angelegt (kann sein, daß man auch ohne RAM direkt lesen kann - egal, das findest Du eventuell später selbst heraus).
Code: Alles auswählen
XML_SetElementHandler( parser,
attachmentcombomergeStartElementHandle,
attachmentcombomergeEndElementHandle);
XML_SetCharacterDataHandler( parser,
attachmentcombomergeCharacterDataHandle );
- attachmentcombomergeStartElementHandle()
- attachmentcombomergeEndElementHandle()
- attachmentcombomergeCharacterDataHandle()
Code: Alles auswählen
/* Init Your own structure to ZERO */
memset( &Data, 0x00, sizeof(pData) );
/* Init some of the Members to useful start values */
Data.curArray = AttachmentComboMerge;
Data.maxArraySize = MAXITEMS;
/* set parser to tell us the address of 'Data' as 1st arg on each call*/
XML_SetUserData(parser, &Data);
Code: Alles auswählen
attachmentcombomergeParseData * pData =
(attachmentcombomergeParseData*) userData;
Code: Alles auswählen
typedef struct
{
UINT16 usItem;
UINT16 usAttachment[2];
UINT16 usResult;
UINT32 uiIndex;
} ComboMergeInfoStruct;
...
ComboMergeInfoStruct AttachmentComboMerge[MAXITEMS+1];
Was kommt nun noch? Nun ja, das Parsen des gesamten Speicherblockes (der ja eine 1:1 Kopie der XML-Datei enthält). Und wenn der Parser fertig ist, das Freigeben des Parser-Objektes.
Und letztlich das Freigeben des Speicherblocks
[/CODE]
XML_Parse(parser, lpcBuffer, uiFSize, TRUE);
XML_ParserFree(parser);
[/CODE]
ja ... aber ... wo wird denn nun gelesen?

Das ist ganz einfach: in den 3 Callback-Funktionen, die oben schon mehrfach erwähnt wurden! Die XxxxStartElement() Funktion wird immer gerufen, wenn die XML-Datei ein Element öffnet. Das ist nicht nur eine einfache Variable wie
Code: Alles auswählen
<uiIndex>0</uiIndex>
Code: Alles auswählen
<ATTACHMENTCOMBOMERGELIST>
<ATTACHMENTCOMBOMERGE>
<uiIndex>0</uiIndex>
In der XxxxCharacterDataHandle() Funktion wird hier - entgegen dem Namen - recht wenig gemacht, nämlich einfach nur der Inhalt aller aktuellen Datenelemente an pData->szCharData angehängt. Auf der ersten Daten-Ebene angekommen, müßte in pData->szCharData also "0" stehen, weil es nur ein einziges Datenelement 'uiIndex' mit Wert '0' gibt: "<uiIndex>0</uiIndex>". Das 'richtige' Auswerten der Daten kommt erst, wenn "</uiIndex>" gefunden wurde, und zwar in
XxxxEndElement(). Das ist durchaus schlau, denn erst jetzt wissen wir, daß der Parser das letzte Zeichen des Dateninhaltes gefunden hatte. in unseren Beispielen ist das zwar immer nur einen einzelne Zahl die wir schon in XxxxCharacterDataHandle() hätten auswerten können, aber das ist in XML durchaus nicht immer der Fall. in JA2.1.13 sind die uiIndex-Felder übrigens sehr sensibel, da alle XML-Lesefunktionen Ihre Indizees für die internen C- Arrays direkt aus diesen XML-Variablen lesen. Und fast alle der externalisierten Arrays sind 5000 Zeichen groß.
Ein letzter Hinweis:
unsere XML-Dateien verwenden UTF-8. UTF-8 erlaubt optional einen BOM (Byte Order Marker), d.h. 3 Bytes am Anfang der Datei, die in Hex "EF BB BF" lauten. Spätestens beim Einsatz von deutschen Texten mit äÄöÖüÜß spinnen einige Tools (u.a. Beyound Compare), wenn die Datei mal mit, mal ohne BOM abgespeichert wurde. Tip: BOM immer benutzen.
