/* XMLparser.p
Dmitri Levin 07/31/2001
*/

DEFINE VARIABLE iLevel AS INTEGER NO-UNDO.
DEFINE VARIABLE Parentname AS CHARACTER NO-UNDO.

DEFINE TEMP-TABLE nodes NO-UNDO
  FIELD NAME AS CHARACTER
  FIELD nodevalue AS CHARACTER
  FIELD PARENT AS CHARACTER
  FIELD level AS INTEGER
  .

RUN ProcessXML( INPUT "C:\dmitri\useful\XML\cust.xml":U ).

RUN ShowAll.
RUN ShowDataOnly.

PROCEDURE ProcessXML:
  DEFINE INPUT PARAMETER XMLfilename AS CHARACTER NO-UNDO.

  DEFINE VARIABLE hXML AS HANDLE NO-UNDO.
  DEFINE VARIABLE hRoot AS HANDLE NO-UNDO.

EMPTY TEMP-TABLE nodes.

  CREATE X-DOCUMENT hXML.
  CREATE X-NODEREF hRoot.

  hXML:LOAD('FILE':U, XMLfilename , FALSE).

  /*Get the root element handle*/
  hXML:GET-DOCUMENT-ELEMENT(hRoot).

  Parentname = "ROOT".
  RUN process-children( INPUT hRoot ).

  DELETE OBJECT hXML.
  DELETE OBJECT hRoot.
END. /* processXML */

PROCEDURE process-children:
  DEFINE INPUT PARAMETER hParent AS HANDLE NO-UNDO.

  DEFINE VARIABLE hChild AS HANDLE NO-UNDO.
  DEFINE VARIABLE i AS INTEGER NO-UNDO.

  iLevel = iLevel + 1.

  CREATE X-NODEREF hChild.

  CREATE nodes.
  ASSIGN
   nodes.NAME = hParent:NAME
   nodes.PARENT = Parentname
   nodes.level = iLevel.

  RUN processAttributes( INPUT hParent ).

  DO i = 1 TO hParent:NUM-CHILDREN :
   hParent:GET-CHILD(hChild,i).
   IF hChild:NAME = "#text" THEN DO:
    ASSIGN
     nodes.nodevalue = hChild:NODE-VALUE.
   END.
   ELSE DO:
    parentname = hParent:NAME.
    RUN process-children( INPUT hChild ).
   END.
  END.

  iLevel = iLevel - 1.
  DELETE OBJECT hChild.
END. /* process-child */

PROCEDURE processAttributes:
  DEFINE INPUT PARAMETER hParent AS HANDLE NO-UNDO.

  DEFINE VARIABLE cAttribute AS CHARACTER NO-UNDO.
  DEFINE VARIABLE i AS INTEGER NO-UNDO.
  DEFINE BUFFER nodes FOR nodes.

  DO i = 1 TO NUM-ENTRIES(hParent:ATTRIBUTE-NAMES) TRANSACTION:
   cAttribute = entry(i,hParent:ATTRIBUTE-NAMES).
   CREATE nodes.
   ASSIGN
    nodes.NAME = cAttribute
    nodes.PARENT = hParent:NAME
    nodes.nodevalue = hParent:GET-ATTRIBUTE(cAttribute)
    nodes.level = iLevel + 1.
  END.
END. /* processAttributes */

PROCEDURE ShowAll:
  FOR EACH nodes:
   DISPLAY
    FILL(" ", nodes.level) + nodes.NAME FORMAT "x(40)"
    trim(nodes.nodevalue) FORMAT "x(20)" NO-LABEL
    WITH TITLE "All Nodes in XML file".
  END.
END. /* showall */

PROCEDURE ShowDataOnly:
  FOR EACH nodes WHERE TRIM(nodes.nodevalue) <> "":
   DISPLAY
    nodes.PARENT + " " + nodes.NAME FORMAT "x(40)"
    trim(nodes.nodevalue) FORMAT "x(20)" NO-LABEL
    WITH TITLE "XML Data Only".
  END.
END. /* showDataOnly */
1