Kbase P157414: 4GL/ABL: Sample code of the use of SAX parser with XSD validation.
Autor |
  Progress Software Corporation - Progress |
Acesso |
  Público |
Publicação |
  15/12/2009 |
|
Status: Unverified
GOAL:
4GL/ABL: Sample code of the use of SAX parser with XSD validation.
GOAL:
How to use SAX parser to validate an XML document with XSD?
FACT(s) (Environment):
All Supported Operating Systems
OpenEdge 10.x
FIX:
The following are two procedures SAXParseWithValidation.p and AppCallbacks_Validate.p and two documents InvalidCars.xml and Cars.xsd to demonstrate the use of SAX parser to read the XML document with XSD validation.
The code also demonstrates how the validation event is captured by the FatalError call back procedure during the parsing of the XML document.
Both the sample procedures and the sample XML and XSD documents were copied from the 'OpenEdge Development with XML' course offered by the Progress Education.
To run the sample, put all the four files in your OpenEdge 10.x directory and execute the SAXParseWithValidation.p from a proenv session using a command similar to the following:
prowin32 -p SAXParseWithValidation.p.
/* SAXParseWithValidation.p */
DEFINE VARIABLE hParser as HANDLE NO-UNDO.
DEFINE VARIABLE hCallbacks AS HANDLE NO-UNDO.
CREATE SAX-READER hParser.
RUN AppCallbacks_Validate.p PERSISTENT SET hCallbacks.
hParser:HANDLER = hCallbacks.
hParser:SET-INPUT-SOURCE("FILE", "InvalidCars.xml").
hParser:NONAMESPACE-SCHEMA-LOCATION = "Cars.xsd".
hParser:VALIDATION-ENABLED=TRUE.
hParser:SAX-PARSE-FIRST() NO-ERROR.
REPEAT WHILE hParser:PARSE-STATUS = SAX-RUNNING:
hParser:SAX-PARSE-NEXT() NO-ERROR.
END.
DELETE OBJECT hParser.
DELETE PROCEDURE hCallbacks.
/* AppCallbacks_Validate.p */
DEFINE TEMP-TABLE Car NO-UNDO
FIELD CarID AS CHARACTER
FORMAT "x(30)"
LABEL "Car ID"
FIELD Style AS CHARACTER
FORMAT "x(30)"
LABEL "Style"
FIELD Ready AS CHARACTER
FORMAT "x(4)"
LABEL "Ready to testdrive?".
DEFINE VARIABLE gcCarID AS CHARACTER NO-UNDO.
DEFINE VARIABLE giNumCars AS INTEGER NO-UNDO.
DEFINE VARIABLE gcCurrentElement AS CHARACTER NO-UNDO.
PROCEDURE StartDocument:
MESSAGE
"Starting the parse of the document"
VIEW-AS ALERT-BOX.
END.
PROCEDURE EndDocument:
MESSAGE
"Number of Cars: " giNumCars
VIEW-AS ALERT-BOX.
END.
PROCEDURE StartElement:
DEFINE INPUT PARAMETER pcNamespaceURI AS CHARACTER NO-UNDO.
DEFINE INPUT PARAMETER pcLocalName AS CHARACTER NO-UNDO.
DEFINE INPUT PARAMETER pcElementName AS CHARACTER NO-UNDO.
DEFINE INPUT PARAMETER phAttributes AS HANDLE NO-UNDO.
gcCurrentElement = pcElementName.
IF pcElementName = "Cars" THEN
giNumCars = 0.
IF pcElementName = "Car" THEN DO:
gcCarID = "".
giNumCars = giNumCars + 1.
END.
END.
PROCEDURE Characters:
DEFINE INPUT PARAMETER ppText AS MEMPTR NO-UNDO.
DEFINE INPUT PARAMETER piNumChars AS INTEGER NO-UNDO.
IF gcCurrentElement = "CarID" THEN
gcCarID = gcCarID + GET-STRING(ppText,1,piNumChars).
END.
PROCEDURE EndElement:
DEFINE INPUT PARAMETER pcNamespaceURI AS CHARACTER NO-UNDO.
DEFINE INPUT PARAMETER pcLocalName AS CHARACTER NO-UNDO.
DEFINE INPUT PARAMETER pcElementName AS CHARACTER NO-UNDO.
RONG> IF pcElementName = "Car" THEN DO:
create Car.
Car.CarID = gcCarID.
END.
IF pcElementName = "Cars" THEN DO:
FOR EACH Car:
DISPLAY Car.CarID.
END.
END.
END.
PROCEDURE FatalError:
DEFINE INPUT PARAMETER pcMessage AS CHARACTER NO-UNDO.
MESSAGE
"Fatal Error Detected in element: " gcCurrentElement ": " pcMessage
VIEW-AS ALERT-BOX.
RETURN ERROR.
END.
PROCEDURE Error:
DEFINE INPUT PARAMETER pcMessage AS CHARACTER NO-UNDO.
MESSAGE
"Schema validation error in element: " gcCurrentElement ": " pcMessage
VIEW-AS ALERT-BOX.
RETURN ERROR.
END.
/* InvalidCars.xml */
<?xml version="1.0"?>
<Cars >
<Car>
<CarID>55</CarID>
<!--on lot-->
<CarAddedDate>06-18-2006</CarAddedDate>
</Car>
<Car Ready="no">
<foo>56</foo>
<!--on lot-->
<CarAddedDate>06-19-2006</CarAddedDate>
</Car>
<Car>
<CarID>57</CarID>
<!--on lot-->
<CarAddedDate>06-20-2006</CarAddedDate>
</Car>
</Cars>
/* cars.xsd */
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
<xs:element name="Cars">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" ref="Car"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="Car">
<xs:complexType>
<xs:sequence>
<xs:element ref="CarID"/>
<xs:element ref="CarAddedDate"/>
</xs:sequence>
<xs:attribute name="Ready" type="xs:NCName"/>
</xs:complexType>
</xs:element>
<xs:element name="CarID" type="xs:integer"/>
<xs:element name="CarAddedDate" type="xs:NMTOKEN"/>
</xs:schema>.