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-ns.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 uses namespaces. */ hParser:SET-INPUT-SOURCE("FILE", "i-sax1-ns.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 xmlns="http:/www.wmhwmh.biz/ns/Default" xmlns:pl="http://www.wmhwmh.biz/ns/phonelist"> <pl:Entry pl:ContactName="Jane Jones"> 555 555-5555 </pl:Entry> <pl:Entry pl:ContactName="John Smith"> 555 555-1111 </pl:Entry> </Phonelist> |
/* Name attribute for the current entry. App gets it during the StartElement
callback */ DEFINE VARIABLE currentPerson AS CHARACTER NO-UNO. /* 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. The code assumes that Namespace processing is enabled and checks to make sure that name parameters are part of the correct namespace. */ 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 attributes AS HANDLE NO-UNDO. IF namespaceURI = "http://www.wmhwmh.biz/ns/phonelist" THEN DO: IF localName = "Entry" THEN currentPerson = attributes:GET-VALUE-BY-NAMESPACE-NAME ("http://www.wmhwmh.biz/ns/phonelist", "ContactName" ). END. END PROCEDURE. /* This callback gets passed the character data for an element. 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. (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. /* Can 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. 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 namespaceURI = "http://www.wmhwmh.biz/ns/phonelist" THEN DO: IF localName = "Entry" THEN DO: MESSAGE "Name: " currentPerson SKIP "Phone Number: " currentNum VIEW-AS ALERT-BOX. ASSIGN currentNum = "" currentPerson = "". END. 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: http:/www.wmhwmh.biz/ns/Default localName: Phonelist qName: Phonelist SAX-ATTRIBUTE has 0 items: Callback function: StartElement namespaceURI: http://www.wmhwmh.biz/ns/phonelist localName: Entry qName: pl:Entry SAX-ATTRIBUTE has 1 items: Attribute 1 : namespaceURI: http://www.wmhwmh.biz/ns/phonelist localName: ContactName qName: pl:ContactName type: CDATA value: Jane Jones Callback function: Characters charData: 555 555-5555 Callback function: EndElement namespaceURI: http://www.wmhwmh.biz/ns/phonelist localName: Entry qName: pl:Entry Callback function: StartElement namespaceURI: http://www.wmhwmh.biz/ns/phonelist localName: Entry qName: pl:Entry SAX-ATTRIBUTE has 1 items: Attribute 1 : namespaceURI: http://www.wmhwmh.biz/ns/phonelist localName: ContactName qName: pl:ContactName type: CDATA value: John Smith Callback function: Characters charData: 555 555-1111 Callback function: EndElement namespaceURI: http://www.wmhwmh.biz/ns/phonelist localName: Entry qName: pl:Entry Callback function: EndElement namespaceURI: http:/www.wmhwmh.biz/ns/Default localName: Phonelist qName: Phonelist Callback function: EndDocument |