Monday, July 20, 2009

ColdFusion Program to Read XML File

Markup encodes and transfers metadata about information such as its structure and format. XML is a markup language, derived from the much earlier SGML, which uses strings of short words to surround the data it is describing. These strings of short words are known as tags. An example would be <name>George</name> <phone>555-1212</phone>.

With XML, a structural model of the data in a file can be encoded along with the data. The structure can be as simple as name and phone or much more complex, with fields like name and phone embedded in other fields like employee. A style sheet, an XSL, can be used to transform the tagged data in an XML file into a Web page. Likewise, a schema file, an XSD, can communicate database information in database operations.

ColdFusion provides a subset of functions that enable a programmer to operate on XML files. A typical operation would be to read an XML file, work on it and write it, perhaps to a database. A datatype in ColdFusion has been created for XML and is known as the XML document object. By doing this, Adobe extends the reach of its already existing ColdFusion structure functions to encompass XML data as well.

Structures consist of objects, properties, and objects embedded in other objects. Name and phone embedded in employee is an example. The dot operator is used to delimit what object in a structure you want to access. The general syntax is <object>.<object>, <object>.<property>. These can be combined to get for instance <object>.<child object>.<property>, so to access my phone number, we would use the dot operator: <employee>.<phone>

The following ColdFusion code uses some of the XML functions to read an XML file. It starts by validating the XML data file to ensure that it is consistent with its schema.

<cfset myResults= XMLValidate ("wits.xml", "wits.xsd")>
<cfoutput> Is Valid? #myResults.status#!
</cfoutput>


Next, a file handle is obtained.

<cffile variable="gmrXML" file=" “wits.xml" action="read">

Then we get a ColdFusion XML Document Object datatype using our file handle and the xmlParse() function:

<cfset myxml=" xmlParse(gmrXML)">

Now we are ready to loop through the data, and display different field values. This test file consists of a series of incidents embedded in an incident list. In addition to its own properties, an incident will have an embedded list, or object, of one or more incident types. In addition to this, it will have, an embedded facilities list, of zero or more facilities involved in the incident. These embedded lists correspond to embedded objects or to child tables in a database.


<cfoutput>
<cfloop index="i" from="1" to="#arrayLen(myXML.incidentList.Incident)#">
Incident<br>
#myXml.incidentlist.incident[i].ICN#<br>
#myXml.incidentlist.incident[i].Subject#<br>
#myXml.incidentlist.incident[i].Summary#<br>
#myXml.incidentlist.incident[i].IncidentDate#<br>
Event Type<br>
<!---Here is an inner loop to get all Event Types for the Incident--->
<cfloop index="j" from="1" to=
"#arrayLen(myXML.incidentList.Incident[i]. EventTypeList.EventType)#">
#myXml.incidentlist.incident[i].EventTypeList.EventType[j]#<br>
</cfloop>
<br>Facilities<br>
<cfif StructKeyExists(myXml.incidentlist.incident[i].FacilityList,"Facility")>
<!---Here is an inner loop to get all Facilities for the Incident--->
<cfloop index="j" from="1" to
"#arrayLen(myXML.incidentList.Incident[i]. FacilityList.Facility)#">
#myXml.incidentlist.incident[i].FacilityList.Facility[j].FacilityType#<br>
#myXml.incidentlist.incident[i].FacilityList.Facility[j].Indicator#<br>
</cfloop>
<cfelse>
No facility for this one
</cfif>
</cfloop>
</cfoutput>



The ColdFusion arraylen is used in the “To” parameter of our loop to return the number of Incidents in this incidentlist. There is one incidentlist per file. Our dot operator starts with the file handle, then refers to the incidentlist we know to be in file (because we validated), and the particular incident is referenced with our index variable [i]:

myXml.incidentlist.incident[i].ICN

The incident number property, ICN, is accessed from the record just read from the file. For EventType, it is very similar. Since we know we will have at least one Event Type in every incident (one or more), the following code is sufficient:

myXml.incidentlist.incident[i].EventTypeList.EventType[j]

On the other hand, we may not have a facility (zero or more) and will get a null pointer exception if we try to dereference a facility in an empty facilitylist. We need to use the ColdFusion StructKeyExists function to test if a facility object is embedded in the facilitylist for the current record.

<cfif StructKeyExists(myXml.incidentlist.incident[i].FacilityList,"Facility")>

If so, then we loop through the facilities involved in the incident, else we indicate no facility.

No comments: