FLAM® Issue Tracker

View Revisions: Issue #869 Back to Issue ]
Summary 0000869: StAX like XML parser and writer
Revision 2017-03-26 22:54 by Falk Reichbott
Description Derzeit ist der Umgang mit unsere FL5-Element-Struktur an sich zu komplex und man könnte für die Kunden auf Basis des FLUC-Record-API im Gegensatz zum COBOL XML PARSE (SAX (Callback/Eventhandler-API)) eine
vereinfachte XMLPULL-API anbieten (StAX).

hdl=FCXOPN(filstr,modstr)
Man gibt beim Open nur den READ.XML-String mit und über den Mode-String legt man fest, ob man die simple oder die komplexe Varinate und noch so ein paar Kleinigkeiten (Kommentare, XML-Schlüsselwörter großgeschrieben, UTF-8, local Charset, UCS-16 (WC) oder UTF-32 (Codepoint in local endianess, Selection (ENUM) für XML-Schlüsselwörter)) haben will.

Nach dem Open kann man die XML-Version und das Encoding abfragen.

R15=FCXNEXT(hdl)
Die Next-Funktion liest das nächste XML-Element und gibt den
Element-Type (Token>0) oder halt einen Fehler (Token<0) zurück.

In Abhängigkeit des Typ bzw. Tokens kann man sich nun mit diversen GET-Funktionen, die jeweiligen Datentypen an dieser Cursor-Position abholen. Hierbei gibt es für XML-Schlüsselwörter (Tag-Namen und Attribut-Namen) zwei Varianten. GetKeyWord (FCXGKW) gibt den String zum Vergleich zurück (Case sensitive oder in Großbuchstaben) oder wenn man eine Selection im Open definiert hat, dann gibt GetKeyValue (FCXGKV) den INTEGER (PIC 9(9) COMP) für das Schlüsselwort zurück.

R15=FCXGKW(hdl,kywlen,kyw)
R15=FCXGKV(hdl)

In Abhängigkeit des Types/Token kann man ein XML-Schlüsselwort und oder XML-Daten abfragen. Zum Beispiel kann man beim Token ATTRIBUTE sich das KeyWord/Value oder die Daten geben lassen. Bei der Datenabfrage kann man sich die internen UTF-8-Strings in jegliche Datentypen wandeln lassen. Für jeden Datentyp gibt es entsprechende Funktionen.

R15=FCXGBH(hdl,binlen,bindat) - GetBinHex
Wandelt hexadezimalen String in Binärdaten.

R15=FCXGB6(hdl,binlen,bindat) - GetBinB64
Wandelt Base64 String in Binärdaten (mit oder ohne Armor-Header-Trailer).

R15=FCXGIB(hdl,intlen,intdat) - GetIntBin
Wandelt Zahlenstring in 2'Complement der Längen 1, 2, 4 und 8

R15=FCXGIC(hdl,bcdlen,bcddat) - GetIntBcd
Wandelt Zahlenstring gepackten BCD mit Vorzeichen

R15=FCXGFB(hdl,fltlen,fltdat) - GetFltBin
Wandelt Zahlenstring in binären Float der Längen 4, 8 und 16

R15=FCXGFCxx(hdl,fltlen,fltdat) - GetFltBcd
Wandelt Zahlenstring in BCD Float, wobei xx für die Nachkommastellen steht

R15=FCXGSC(hdl,strlen,strdat) - GetStrClp (Collapsed)
Gibt String collapsed zurück

R15=FCXGSB(hdl,strlen,strdat) - GetStrBth (Both)
Gibt String ohne Trailing and leading Whitespace zurück

R15=FCXGDAT(hdl,datlen,data) - GatData
Gibt die Daten unverändert (UTF-8) zurück.

Da wird es noch einiges mehr an Funktionen geben, hier nur mal die Wichtigsten.

Nun noch zu den Varianten:

Simple:

Hier gibt es die folgenden XML-Typen/Token, DTD und Kommentare werden überlesen. CDATA wird nicht unterstützt. Datenteile dürfen eine Stringlänge von 64k nicht übersteigen. Datenteile sind nur in den Blättern möglich.

XML-STARTELM hier geht kann man sich nur das Key-Word/Value holen
XML-ATTRIBUTE hier kann man sich Key-Word/Value und die Daten holen
XML-ENDSTARTELM hier kommen keine Daten und man kann sich nur das KeyWord/Value holen
XML-ENDSTARTELMDAT hier kann man sich die Daten und das KeyWord/Value holen
XML-ENDELM hier kann man sich nur das KeyWord/Value holen

Das XML-Dokument darf bei der simplen Variante nur folgende Syntax haben.

xml-document -> XML xml-statement-list
             | xml-statement-list

xml-statement-list -> xml-statement xml-statement-list
                   | xml-statement

xml-statement -> XML-XML-SARTELM xml-attr-list XML-ENDELM
xml-statement | XML-XML-SARTELM xml-attr-list XML-ENDSTARTELM
xml-statement | XML-XML-SARTELM xml-attr-list XML-ENDSTARTELMDAT

xml-attr-list -> XML-ATTRIBUTE xml-attr-list
              | @

Komplex:

Die komplexe Variante unterstützt dann CDATA, Kommentare, Datenteile überall und auch mehrteilige Datenpasagen und DTD. Allerding gibt es dann wieder alle Elementtypen und in der Regel kann man sich bis auf die Attribute entweder die KeyWords/Values oder die Daten abholen.

Das Schreiben geht an sich genauso, nur das man hier mit Settern die Daten an das Handle übergibt und dann mit FCXNEXT() das Rausschreiben bewirkt.
Revision 2017-03-27 10:45 by Falk Reichbott
Description Mit der Version 5.1.15, welche wir gerade fertig stellen, kommen die
Integer- und Float-Element-Konverter, damit man FL5-XML-Elemente direkt
in Cobol-Zahlen-Datentypen (BCD und BIN) wandeln kann. Dies brauchen wir in de 5.1.16 für den Table-Support, damit sie CSV-Dateien als FB-Record über die Satzschnittstelle zurückbekommen oder auch schreiben können.

Wenn man auf der anderen Seite im XML weiß, dass ein Betrag jetzt
gekommen ist, dann konvertiert man das Attributevalue oder das
Datenelement zu einem BCD oder 2'er-Komplement.

Da das XML-Element ein UTF-8-String ist, muss man also die Zahl von
einer externen Stringdarstellung in die interne neutrale Zahlendarstellung (wir nutzen BCD, damit es keinen Genauigkeitsverlust gibt) überführen und von dieser in den jeweiligen externen Datentyp, welchen man in seinem COPYBOOK braucht (egal, wie die Zahl in dem XML-Dokument gestanden hat).

> "conv.integer(from(format.str(chrset=UTF8)) to(format.bin(width=32)))"

Hierfür haben wir den FROM-TO-Conversion-String (siehe oben und die komplette Syntax am Ende der Mail) eingeführt und stellen mit der 5.1.15 alle Konvertrierung auch explizit über die neue Funktion FCRCONV(hdl,rtc,inlen, indat,outlen, outdat) zur Verfügung. Manchmal
weis man beim GET halt noch nicht, welche die richtige implitzite
Konvertierung wäre. In solchen Fällen oder halt immer kann man explizit
konvertieren. Haben Sie hier noch Ideen oder Wünsche.

Jetzt ist noch der Umgang mit unsere FL5-Element-Struktur beim
format.element() an sich zu komplex und man könnte für die Kunden auf
Basis des FLUC-Element-API im Gegensatz zum COBOL XML PARSE (SAX
(Callback/Eventhandler-API)) eine vereinfachte XMLPULL-API anbieten (StAX).

hdl=FCXOPEN(filstr,modstr)
Man gibt beim Open nur den READ.XML-String mit und über den Mode-String
legt man fest, ob man die simple oder die komplexe Varinate und noch so
ein paar Kleinigkeiten (Case-Senitive oder nicht, CCSID im Speicher, Selection (ENUM) für XML-Schlüsselwörter, und vieles mehr) haben will.

vsn=FCXGVSN(hdl)
enc=FCXGENC(hdl)
Nach dem Open kann man die XML-Version und das Encoding abfragen, da der
optionale XML-Tag ggf. schon weggelesen wurde.

R15=FCXNEXT(hdl)
Die Next-Funktion liest das nächste XML-Element und gibt den
Element-Type (Token>0) oder halt einen Fehler (Token<0, kann EOF sein)
zurück (sie stellt den Scanner für die diversen Datenformate (SEPA) in XML dar).

In Abhängigkeit des Typ bzw. Tokens kann man sich nun mit diversen
GET-Funktionen, die jeweiligen Datentypen an dieser Cursor-Position
abholen. Hierbei gibt es für XML-Schlüsselwörter (Tag-Namen und
Attribut-Namen) zwei Varianten. GetKeyWord (FCXGKW) gibt den String zum
Vergleich zurück (Case sensitive oder in Großbuchstaben) oder wenn man
eine Selection im Open definiert hat, dann gibt GetKeyValue (FCXGKV) den
INTEGER (PIC 9(9) COMP) für das Schlüsselwort zurück, sofern es gefunden
wurde (Achtung, bezieht sich auf den Tag- oder Attribut-Namen).

R15=FCXGKW(hdl,kywlen,kyw)
R15=FCXGKV(hdl)

In Abhängigkeit des Types/Token kann man ein XML-Schlüsselwort und oder
XML-Daten abfragen (State-Maschine im Hintergrund zur kontrolle). Zum Beispiel kann man beim Token XML-ATTRIBUTE sich das KeyWord/Value oder die Daten geben lassen. Bei der Datenabfrage kann man sich die internen UTF-8-Strings in jegliche Datentypen wandeln lassen. Für jeden Datentyp gibt es entsprechende GET-Funktionen.

R15=FCXGSV(hdl) - GetSelectionValue
Wandelt auch ein Schlüsselwort (Attributevalue oder Datenteil) in eine
Zahl (Fullword)

R15=FCXGBH(hdl,binlen,bindat) - GetBinHex
Wandelt hexadezimalen String in Binärdaten.

R15=FCXGB6(hdl,binlen,bindat) - GetBinB64
Wandelt Base64 String in Binärdaten (mit oder ohne Armor-Header-Trailer).

R15=FCXGIB(hdl,intlen,intdat) - GetIntBin
Wandelt Zahlenstring in 2'Complement der Längen 1, 2, 4 und 8

R15=FCXGIC(hdl,bcdlen,bcddat) - GetIntBcd
Wandelt Zahlenstring gepackten BCD mit Vorzeichen

R15=FCXGFB(hdl,fltlen,fltdat) - GetFltBin
Wandelt Zahlenstring in binären Float der Längen 4, 8 und 16

R15=FCXGFCxx(hdl,fltlen,fltdat) - GetFltBcd
Wandelt Zahlenstring in BCD Float, wobei xx für die Nachkommastellen
steht und die fltlen die führenden Nullen ergibt

R15=FCXGSC(hdl,strlen,strdat) - GetStrClp (Collapsed)
Gibt String collapsed zurück

R15=FCXGSB(hdl,strlen,strdat) - GetStrBth (Both)
Gibt String ohne Trailing and leading Whitespace zurück

R15=FCXGDAT(hdl,datlen,data) - GatData
Gibt die Daten unverändert (UTF-8) zurück.

Da wird es noch einiges mehr an Funktionen geben, hier nur mal die
Wichtigsten, um das Prizip zu veranschaulichen.

Nun noch zu den Varianten:

Simple:

Hier gibt es die folgenden XML-Typen/Token, DTD und Kommentare werden
überlesen. CDATA wird nicht akzeptiert. Datenteile dürfen eine
Stringlänge von 64k nicht übersteigen (kann im Open verkleinert oder bis
zu 1GiB vergrößert werden). Datenteile sind nur in den Blättern möglich.
Datenteile einfach zwischen drin, dürfen nur Whitespace enthalten und
werden genauso wie Default-Elemente überlesen. Sprich eine klassische
XML-Datei ohne Spakazien (ggf. kann Simple auch CDATA, aber da CDATA
auch Datenteile unterbrechen kann, passt dies nicht wirklich, man könnte an sich nur XML_ENDSTARTELMCDATA noch einführen, sprich ein ganzes Datenelement muss CDATA sein.)

> XML-STARTELM hier geht kann man sich nur das Key-Word/Value holen
> XML-ATTRIBUTE hier kann man sich Key-Word/Value und die Daten holen
> XML-ENDSTARTELM hier kommen keine Daten und man kann sich nur das KeyWord/Value holen
> XML-ENDSTARTELMDATA hier kann man sich die Daten und das KeyWord/Value holen
> XML-ENDELM hier kann man sich nur das KeyWord/Value holen

Das XML-Dokument darf bei der simplen Variante nur folgende Syntax haben (bitte beachten, dass DTD, Default-Elemente, leere Datenelemente und Kommentar überlesen werden).

> xml-document -> XML-TAG xml-statement-list
> | xml-statement-list
>
> xml-statement-list -> xml-statement xml-statement-list
> | @
>
> xml-statement -> XML-STARTELM xml-attr-list XML-ENDELM
> | XML-STARTELM xml-attr-list XML-ENDSTARTELMDAT
> | XML-STARTELM xml-attr-list XML-ENDSTARTELM xml-statement-list XML-ENDELM
>
> xml-attr-list -> XML-ATTRIBUTE xml-attr-list
> | @

Das XML-ENDSTARTELMDAT kennzeichnet ein Blatt mit Daten und der CloseTag
(XML-ENDELM) wurde schon mit Weggelesen (um das Ende der Daten zu
bestimmen), sprich es kommt kein XML-ENDELM für ein Blatt sondern nur
wenn es ein XML-ENDSTARTELM ohne Daten, dafür mit weiteren XML-STARTELM (nächste Hierarchiestufe) gegeben hat.

Die optionale "xml-attr-list" könnte man noch eleminieren, indem man sie durch GetAttrCount (FCXGAC oder FCXNEXT gibt im oberen Halbword, den Attribut-Count gleich mit zurück) und weitere Getter (FirstAttr, NextAttr, LastAttr, FindAttr, ...) ersetzt, womit man immer das gesamte XML-Tag als Cursor-Position hätte.

> xml-statement -> XML-ATTRELM
> | XML-DATAELM
> | XML-STARTELM xml-statement-list XML-ENDELM

Da der Open schon das "xml-document" abarbeitet, hätte man so mit 3 Funktionen seinen kompletten XML-Parser fertig.

> int tag;
>
> match(hdl,typ) {
> if (tag==typ) {
> return(FCXNEXT(hdl));
> } else {
> error();
> }
> }
>
> main() {
> hdl=FCXOPEN("read(file='DD:INPUT')","mode.simple()");
> tag=FCXNEXT(hdl);
> xml_statement_list(hdl);
> }
>
> xml_statement_list(hdl) {
> while(tag=XML-ATTRELM || XML-DATAELM || tag==XML-STARTELM) {
> xml_statement(hdl);
> }
> }
>
> xml_statment(hdl) {
> switch(tag) {
> case XML-ATTRELM:
> FCXGKW(hdl,kywlen,kywdat);
> ...
> tag=match(hdl,XML-ATTRELM);
> break;
> case XML-DATAELM:
> FCXGKW(hdl,kywlen,kywdat);
> ...
> tag=match(hdl,XML-DATAELM);
> break;
> case XML_STARTELM:
> FCXGKW(hdl,kywlen,kywdat);
> ...
> tag=match(hdl,XML_STARTELM);
> xml_statement_list(hdl);
> tag=match(hdl,XML_ENDELM);
> break;
> default:
> error();
> break;
> }

Komplex:

Die komplexe Variante unterstützt dann CDATA, Kommentare, Datenteile
überall und auch mehrteilige Datenpasagen (größer 64k) und DTD. Allerding gibt es dann wieder alle Elementtypen und in der Regel kann man sich bis auf die Attribute entweder die KeyWords/Values oder die Daten abholen.

Das Schreiben geht an sich genauso (simple oder complex), nur das man hier mit Settern die Daten an das Handle übergibt und dann mit FCXNEXT() das Rausschreiben bewirkt. Beim Lesen wird es noch das FCXPREV() geben, womit man den Cursor um ein Element zurückbewegen kann.
Revision 2017-05-02 11:52 by Falk Reichbott
Description Mit der Version 5.1.15, welche wir gerade fertig stellen, kommen die
Integer- und Float-Element-Konverter, damit man FL5-XML-Elemente direkt
in Cobol-Zahlen-Datentypen (BCD und BIN) wandeln kann. Dies brauchen wir in de 5.1.16 für den Table-Support, damit sie CSV-Dateien als FB-Record über die Satzschnittstelle zurückbekommen oder auch schreiben können.

Wenn man auf der anderen Seite im XML weiß, dass ein Betrag jetzt
gekommen ist, dann konvertiert man das Attributevalue oder das
Datenelement zu einem BCD oder 2'er-Komplement.

Da das XML-Element ein UTF-8-String ist, muss man also die Zahl von
einer externen Stringdarstellung in die interne neutrale Zahlendarstellung
 (wir nutzen BCD, damit es keinen Genauigkeitsverlust gibt) überführen und von
  dieser in den jeweiligen externen Datentyp, welchen man in seinem COPYBOOK braucht
   (egal, wie die Zahl in dem XML-Dokument gestanden hat).

> "conv.integer(from(format.str(chrset=UTF8)) to(format.bin(width=32)))"

Hierfür haben wir den FROM-TO-Conversion-String (siehe oben und die komplette
Syntax am Ende der Mail) eingeführt und stellen mit der 5.1.15 alle Konvertrierung
 auch explizit über die neue Funktion FCRCONV(hdl,rtc,inlen, indat,outlen, outdat)
  zur Verfügung. Manchmal
weis man beim GET halt noch nicht, welche die richtige implitzite
Konvertierung wäre. In solchen Fällen oder halt immer kann man explizit
konvertieren. Haben Sie hier noch Ideen oder Wünsche.

Jetzt ist noch der Umgang mit unsere FL5-Element-Struktur beim
format.element() an sich zu komplex und man könnte für die Kunden auf
Basis des FLUC-Element-API im Gegensatz zum COBOL XML PARSE (SAX
(Callback/Eventhandler-API)) eine vereinfachte XMLPULL-API anbieten (StAX).

hdl=FCXOPEN(filstr,modstr)
Man gibt beim Open nur den READ.XML-String mit und über den Mode-String
legt man fest, ob man die simple oder die komplexe Varinate und noch so
ein paar Kleinigkeiten (Case-Senitive oder nicht, CCSID im Speicher, Selection (ENUM) für XML-Schlüsselwörter, und vieles mehr) haben will.

vsn=FCXGVSN(hdl)
enc=FCXGENC(hdl)
Nach dem Open kann man die XML-Version und das Encoding abfragen, da der
optionale XML-Tag ggf. schon weggelesen wurde.

R15=FCXNEXT(hdl)
Die Next-Funktion liest das nächste XML-Element und gibt den
Element-Type (Token>0) oder halt einen Fehler (Token<0, kann EOF sein)
zurück (sie stellt den Scanner für die diversen Datenformate (SEPA) in XML dar).

In Abhängigkeit des Typ bzw. Tokens kann man sich nun mit diversen
GET-Funktionen, die jeweiligen Datentypen an dieser Cursor-Position
abholen. Hierbei gibt es für XML-Schlüsselwörter (Tag-Namen und
Attribut-Namen) zwei Varianten. GetKeyWord (FCXGKW) gibt den String zum
Vergleich zurück (Case sensitive oder in Großbuchstaben) oder wenn man
eine Selection im Open definiert hat, dann gibt GetKeyValue (FCXGKV) den
INTEGER (PIC 9(9) COMP) für das Schlüsselwort zurück, sofern es gefunden
wurde (Achtung, bezieht sich auf den Tag- oder Attribut-Namen).

R15=FCXGKW(hdl,kywlen,kyw)
R15=FCXGKV(hdl)

In Abhängigkeit des Types/Token kann man ein XML-Schlüsselwort und oder
XML-Daten abfragen (State-Maschine im Hintergrund zur kontrolle). Zum Beispiel
kann man beim Token XML-ATTRIBUTE sich das KeyWord/Value oder die Daten geben lassen.
Bei der Datenabfrage kann man sich die internen UTF-8-Strings in jegliche Datentypen wandeln
lassen. Für jeden Datentyp gibt es entsprechende GET-Funktionen.

R15=FCXGSV(hdl) - GetSelectionValue
Wandelt auch ein Schlüsselwort (Attributevalue oder Datenteil) in eine
Zahl (Fullword)

R15=FCXGBH(hdl,binlen,bindat) - GetBinHex
Wandelt hexadezimalen String in Binärdaten.

R15=FCXGB6(hdl,binlen,bindat) - GetBinB64
Wandelt Base64 String in Binärdaten (mit oder ohne Armor-Header-Trailer).

R15=FCXGIB(hdl,intlen,intdat) - GetIntBin
Wandelt Zahlenstring in 2'Complement der Längen 1, 2, 4 und 8

R15=FCXGIC(hdl,bcdlen,bcddat) - GetIntBcd
Wandelt Zahlenstring gepackten BCD mit Vorzeichen

R15=FCXGFB(hdl,fltlen,fltdat) - GetFltBin
Wandelt Zahlenstring in binären Float der Längen 4, 8 und 16

R15=FCXGFCxx(hdl,fltlen,fltdat) - GetFltBcd
Wandelt Zahlenstring in BCD Float, wobei xx für die Nachkommastellen
steht und die fltlen die führenden Nullen ergibt

R15=FCXGSC(hdl,strlen,strdat) - GetStrClp (Collapsed)
Gibt String collapsed zurück

R15=FCXGSB(hdl,strlen,strdat) - GetStrBth (Both)
Gibt String ohne Trailing and leading Whitespace zurück

R15=FCXGDAT(hdl,datlen,data) - GatData
Gibt die Daten unverändert (UTF-8) zurück.

Da wird es noch einiges mehr an Funktionen geben, hier nur mal die
Wichtigsten, um das Prizip zu veranschaulichen.

Nun noch zu den Varianten:

Simple:

Hier gibt es die folgenden XML-Typen/Token, DTD, Processing-Instructions und Kommentare werden
überlesen. CDATA wird nicht akzeptiert. Datenteile dürfen eine
Stringlänge von 64k nicht übersteigen (kann im Open verkleinert oder bis
zu 1GiB vergrößert werden). Datenteile sind nur in den Blättern möglich.
Datenteile einfach zwischen drin, dürfen nur Whitespace enthalten und
werden genauso wie Default-Elemente überlesen. Sprich eine klassische
XML-Datei ohne Spakazien (ggf. kann Simple auch CDATA, aber da CDATA
auch Datenteile unterbrechen kann, passt dies nicht wirklich, man könnte an sich nur XML_ENDSTARTELMCDATA noch einführen, sprich ein ganzes Datenelement muss CDATA sein.)

> XML-STARTELM hier geht kann man sich nur das Key-Word/Value holen
> XML-ATTRIBUTE hier kann man sich Key-Word/Value und die Daten holen
> XML-ENDSTARTELM hier kommen keine Daten und man kann sich nur das KeyWord/Value holen
> XML-ENDSTARTELMDATA hier kann man sich die Daten und das KeyWord/Value holen
> XML-ENDELM hier kann man sich nur das KeyWord/Value holen

Das XML-Dokument darf bei der simplen Variante nur folgende Syntax haben (bitte beachten, dass DTD, Default-Elemente, leere Datenelemente und Kommentar überlesen werden).

> xml-document -> XML-TAG xml-statement-list
> | xml-statement-list
>
> xml-statement-list -> xml-statement xml-statement-list
> | @
>
> xml-statement -> XML-STARTELM xml-attr-list XML-ENDELM
> | XML-STARTELM xml-attr-list XML-ENDSTARTELMDAT
> | XML-STARTELM xml-attr-list XML-ENDSTARTELM xml-statement-list XML-ENDELM
>
> xml-attr-list -> XML-ATTRIBUTE xml-attr-list
> | @

Das XML-ENDSTARTELMDAT kennzeichnet ein Blatt mit Daten und der CloseTag
(XML-ENDELM) wurde schon mit Weggelesen (um das Ende der Daten zu
bestimmen), sprich es kommt kein XML-ENDELM für ein Blatt sondern nur
wenn es ein XML-ENDSTARTELM ohne Daten, dafür mit weiteren XML-STARTELM (nächste Hierarchiestufe) gegeben hat.

Die optionale "xml-attr-list" könnte man noch eleminieren, indem man sie durch
 GetAttrCount (FCXGAC oder FCXNEXT gibt im oberen Halbword, den Attribut-Count
  gleich mit zurück) und weitere Getter (FirstAttr, NextAttr, LastAttr, FindAttr, ...)
   ersetzt, womit man immer das gesamte XML-Tag als Cursor-Position hätte.

> xml-statement -> XML-ATTRELM
> | XML-DATAELM
> | XML-CDATAELM
> | XML-STARTELM xml-statement-list XML-ENDELM

Da der Open schon das "xml-document" abarbeitet, hätte man so mit 3 Funktionen seinen kompletten XML-Parser fertig.

> int tag;
>
> match(hdl,typ) {
> if (tag==typ) {
> return(FCXNEXT(hdl));
> } else {
> error(syntax);
> }
> }
>
> main() {
> hdl=FCXOPEN("read(file='DD:INPUT')","mode.simple()");
> tag=FCXNEXT(hdl);
> xml_statement_list(hdl);
> }
>
> xml_statement_list(hdl) {
> while(tag=XML-ATTRELM || XML-DATAELM || tag==XML-STARTELM) {
> xml_statement(hdl);
> }
> }
>
> xml_statment(hdl) {
> switch(tag) {
> case XML-ATTRELM:
> FCXGKW(hdl,kywlen,kywdat);
> ...
> tag=match(hdl,XML-ATTRELM);
> break;
> case XML-DATAELM:
> FCXGKW(hdl,kywlen,kywdat);
> ...
> tag=match(hdl,XML-DATAELM);
> break;
> case XML_STARTELM:
> FCXGKW(hdl,kywlen,kywdat);
> ...
> tag=match(hdl,XML_STARTELM);
> xml_statement_list(hdl);
> tag=match(hdl,XML_ENDELM);
> break;
> default:
> error();
> break;
> }

Komplex (ohne DTD, müsste aber dabei sein):

> xml-document -> XML-TAG xml-statement-list
> | xml-statement-list
>
> xml-statement-list -> xml-statement xml-statement-list
> | @
>
> xml-statement -> XML-STARTELM xml-list XML-ENDELM
> | XML-COMMENT
>
> xml-list -> xml-element xml-list
> | @
>
> xml-element -> xml-statement
> | xml-cdata-statement
> | XML-DATA
> | XML-PROCINS
> | XML-DEFAULTS
>
> xml-cdata-statement -> XML-START-CD xml-data-list XML-END-CD
>
> xml-data-list -> XML-DATA xml-data-list
> | @

Die komplexe Variante unterstützt dann CDATA, Kommentare, Datenteile
überall und auch mehrteilige Datenpasagen (größer 64k) und DTD. Allerding gibt es dann wieder alle Elementtypen und in der Regel kann man sich bis auf die Attribute entweder die KeyWords/Values oder die Daten abholen.

Das Schreiben geht an sich genauso (simple oder complex), nur das man hier mit Settern
 die Daten an das Handle übergibt und dann mit FCXNEXT() das Rausschreiben bewirkt. Beim
  Lesen wird es noch das FCXPREV() geben, womit man den Cursor um ein Element zurückbewegen
   kann.


Copyright © 2000 - 2024 MantisBT Team
Powered by Mantis Bugtracker