2

When I execute the following code to read a XML file in progress language, I need only 3 items from that XML file but this code can not read it.

The code is:

DEFINE VARIABLE hDoc   AS HANDLE  NO-UNDO.
DEFINE VARIABLE hRoot  AS HANDLE  NO-UNDO.
DEFINE VARIABLE hTable AS HANDLE  NO-UNDO.
DEFINE VARIABLE hField 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 ix     AS INTEGER NO-UNDO.
DEFINE VARIABLE jx     AS INTEGER NO-UNDO.
DEFINE VARIABLE returnCode AS DECIMAL   NO-UNDO.
DEFINE VARIABLE returnMessage AS CHARACTER   NO-UNDO.
DEFINE VARIABLE bravoId AS CHAR   NO-UNDO.

CREATE X-DOCUMENT hDoc.
CREATE X-NODEREF hRoot.
CREATE X-NODEREF hTable.
CREATE X-NODEREF hField.
CREATE X-NODEREF hText.


/* Read in the file created in i-outcus.p */
hDoc:LOAD("file", "C:\user53.xml", TRUE).
hDoc:GET-DOCUMENT-ELEMENT(hRoot).

REPEAT ix = 1 TO hRoot:NUM-CHILDREN:
  hRoot:GET-CHILD(hTable, ix).

  /* Get the fields given as attributes */

  string(returnCode)    = hTable:GET-NODE("returnCode").
  returnMessage = hTable:GET-NODE("returnMessage").
  bravoId       = hTable:GET-NODE("Id").
REPEAT jx = 1 TO hTable:NUM-CHILDREN:
    hTable:GET-CHILD(hField, jx).                              
    hField:GET-CHILD(hText, 1).
 hDBFld:BUFFER-VALUE = hTEXT:NODE-VALUE.
  END.
END.

DELETE OBJECT hDoc.
DELETE OBJECT hRoot.
DELETE OBJECT hTable.
DELETE OBJECT hField.
DELETE OBJECT hText.

FOR EACH v:
  DISPLAY ' ReturnCode: ' + STRING(returnCode) + ' - ReturnMessage: ' + returnMessage + ' id: ' + id.
END.

The XML file:

<?xml version="1.0" encoding="utf-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
  <soapenv:Body>
    <ns1:ImportProfilesResponse xmlns:ns1="http://host.bs.com/common/webservice/ProfileManagement/">
      <returnCode>-996</returnCode>
      <returnMessage>Invalid SOAP Request Object - 112(FISCAL_CODE);</returnMessage>
      <id>0000</id>
    </ns1:ImportProfilesResponse>
  </soapenv:Body>
</soapenv:Envelope>
gre_gor
  • 6,669
  • 9
  • 47
  • 52

2 Answers2

4

There are different ways to do this. Perhaps you could define a dataset with temp-tables and simply read the data into that.

Keeping parts of your solution this is what I ended up with. It could also be done recursively (walking the xml).

Basically what you need to do is traverse the xml and when you hit the correct node you step down one more level etc. Also you need to understand that the value of a node actually is a node in itself.

DEFINE VARIABLE hDoc   AS HANDLE  NO-UNDO.
DEFINE VARIABLE hRoot  AS HANDLE  NO-UNDO.
DEFINE VARIABLE hTable AS HANDLE  NO-UNDO.
DEFINE VARIABLE hField AS HANDLE  NO-UNDO.
DEFINE VARIABLE hText  AS HANDLE  NO-UNDO.
DEFINE VARIABLE hValue AS HANDLE NO-UNDO.
DEFINE VARIABLE ix     AS INTEGER NO-UNDO.
DEFINE VARIABLE jx     AS INTEGER NO-UNDO.
DEFINE VARIABLE kx     AS INTEGER NO-UNDO.

DEFINE VARIABLE returnCode    AS DECIMAL    NO-UNDO.
DEFINE VARIABLE returnMessage AS CHARACTER  NO-UNDO.
DEFINE VARIABLE bravoId       AS CHAR       NO-UNDO.

CREATE X-DOCUMENT hDoc.
CREATE X-NODEREF hRoot.
CREATE X-NODEREF hTable.
CREATE X-NODEREF hField.
CREATE X-NODEREF hText.
CREATE X-NODEREF hValue.

/* Read in the file created in i-outcus.p */
hDoc:LOAD("file", "C:\temp\user53.xml", FALSE).
hDoc:GET-DOCUMENT-ELEMENT(hRoot).

REPEAT ix = 1 TO hRoot:NUM-CHILDREN:
    hRoot:GET-CHILD(hTable, ix).

    IF hTable:NAME = "soapEnv:body" THEN DO:

        REPEAT jx = 1 TO hTable:NUM-CHILDREN:
            hTable:GET-CHILD(hField, jx).

            IF hField:NAME = "ns1:ImportProfilesResponse" THEN DO:
                REPEAT kx = 1 TO hFIeld:NUM-CHILDREN:
                    hField:GET-CHILD(hText, kx).

                    IF hText:NUM-CHILDREN = 1 THEN DO:
                        hText:GET-CHILD(hValue, 1).

                        IF hText:NAME = "returnCode" THEN DO:
                            returnCode = DECIMAL(hValue:NODE-VALUE) NO-ERROR.        
                        END.
                        ELSE IF hText:NAME = "returnMessage" THEN DO:
                            returnMessage = hValue:NODE-VALUE. 
                        END.
                        ELSE IF hText:NAME = "id" THEN DO:
                            bravoId = hValue:NODE-VALUE.
                        END. 
                    END.
                END.    
            END.
        END.
    END.
END.

DELETE OBJECT hDoc.
DELETE OBJECT hRoot.
DELETE OBJECT hTable.
DELETE OBJECT hField.
DELETE OBJECT hText.
DELETE OBJECT hValue.


  MESSAGE ' ReturnCode: ' STRING(returnCode) SKIP 
          ' ReturnMessage: ' returnMessage  SKIP
          ' Id: ' bravoId VIEW-AS ALERT-BOX .
Jensd
  • 7,886
  • 2
  • 28
  • 37
2

For reading and processing just a few fragments of an XML I think you would be better off with the SAX reader.

This Progress Sax-reader has some ideas on how to implement that.

In my experience the SAX reader is much easier to work with than the full blown XML document.

Tom Bascom
  • 13,405
  • 2
  • 27
  • 33