In previous posts I have explored the components required to publish a Word Document that contains a form that can be populated from IBM SPSS Data Collection. The Word document was created using Form Fields within a table. The Word 2007 Content Control toolkit (available here) was used to create a custom part, a slice of custom XML defined not by Word but by the developer. The same tool was then used to link the custom parts to the form fields in the table (Binding custom parts to form fields). All this work has resulted in a Word document that is using custom XML to define the content of the table.
The purpose of this post is to go back to IBM SPSS Data Collection to build the XML ready to be sent to Word for posting into the Word document. There are two ways in which this can be done:
It may be that these two techniques will blend together. The current custom part will be read through a stream, updated and then written back. There are only two key questions to be answered:
In the latter case the alternative is for IBM SPSS Data Collection to converse with the dll sending attribute/value pairs each time it wants to update an element of the document. As the latter is likely to result in multiple reads of the Word document it is not considered suitable for this particular scenario. If the document was being collaborated on such that two or more users may want to see the changes taking place in real-time it is likely that this approach would be used.
Consequently the plan at this time is to have the routing of the survey create an XML structure from the responses provided and to send that XML data structure to Word via a DLL that handles the updating of the custom part.
Data Collection Script (DCScript) does not used strongly typed variables but the variables do have to be declared. Consequently a Dim statement for xmlPart is required before this script. Once this is done it is possible to create the relevant nodes. The first is the root node that appears at the top of the XML. This would usually be done using createElement method, however, this method does not support namespaces so the more complex createNode is required:
The createNode method has a constant Node_Element that has a value of 1. This constant is declared at the top of the script. The createNode is followed by an appendChild method to add this node to the XML document. This process can be repeated for the personal and incident nodes. In the case of the incident node there is two attributes associated to this node. The code used to generated these two attributes is the same as the code used to generate almost all the attributes in the XML document. In each case an IF statement is used to check whether there was a response to the question. If a response is present the value is applied to the Incident Node using the setAttribute method, otherwise the setAttribute method is used to create a blank value. This ensures that the attribute is present so that the Word document can be mapped correctly and the structure of the XML is consistent.
The exception to this methodology is the Title and Severity questions. Both of these questions are categorical (single punch) and so the response.value is an array (e.g. {Mr}). Even though, being single punch these responses only ever have one element in the array it is necessary to turn the response into a text string before applying it to the XML. Data Collection provides the format function to convert (amongst other things) categorical responses into either their categorical name or their categorical label.
Although as a rule DCScript is not case sensitive. This function is one of the exceptions. It is essential that the code (“a” or “b”) is in lower case to deliver the right result. As a consequence the writing of these responses into the XML looks like this:
Routing(Web)
Dim xmlPart, xmlNode, xmlRoot, xmlPersonal, xmlIncident
Const Node_Element = 1
IOM.LayoutTempla
te = "RailComplaint.htm"
Personal.Ask()
Incident.Ask()
set xmlPart = CreateObject("Microsoft.XMLDOM")
set xmlRoot = xmlPart.createNode(Node_Element, "cao2:root", "http://www.kevinagray.co.uk/railcomplaint")
xmlPart.appendChild(xmlRoot)
set xmlPersonal = xmlPart.CreateNode(Node_Element, "cao2:personal", "http://www.kevinagray.co.uk/railcomplaint")
xmlRoot.appendChild(xmlPersonal)
set xmlIncident = xmlPart.CreateNode(Node_Element, "cao2:incident", "http://www.kevinagray.co.uk/railcomplaint")
xmlRoot.appendChild(xmlIncident)
if IncidentDate.Response.Value <> null then
xmlIncident.setAttribute("cao2:when", IncidentDate.Response.Value)
else
xmlIncident.setAttribute("cao2:when", "")
end if
if IncidentDestination.Response.Value <> null then
xmlIncident.setAttribute("cao2:destination", IncidentDestination.Response.Value)
else
xmlIncident.setAttribute("cao2:destination", "")
end if
set xmlNode = xmlPart.CreateNode(Node_Element, "cao2:name", "http://www.kevinagray.co.uk/railcomplaint")
xmlPersonal.appendChild(xmlNode)
if Title.Response.Value <> null then
xmlNode.setAttribute("cao2:title", format(Title.Response.Value,"b"))
else
xmlNode.setAttribute("cao2:title", "")
end if
if fname.Response.Value <> null then
xmlNode.setAttribute("cao2:fname", fname.response.Value)
else
xmlNode.setAttribute("cao2:fname", "")
end if
if lname.Response.Value <> null then
xmlNode.setAttribute("cao2:lname", lname.response.Value)
else
xmlNode.setAttribute("cao2:lname", "")
end if
set xmlNode = xmlPart.CreateNode(Node_Element, "cao2:address", "http://www.kevinagray.co.uk/railcomplaint")
xmlPersonal.appendChild(xmlNode)
if address1.Response.Value <> null then
xmlNode.setAttribute("cao2:line1", address1.Response.Value)
else
xmlNode.setAttribute("cao2:line1", "")
end if
if address2.Response.Value <> null then
xmlNode.setAttribute("cao2:line2", address2.Response.Value)
else
xmlNode.setAttribute("cao2:line2", "")
end if
if Town.Response.Value <> null then
xmlNode.setAttribute("cao2:town", town.Response.Value)
else
xmlNode.setAttribute("cao2:town", "")
end if
if postcode.Response.Value <> null then
xmlNode.setAttribute("cao2:postcode", postcode.Response.Value)
else
xmlNode.setAttribute("cao2:postcode", "")
end if
set xmlNode = xmlPart.CreateNode(Node_Element, "cao2:contact", "http://www.kevinagray.co.uk/railcomplaint")
xmlPersonal.appendChild(xmlNode)
if Phone.Response.Value <> null then
xmlNode.setAttribute("cao2:work", Phone.Response.Value)
else
xmlNode.setAttribute("cao2:work", "")
end if
if Phone2.Response.Value <> null then
xmlNode.setAttribute("cao2:home", Phone2.Response.Value)
else
xmlNode.setAttribute("cao2:home", "")
end if
if Mobile.Response.Value <> null then
xmlNode.setAttribute("cao2:mobile", Mobile.Response.Value)
else
xmlNode.setAttribute("cao2:mobile", "")
end if
if eMail.Response.Value <> null then
xmlNode.setAttribute("cao2:email", eMail.Response.Value)
else
xmlNode.setAttribute("cao2:email", "")
end if
set xmlNode = xmlPart.CreateNode(Node_Element, "cao2:departure", "http://www.kevinagray.co.uk/railcomplaint")
xmlIncident.appendChild(xmlNode)
if IncidentDepart.Response.Value <> null then
xmlNode.setAttribute("cao2:from", IncidentDepart.Response.Value)
else
xmlNode.setAttribute("cao2:from", "")
end if
if IncidentExpected.Response.Value <> null then
xmlNode.setAttribute("cao2:expected", IncidentExpected.Response.Value)
else
xmlNode.setAttribute("cao2:expected", "")
end if
if IncidentActual.Response.Value <> null then
xmlNode.setAttribute("cao2:actual", IncidentActual.Response.Value)
else
xmlNode.setAttribute("cao2:actual", "")
end if
set xmlNode = xmlPart.CreateNode(Node_Element, "cao2:impact", "http://www.kevinagray.co.uk/railcomplaint")
xmlIncident.appendChild(xmlNode)
if IncidentSeverity.Response.Value <> null then
xmlNode.setAttribute("cao2:severity", format(IncidentSeverity.Response.Value, "b"))
else
xmlNode.setAttribute("cao2:severity", "")
end if
if ExpectedOutcome.Response.Value <> null then
xmlNode.setAttribute("cao2:outcome", ExpectedOutcome.Response.Value)
else
xmlNode.setAttribute("cao2:outcome", "")
end if
if CostIncurred.Response.Value <> null then
xmlNode.setAttribute("cao2:cost", CostIncurred.Response.Value)
else
xmlNode.setAttribute("cao2:cost", "")
end if
set xmlNode = xmlPart.CreateNode(Node_Element, "cao2:description", "http://www.kevinagray.co.uk/railcomplaint")
xmlIncident.appendChild(xmlNode)
if IncidentSeverity.Response.Value <> null then
xmlPart.createTextNode(IncidentDescription.Response.Value)
else
xmlPart.createTextNode("")
end if
debug.Log(xmlPart.xml)
End Routing