DEFINE VARIABLE hHandler AS HANDLE NO-UNDO.
DEFINE VARIABLE hParser AS HANDLE NO-UNDO. /* Create the SAX-reader object */ CREATE SAX-READER hParser. /* Run the persistent procedure that contains the callbacks */ RUN "i-sax1h.p" PERSISTENT SET hHandler. /* Give the SAX-READER the handle to the persistent procedure */ hParser:HANDLER = hHandler. /* Give the SAX-READER the info on the file to parse. This XML file does not use namespaces. */ hParser:SET-INPUT-SOURCE("FILE", "i-sax1.xml"). hParser:SAX-PARSE( ) NO-ERROR. /* By the time SAX-PARSE returns, our callbacks have been called as many times as necessary and we're done processing the XML document (or there was an error) */ IF ERROR-STATUS:ERROR THEN DO: IF ERROR-STATUS:NUM-MESSAGES > 0 THEN /* Unable to begin the parse */ MESSAGE ERROR-STATUS:GET-MESSAGE(1) VIEW-AS ALERT-BOX. ELSE /* Error detected in a callback */ MESSAGE RETURN-VALUE VIEW-AS ALERT-BOX. END. ELSE MESSAGE "Document parsed successfully" VIEW-AS ALERT-BOX. DELETE OBJECT hParser. DELETE PROCEDURE hHandler. |
<?xml version='1.0' ?>
<Phonelist> <Entry ContactName="Jane Jones"> 555 555-5555 </Entry> <Entry ContactName="John Smith"> 555 555-1111 </Entry> </Phonelist> |
/* This small example uses a very simple approach to keeping track of where
it is in the processing of the document. It uses currentPerson and currentNum, which are variables global to this procedure that enable the application to tie together the several different pieces of information that it gets for each element in the XML document. */ /* Name attribute for the current entry. App gets it during the StartElement callback */ DEFINE VARIABLE currentPerson AS CHARACTER NO-UNDO. /* Phone number from the current entry. App gets it during the Characters callback because it is the character data for the element. */ DEFINE VARIABLE currentNum AS CHARACTER NO-UNDO. /* This procedure is called when the parser finds the start tag for an element. For this particular XML doc, the app simply looks for "Entry" elements and digs out the "ContactName" attribute during the StartElement call, saving it in currentPerson */ PROCEDURE StartElement: DEFINE INPUT PARAMETER namespaceURI AS CHARACTER NO-UNDO. DEFINE INPUT PARAMETER localName AS CHARACTER NO-UNDO. DEFINE INPUT PARAMETER qname AS CHARACTER NO-UNDO. DEFINE INPUT PARAMETER hAttributes AS HANDLE NO-UNDO. IF qName = "Entry" THEN currentPerson = hAttributes:GET-VALUE-BY-QNAME("ContactName"). END PROCEDURE. /* This callback gets passed the character data for an element. Note that SAX does not guarantee that all the characters for an element get passed in one call -- that's why the app has to maintain the currentNum global variable and append to it when handling Characters, and also why it has to wait for EndElement before displaying the message box. (Note also that some apps may need to use a MEMPTR to accumulate the character data, which may exceed the 32K ABL CHARACTER variable limit) */ PROCEDURE Characters: DEFINE INPUT PARAMETER charData AS MEMPTR NO-UNDO. DEFINE INPUT PARAMETER numChars AS INTEGER NO-UNDO. /* Assume that any call to Characters is for an Entry's text value, because we know what the document looks like. If this weren't the case, we'd have to keep track of the localName passed to the most recent call to StartElement. */ currentNum = currentNum + GET-STRING(charData, 1, GET-SIZE(charData)). END PROCEDURE. /* This callback is called when the parser finds the end tag for an Element. Note that this app only cares about the end of an Entry element.*/ PROCEDURE EndElement: DEFINE INPUT PARAMETER namespaceURI AS CHARACTER NO-UNDO. DEFINE INPUT PARAMETER localName AS CHARACTER NO-UNDO. DEFINE INPUT PARAMETER qName AS CHARACTER NO-UNDO. IF qName = "Entry" THEN DO: MESSAGE "Name: " currentPerson SKIP "Phone Number: " currentNum VIEW-AS ALERT-BOX. ASSIGN currentNum = "" currentPerson = "". END. END PROCEDURE. /* Knowing the structure of the XML doc, the app could have done this in the EndElement call for the Phonelist element and could then have omitted EndDocument altogether. */ PROCEDURE EndDocument: MESSAGE "All Done" VIEW-AS ALERT-BOX. END PROCEDURE. |
Callback function: StartDocument
Callback function: StartElement namespaceURI: localName: Phonelist qName: Phonelist SAX-ATTRIBUTE has 0 items: Callback function: StartElement namespaceURI: localName: Entry qName: Entry SAX-ATTRIBUTE has 1 items: Attribute 1 : namespaceURI: localName: ContactName qName: ContactName type: CDATA value: Jane Jones Callback function: Characters charData: 555 555-5555 Callback function: Characters charData: 555 555-5555 Callback function: EndElement namespaceURI: localName: Entry qName: Entry Callback function: StartElement namespaceURI: localName: Entry qName: Entry SAX-ATTRIBUTE has 1 items: Attribute 1 : namespaceURI: localName: ContactName qName: ContactName type: CDATA value: John Smith Callback function: Characters charData: 555 555-1111 Callback function: EndElement namespaceURI: localName: Entry qName: Entry Callback function: EndElement namespaceURI: localName: Phonelist qName: Phonelist Callback function: EndDocument |