tt to XML and array attributes

m.hansler

New Member
Hello everyone,

I'm stuck with generating an xml file from a temp-table for third party software. In particular the array fields that are in the temp-table. Examples that I found don't really help me much because in those examples every extent in an array gets it's own node and I need an array to be an attribute of another corresponding array.

For example:
Code:
DEF TEMP-TABLE DebtorList
    FIELD debtor_number AS CHAR FORMAT "x(24)"
    FIELD name          AS CHAR FORMAT "x(100)"
    FIELD search_code   AS CHAR FORMAT "x(20)"
    FIELD currency      AS CHAR FORMAT "x(3)"
    FIELD credit_limit  AS DEC  FORMAT ">>>>>>>>>>>>>>>>>9"
    FIELD interest_rate AS DEC  FORMAT ">>>>9" INITIAL 700
    FIELD registration_number AS CHAR FORMAT "x(50)"
    FIELD userfield     AS CHAR FORMAT "x(100)" EXTENT 5
    FIELD usrfielddt    AS CHAR                 EXTENT 5
    INDEX debtor_number IS PRIMARY debtor_number ASCENDING.

Where 'userfield' has a free to define fieldvalue and the corresponding extentID from 'usrfielddt' defines the datatype of that value (string, integer, decimal).

A record of one debtor should look like this:
Code:
   <debtor>
      <debtor_number>001234</debtor_number>
      <search_code>DOE</search_code>
      <name>John Doe Inc.</name>
      <credit_limit currency='EUR'>12000</credit_limit>
      <interest_rate>7</interest_rate>
      <registration_number>0123456789</registration_number>
      <userfield id='1' datatype='decimal'>15000</userfield>
      <userfield id='2' datatype='string'>P00009</userfield>
   </debtor>

The normal fields are set in the XML file without a problem, but I can't figure out a way to get the correct result with the array fields.

Here is the code I have (Note: the output of the array fields is not correct, I know):

Code:
RUN CreateXML.
 
DEFINE VARIABLE hDoc AS HANDLE NO-UNDO.
DEFINE VARIABLE hRoot AS HANDLE NO-UNDO.
DEFINE VARIABLE hRow AS HANDLE NO-UNDO.
DEFINE VARIABLE hField AS HANDLE NO-UNDO.
DEFINE VARIABLE hText AS HANDLE NO-UNDO.
DEFINE VARIABLE hBuffer AS HANDLE NO-UNDO.
DEFINE VARIABLE hDBFld AS HANDLE NO-UNDO.
DEFINE VARIABLE iNumFields AS INTEGER NO-UNDO.
DEFINE VARIABLE iExtents AS INTEGER NO-UNDO.
/* ================================== */
/* -          DATA TO XML         - */
/* ================================== */
PROCEDURE CreateXML:
/* Create the objects we need. */
CREATE X-DOCUMENT hDoc.
CREATE X-NODEREF hRoot.
CREATE X-NODEREF hRow.
CREATE X-NODEREF hField.
CREATE X-NODEREF hText.
/* Get a buffer for the Customer table. */
hBuffer = BUFFER DebtorList:HANDLE.
/* Set up a root node. */
hDoc:CREATE-NODE (hRoot, "debtors", "ELEMENT").
hDoc:APPEND-CHILD (hRoot).
/* Set up the attributes of the root node */
hRoot:SET-ATTRIBUTE ("xmlns:xsi", "'http://www.w3.org/2001/XMLSchema-instance'").
hRoot:SET-ATTRIBUTE ("xsi:noNamespaceSchemaLocation", "'debtors.xsd'").
FOR EACH DebtorList:
    /* Create a customer row node. */
    hDoc:CREATE-NODE (hRow, "debtor", "ELEMENT").
    hRoot:APPEND-CHILD (hRow).
    /* Add the other fields as elements. */
    REPEAT iNumFields = 1 TO hBuffer:NUM-FIELDS:
        hDBFld = hBuffer:BUFFER-FIELD (iNumFields).
 
       IF (hDBFld:NAME = "userfield" OR hDBFld:NAME = "usrfielddt") THEN
       DO:
          REPEAT iExtents = 1 TO hDBFld:EXTENT:
            IF hDBFld:NAME = "userfield" THEN
                hDoc:CREATE-NODE (hField, hDBFld:NAME, "ELEMENT").
            hField:SET-ATTRIBUTE("id":U, STRING(iExtents)).
            hField:SET-ATTRIBUTE("datatype":U, hDBFld:BUFFER-VALUE(iExtents)).
            hRow:APPEND-CHILD (hField).
        hDoc:CREATE-NODE (hText, "", "TEXT").
        /* Node to hold value. */
        hField:APPEND-CHILD (hText).
        /* Attach text to field */
        hText:NODE-VALUE = STRING(hDBFld:BUFFER-VALUE(iExtents)).
          END.
          NEXT.
       END.

       /* Create an element with the field name as the tag.*/
        hDoc:CREATE-NODE (hField, hDBFld:NAME, "ELEMENT").
        hRow:APPEND-CHILD (hField).
        /* Make new field next row child. */
        hDoc:CREATE-NODE (hText, "", "TEXT").
        /* Node to hold value. */
        hField:APPEND-CHILD (hText).
        /* Attach text to field */
        hText:NODE-VALUE = STRING (hDBFld:BUFFER-VALUE).
    END. /* REPEAT iNumFields = 1 TO hBuffer:NUM-FIELDS: */
END. /* FOR EACH */
/* Write the XML node tree to an xml file. */
hDoc:SAVE ("file", "z:\cust.xml").
 
/* Delete the objects. Note that deleting the document
   object deletes the DOM structure under it also. */
DELETE OBJECT hDoc.
DELETE OBJECT hRoot.
DELETE OBJECT hRow.
DELETE OBJECT hField.
DELETE OBJECT hText.
END PROCEDURE.

The output I get is as follows:
Code:
[FONT=Verdana][COLOR=#000000]  <?xml version="1.0" encoding="UTF-8" ?> 
  <debtors xmlns:xsi="'http://www.w3.org/2001/XMLSchema-instance'" xsi:noNamespaceSchemaLocation="'debtors.xsd'">
  <debtor>
  <debtor_number>001234</debtor_number> 
  <name>John Doe Inc.</name> 
  <search_code>DOE</search_code> 
  <currency>EUR</currency> 
  <credit_limit>12000</credit_limit> 
  <interest_rate>7</interest_rate> 
  <registration_number>0123456789</registration_number> 
  <userfield id="1" datatype="0">15000</userfield> 
  <userfield id="2" datatype="P00009">P00009</userfield> 
  <userfield id="3" datatype="" /> 
  <userfield id="4" datatype="" /> 
  <userfield id="5" datatype="">stringstring</userfield> 
  </debtor>
  </debtors>[/COLOR][/FONT]
[COLOR=#0000ff][/COLOR]

Can someone give me some pointers or direct links to some good sources?
 
Here is some code to export data to XML, taking extents into account. Use proprocessors to change the tablename.



/* *************************** Definitions ************************** */
/* Writing to XML */
&GLOBAL-DEFINE TableName Salesrep
&GLOBAL-DEFINE WhereClause WHERE TRUE
&GLOBAL-DEFINE Attributes
&GLOBAL-DEFINE Attrib1
&GLOBAL-DEFINE Attrib2
&GLOBAL-DEFINE Save2File z:\salesrep.xml

DEFINE VARIABLE hDoc AS HANDLE NO-UNDO.
DEFINE VARIABLE hRoot AS HANDLE NO-UNDO.
DEFINE VARIABLE hRow AS HANDLE NO-UNDO.
DEFINE VARIABLE hField AS HANDLE NO-UNDO.
DEFINE VARIABLE hExtent AS HANDLE NO-UNDO.
DEFINE VARIABLE hText AS HANDLE NO-UNDO.
DEFINE VARIABLE hBuf AS HANDLE NO-UNDO.
DEFINE VARIABLE hDBFld AS HANDLE NO-UNDO.
DEFINE VARIABLE lcElemExt AS CHARACTER NO-UNDO.
DEFINE VARIABLE liCnt AS INTEGER NO-UNDO.
DEFINE VARIABLE liCntExt AS INTEGER NO-UNDO.
/* *************************** Main Block *************************** */
RUN ipCreateHandles.
hbuf = BUFFER {&TableName}:HANDLE.
/* Set up a root node */
RUN ipRootNode.
RUN ipMainLoop.
hDoc:SAVE("file","{&Save2File}").
RUN ipCLeanUp.
/* ************ Internal Procedures *************** */
PROCEDURE ipCreateHandles:
CREATE X-DOCUMENT hDoc.
CREATE X-NODEREF hRoot.
CREATE X-NODEREF hRow.
CREATE X-NODEREF hField.
CREATE X-NODEREF hExtent.
CREATE X-NODEREF hText.
END.
PROCEDURE ipRootNode:
/*------------------------------------------------------------------------------
Purpose: Set up a root node. Always needed.
Parameters: <none>
Notes:
------------------------------------------------------------------------------*/
hDoc:CREATE-NODE(hRoot,"{&TableName}s","ELEMENT").
hDoc:APPEND-CHILD(hroot).
END.
PROCEDURE ipMainLoop:
blMain:
FOR EACH {&TableName} NO-LOCK
{&WhereClause}
:
hdoc:CREATE-NODE(hRow,"{&TableName}","ELEMENT"). /* Create Row-node */
hRoot:APPEND-CHILD(hRow). /* put row in the tree */
/{&Attributes}*/
hRow:SET-ATTRIBUTE("{&Attrib1}", STRING({&TableName}.{&Attrib1}) ).
hRow:SET-ATTRIBUTE("{&Attrib2}", STRING({&TableName}.{&Attrib2}) ).
/{&Attributes}*/
/* Add other fields as tags in the XML */
REPEAT licnt = 1 TO hBuf:NUM-FIELDS
:
hDBFld = hBuf:BUFFER-FIELD(licnt).
/{&Attributes}*/
IF hDBFld:NAME = "{&Attrib1}"
OR hDBFld:NAME = "{&Attrib2}"
THEN NEXT.
/{&Attributes}*/
/* Create a tag with fieldname */
hDoc:CREATE-NODE(hField,hDBFld:NAME,"ELEMENT").
hRow:APPEND-CHILD(hField). /* put new field as next child of row */
IF hDBFld:EXTENT GT 0 THEN
DO liCntExt = 1 TO hDBFld:EXTENT:
ASSIGN
lcElemExt = hDBFld:NAME + STRING(liCntExt).
/* Create a tag with fieldname + extent */
hDoc:CREATE-NODE(hExtent,lcElemExt,"ELEMENT").
hField:APPEND-CHILD(hExtent). /* put new field as next child of row */
/* Node to hold the field value */
hDoc:CREATE-NODE(hText,"","TEXT").
hExtent:APPEND-CHILD(hText). /* Add node to hold the extent value */
hText:NODE-VALUE = STRING(hDBFld:BUFFER-VALUE(licntExt)).
END.
ELSE DO:
/* Node to hold the field value */
hDoc:CREATE-NODE(hText,"","TEXT").
hfield:APPEND-CHILD(hText). /* Add node to hold the field value */
hText:NODE-VALUE = STRING(hDBFld:BUFFER-VALUE).
END.
END. /* Repeat */
END.
END PROCEDURE. /* ipMainloop */
PROCEDURE ipCleanUp:
/* Delete the mess */
DELETE OBJECT hDoc.
DELETE OBJECT hRoot.
DELETE OBJECT hRow.
DELETE OBJECT hField.
DELETE OBJECT hExtent.
DELETE OBJECT hText.
END.


The result:


<?xml version="1.0" ?>
- <Salesreps>
- <Salesrep>
<Sales-Rep>BBB</Sales-Rep>

<Rep-Name>Brawn , Bubba B.</Rep-Name>

<Region>East</Region>

- <Month-Quota>
<Month-Quota1>1600</Month-Quota1>

<Month-Quota2>1648</Month-Quota2>

<Month-Quota3>1697</Month-Quota3>

<Month-Quota4>1748</Month-Quota4>

<Month-Quota5>1800</Month-Quota5>

<Month-Quota6>1854</Month-Quota6>

<Month-Quota7>1910</Month-Quota7>

<Month-Quota8>1967</Month-Quota8>

<Month-Quota9>2026</Month-Quota9>

<Month-Quota10>2087</Month-Quota10>

<Month-Quota11>2150</Month-Quota11>

<Month-Quota12>2215</Month-Quota12>

</Month-Quota>


</Salesrep>


- <Salesrep>
<Sales-Rep>DKP</Sales-Rep>

<Rep-Name>Pitt , Dirk K.</Rep-Name>

<Region>Central</Region>

- <Month-Quota>
<Month-Quota1>1800</Month-Quota1>

<Month-Quota2>1854</Month-Quota2>

<Month-Quota3>1910</Month-Quota3>

<Month-Quota4>1967</Month-Quota4>

<Month-Quota5>2026</Month-Quota5>

<Month-Quota6>2087</Month-Quota6>

<Month-Quota7>2150</Month-Quota7>

<Month-Quota8>2215</Month-Quota8>

<Month-Quota9>2281</Month-Quota9>

<Month-Quota10>2349</Month-Quota10>

<Month-Quota11>2419</Month-Quota11>

<Month-Quota12>2492</Month-Quota12>

</Month-Quota>


</Salesrep>




......
 
Back
Top