Programmierung

XML-Verarbeitung

Immer mehr Applikationen setzen auf XML als Format für die Übertragung und Speicherung von Daten. Nicht zuletzt in den Bereichen SOA und Web-Services spielt XML eine große Rolle. Heute möchte ich Ihnen zeigen, wie Sie das XML-Fomat mit CONZEPT 16 verarbeiten können.

Die Verarbeitung von XML innerhalb von CONZEPT 16 wird über zwei Funktionen realisiert:

XML-Daten schreiben/speichern

Mit der Funktion XMLSave() können Sie Daten über einen Cte-Knoten in ein XML-Dokument schreiben.

XMLSave(
  CteNodeXMLDoc     : handle;  // Cte-Struktur mit XML-Daten
  File              : alpha;   // Datei für XML-Dokument
  opt Options       : int;     // Optionen
  opt Mem           : handle;  // Speicherblock für XML-Dokum.
  opt CharsetTarget : int;     // Zielzeichensatz
  opt CharsetSource : int;     // Quellzeichensatz
) : int                        // Fehler

Die Funktion erwartet einen Cte-Knoten als Quellobjekt für die XML-Daten. Als Zielobjekt kann entweder eine Datei oder ein Memory-Objekt angegeben werden, in die das XML-Dokument gespeichert wird. Für die Konvertierung zwischen verschiedenen Zeichensätzen können außerdem Ziel- und Quellzeichensatz angegeben werden.

Das XML-Dokument wird über die Eigenschaften und die Struktur der Cte-Knoten definiert:

  • Die Eigenschaft spName bestimmt den Namen eines Elementes oder eines Attributes.
  • Die Eigenschaft spID bestimmt den Typ eines Knotens. Mögliche Werte sind:
    • _XMLNodeDocument – Dokument
    • _XMLNodeElement – Element
    • _XMLNodeAttribute – Attribut
    • _XMLNodeComment – Kommentar
    • _XMLNodeText – Text
    • _XMLNodeCDATA – CDATA-Segment
  • Die Eigenschaft spValueAlpha bestimmt den Wert beziehungsweise Inhalt eines Attributes, Textes, Kommentars oder eines CDATA-Segments.

Nach Aufruf der Funktion wurden bei Erfolg die XML-Daten aus der Cte-Struktur in das XML-Dokument geschrieben. Im Fehlerfall kann über den Rückgabewert der Funktion die Fehlerursache ermittelt werden.

Beispiel:
sub XMLSaveToFile
()

  local
  {
    tCteNodeXMLDoc      : handle;
    tCteNodeXMLItemRoot : handle;
    tCteNodeXMLItem     : handle;
    tErr                : int;
  }

{
  // XML-Dokument als Cte-Knoten anlegen
  tCteNodeXMLDoc # CteOpen(_CteNode);

  // Cte-Knoten als XML-Dokument deklarieren
  tCteNodeXMLDoc->spID # _XMLNodeDocument;

  // Standalone-Dokumentdeklaration
  tCteNodeXMLDoc->CteInsertNode(
    'standalone', _XMLNodeAttribute, 'yes', _CteAttrib);

  // Element (Wurzel)
  tCteNodeXMLItemRoot # tCteNodeXMLDoc->CteInsertNode(
    'root', _XMLNodeElement, NULL);

  // Element
  tCteNodeXMLItem # tCteNodeXMLItemRoot->CteInsertNode(
    'element', _XMLNodeElement, NULL);

  // Attribut
  tCteNodeXMLItem->CteInsertNode(
    'attribute',_XMLNodeAttribute, 'attrib-value', _CteAttrib);

  // Kommentar
  tCteNodeXMLItemRoot->CteInsertNode(
    '', _XMLNodeComment, 'comment');

  // Text
  tCteNodeXMLItemRoot->CteInsertNode(
    '', _XMLNodeText, 'text');

  // CDATA
  tCteNodeXMLItemRoot->CteInsertNode(
    '', _XMLNodeCDATA, 'CDATA');

  tErr # tCteNodeXMLDoc->XMLSave('C:\XML-UTF8.xml',
    _XMLSaveDefault, 0, _CharsetUTF8);

  // Cte-Knoten leeren freigeben
  tCteNodeXMLDoc->CteClear(true);
  tCteNodeXMLDoc->CteClose();

  // Fehler bei XMLSave()
  if (tErr != _ErrOK)
  {
    // ...
  }
}

Nach dem Aufruf dieser Funktion enhält die Datei XML-UTF8.xml folgenden Inhalt:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<root>
  <element attribute="attrib-value"/>
  <!--comment-->
  text
  <![CDATA[CDATA]]>
</root>

Wird die Option _XMLSaveDefault durch die Option _XMLSavePure ersetzt, werden keine Leerzeichen und Zeilenumbrüche geschrieben und das Ergebnis sieht wie folgt aus:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?><root> ¬
<element attribute="attrib-value"/><!--comment-->text<![CDATA[ ¬
CDATA]]></root>
XML-Daten lesen/laden

Mit der Funktion XMLLoad() könnn Sie Daten aus einem XML-Dokument in ein Cte-Knoten laden und anschließend weiterverarbeiten.

XMLLoad(
  CteNodeXMLDoc  : handle;  // Cte-Knoten für XML-Daten
  File           : alpha;   // XML-Dokument als Datei
  opt Options    : int;     // Optionen
  opt Mem        : handle;  // XML-Dokum. als Speicherblock
  opt FileSchema : alpha;   // XML-Schema als Datei
  opt MemSchema  : handle;  // XML-Schema als Speicherblock
) : int                     // Fehler

Die Funktion erwartet einen Cte-Knoten als Zielobjekt für die XML-Daten. Als Quellobjekt kann entweder eine Datei oder ein Memory-Objekt angegeben werden, in dem das XML-Dokument vorliegt. Zusätzlich zum XML-Dokument kann ein XML-Schema angegeben werden, gegen das das XML-Dokument geprüft wird.
Nach Aufruf der Funktion wurden bei Erfolg die XML-Daten aus dem XML-Dokument in die Cte-Struktur gelesen und können anschließend weiterverarbeitet werden. Im Fehlerfall kann über den Rückgabewert der Funktion und über die Funktion XMLError() die Fehlerursache ermittelt werden.

Beispiel:
sub XMLLoadFromFile
()

  local
  {
    tCteNodeXMLDoc      : handle;
    tCteNodeXMLAttr     : handle;
    tCteNodeXMLItemRoot : handle;
    tCteNodeXMLNode     : handle;
    tErr                : int;
    tName               : alpha(4096);
    tValue              : alpha(4096);
  }

{
  tCteNodeXMLDoc # CteOpen(_CteNode);

  tErr # tCteNodeXMLDoc->XMLLoad('C:\XML-UTF8.xml');
  if (tErr = _ErrOK)
  {
    // Standalone-Dokumentdeklaration ermitteln
    tCteNodeXMLAttr # tCteNodeXMLDoc->CteRead(
      _CteAttribTree | _CteCmpE, 0, 'standalone');
    if (tCteNodeXMLAttr > 0 and
      tCteNodeXMLAttr->spValueAlpha =^ 'yes')
    {
      // ...
    }

    // Element (Wurzel) ermitteln
    tCteNodeXMLItemRoot # tCteNodeXMLDoc->CteRead(
      _CteChildList | _CteFirst);
    if (tCteNodeXMLItemRoot > 0)
    {
      for   tCteNodeXMLNode # tCteNodeXMLItemRoot->CteRead(
        _CteChildList | _CteFirst);
      loop  tCteNodeXMLNode # tCteNodeXMLItemRoot->CteRead(
        _CteChildList | _CteNext, tCteNodeXMLNode);
      while (tCteNodeXMLNode > 0)
      {
        switch (tCteNodeXMLNode->spID)
        {
          // Element
          case _XMLNodeElement :
          {
            for   tCteNodeXMLAttr # tCteNodeXMLNode->CteRead(
              _CteAttribList | _CteFirst);
            loop  tCteNodeXMLAttr # tCteNodeXMLNode->CteRead(
              _CteAttribList | _CteNext, tCteNodeXMLAttr);
            while (tCteNodeXMLAttr > 0)
            {
              // Attributname ermitteln
              tName # tCteNodeXMLAttr->spName;
              // Attributwert ermitteln
              tValue # tCteNodeXMLAttr->spValueAlpha;
            }
          }
          // Kommentar
          case _XMLNodeComment :
          {
            // Kommentar ermitteln
            tValue # tCteNodeXMLNode->spValueAlpha;
          }
          // Text
          case _XMLNodeText    :
          {
            // Text ermitteln
            tValue # tCteNodeXMLNode->spValueAlpha;
          }
          // CDATA
          case _XMLNodeCDATA   :
          {
            // CDATA-Segment ermitteln
            tValue # tCteNodeXMLNode->spValueAlpha;
          }
        }
      }
    }
  }

  tCteNodeXMLDoc->CteClear(true);
  tCteNodeXMLDoc->CteClose();

  // Fehler bei XMLLoad()
  if (tErr != _ErrOK)
  {
    // XML-Fehler
    if (tErr <= _ErrXMLWarning and tErr >= _ErrXMLFatal)
    {
      WinDialogBox(0,
        'Fehler beim Laden von XML-Daten',
        XMLError(_XMLErrorText) + ' ' +
        '(Fehler ' + XMLError(_XMLErrorCode) + ') ' +
        'Zeile: ' + XMLError(_XMLErrorLine) + ' ' +
        'Spalte: ' + XMLError(_XMLErrorColumn),
        _WinIcoError,
        _WinDialogOK,
        1
      );
    }
  }
}
Keine Kommentare

Kommentar abgeben