- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎02-27-2020 06:43 AM
I am trying to parse some XML in a scoped application and create records in a table. Here's my XML:
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">
<soapenv:Body>
<NS1:Get_BuildingResponse xmlns:NS1="http://Building_Pull">
<buildings>
<building>
<buildingId>663280148</buildingId>
<unitNum>1</unitNum>
<addrStreeNumFrom>5</addrStreeNumFrom>
<addrStreetName>LAKEVIEW </addrStreetName>
<addrStreetTypeCode>AVE </addrStreetTypeCode>
<addrCityName>KINGSTON </addrCityName>
<addrProvinceCode>ON</addrProvinceCode>
<locationDescriptions>
<locationDescription>
<addressId>370</addressId>
<locDescId>1</locDescId>
<locDescType>LOT </locDescType>
<locDescValue>1 </locDescValue>
</locationDescription>
<locationDescription>
<addressId>370</addressId>
<locDescId>2</locDescId>
<locDescType>CONC </locDescType>
<locDescValue>2 </locDescValue>
</locationDescription>
<locationDescription>
<addressId>370</addressId>
<locDescId>3</locDescId>
<locDescType>PART LOT</locDescType>
<locDescValue>4 </locDescValue>
</locationDescription>
<locationDescription>
<addressId>370</addressId>
<locDescId>4</locDescId>
<locDescType>BLOCK </locDescType>
<locDescValue>5 </locDescValue>
</locationDescription>
</locationDescriptions>
</building>
<building>
<buildingId>663280148</buildingId>
<unitNum>2</unitNum>
<addrStreeNumFrom>5</addrStreeNumFrom>
<addrStreetName>LAKEVIEW </addrStreetName>
<addrStreetTypeCode>AVE </addrStreetTypeCode>
<addrCityName>KINGSTON </addrCityName>
<addrProvinceCode>ON</addrProvinceCode>
<locationDescriptions>
<locationDescription>
<addressId>371</addressId>
<locDescId>1</locDescId>
<locDescType>LOT </locDescType>
<locDescValue>20 </locDescValue>
</locationDescription>
<locationDescription>
<addressId>371</addressId>
<locDescId>2</locDescId>
<locDescType>CONC </locDescType>
<locDescValue>40 </locDescValue>
</locationDescription>
<locationDescription>
<addressId>371</addressId>
<locDescId>3</locDescId>
<locDescType>PART LOT</locDescType>
<locDescValue>50 </locDescValue>
</locationDescription>
<locationDescription>
<addressId>371</addressId>
<locDescId>4</locDescId>
<locDescType>BLOCK </locDescType>
<locDescValue>60 </locDescValue>
</locationDescription>
</locationDescriptions>
</building>
<building>
<buildingId>663280148</buildingId>
<unitNum>3</unitNum>
<addrStreeNumFrom>5</addrStreeNumFrom>
<addrStreetName>LAKEVIEW </addrStreetName>
<addrStreetTypeCode>AVE </addrStreetTypeCode>
<addrCityName>KINGSTON </addrCityName>
<addrProvinceCode>ON</addrProvinceCode>
<locationDescriptions>
<locationDescription>
<addressId>372</addressId>
<locDescId>1</locDescId>
<locDescType>LOT </locDescType>
<locDescValue>200 </locDescValue>
</locationDescription>
<locationDescription>
<addressId>372</addressId>
<locDescId>2</locDescId>
<locDescType>CONC </locDescType>
<locDescValue>600 </locDescValue>
</locationDescription>
<locationDescription>
<addressId>372</addressId>
<locDescId>3</locDescId>
<locDescType>PART LOT</locDescType>
<locDescValue>500 </locDescValue>
</locationDescription>
<locationDescription>
<addressId>372</addressId>
<locDescId>4</locDescId>
<locDescType>BLOCK </locDescType>
<locDescValue>900 </locDescValue>
</locationDescription>
</locationDescriptions>
</building>
</buildings>
</NS1:Get_BuildingResponse>
</soapenv:Body>
</soapenv:Envelope>
The problem I'm having is that when I get to the <locationDescriptions> and <locationDescription> tags, my code is processing ALL of these tags when it should only be processing the tags associated to the specific building.
In the above example, I get three building records all with the same / last <locationDescription> set (Lot 200 - Conc 600).
I have attached my entire UI Action but here's the relevant snippets:
Create XML
Send it off
Get response
...
Error handling
...
//Building Nodes exist - write them out
//gs.addInfoMessage("Building Lookup - Point 1", 'Extreme Quote');
//Update FIRST building
node = xmlDoc.getFirstNode('//building');
iter1= node.getChildNodeIterator();
ci = createBuilding(iter1, xmlDoc); //<<< ends up at the code below
//Update SECOND buidling
nodeNext = xmlDoc.getNextNode(node);
if( !nodeNext ){
//no second buidling - do nothing
} else {
iter1= nodeNext.getChildNodeIterator();
ci = createBuilding(iter1); //<<< ends up at the code below
//Update REMAINING buildings
while(nodeNext){
node = nodeNext;
nodeNext = xmlDoc.getNextNode(node);
if(nodeNext === null){
break;
}
iter1= nodeNext.getChildNodeIterator();
ci = createBuilding(iter1); //<<< ends up at the code below
}
} //end while
} //end mainBuildingNode If
} catch(e) {
...
Check if the building exists - if so, update it
If not, create new
- write out all the building fields
...
//NON-CIVIC ADDRESS FIELDS
if(locDescExists == 'yes'){
//gs.addInfoMessage("Building Lookup - locDescExists yes", 'Extreme Quote');
//Update FIRST location description node
node2 xmlDoc.getFirstNode('//building/locationDescriptions/locationDescription');
iter2= node2.getChildNodeIterator();
ld = locationDescription(iter2);
grB.location_type_1a = ld[2];
grB.number_1a = ld[3];
//Update SECOND location description node
nodeNext2 = xmlDoc.getNextNode(node2);
if( !nodeNext2 ){
//no second coverage - do nothing
} else {
iter2= nodeNext2.getChildNodeIterator();
ld = locationDescription(iter2);
grB.location_type_1b = ld[2];
grB.number_1b = ld[3];
//gs.addInfoMessage("thru LD 2");
//Update REMAINING location description node
while(nodeNext2){
node2 = nodeNext2;
nodeNext2 = xmlDoc.getNextNode(node2);
if(nodeNext2 === null){
break;
}
iter2= nodeNext2.getChildNodeIterator();
ld = locationDescription(iter2);
//gs.addInfoMessage("thru LD 3+");
locDescID = ld[1];
switch (locDescID.toString()) {
case '3':
grB.location_type_2a = ld[2];
grB.number_2a = ld[3];
break;
case '4' :
grB.location_type_2b = ld[2];
grB.number_2b = ld[3];
break;
case '5' :
grB.location_type_3a = ld[2];
grB.number_3a = ld[3];
break;
case '6':
grB.location_type_3b = ld[2];
grB.number_3ba = ld[3];
break;
}
} // end WHILE remaining locations
} // process second location
} //end LocDesc exists
I need to know how to process only the <locationDescriptions> attached to the building currently being processed.
Thank you!
Solved! Go to Solution.
- Labels:
-
Scripting and Coding

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎02-27-2020 07:47 AM
Hello,
I would suggest using XMLHelper script to convert your returned XML into an Object. From there you can extract the different building and location details into an Array. Something like so:
var helper =new XMLHelper(responseBody);
var objHlpr = helper.toObject();
var buildingArr = objHlpr['soapenv:Body']['NS1:Get_BuildingResponse']['buildings']['building'];
The resulting Array would contain the following values:
[
{
"buildingId": "663280148",
"unitNum": "1",
"addrStreeNumFrom": "5",
"addrStreetName": "LAKEVIEW",
"addrStreetTypeCode": "AVE",
"addrCityName": "KINGSTON",
"addrProvinceCode": "ON",
"locationDescriptions": {
"locationDescription": [
{
"addressId": "370",
"locDescId": "1",
"locDescType": "LOT",
"locDescValue": "1"
},
{
"addressId": "370",
"locDescId": "2",
"locDescType": "CONC",
"locDescValue": "2"
},
{
"addressId": "370",
"locDescId": "3",
"locDescType": "PART LOT",
"locDescValue": "4"
},
{
"addressId": "370",
"locDescId": "4",
"locDescType": "BLOCK",
"locDescValue": "5"
}
]
}
},
{
"buildingId": "663280148",
"unitNum": "2",
"addrStreeNumFrom": "5",
"addrStreetName": "LAKEVIEW",
"addrStreetTypeCode": "AVE",
"addrCityName": "KINGSTON",
"addrProvinceCode": "ON",
"locationDescriptions": {
"locationDescription": [
{
"addressId": "371",
"locDescId": "1",
"locDescType": "LOT",
"locDescValue": "20"
},
{
"addressId": "371",
"locDescId": "2",
"locDescType": "CONC",
"locDescValue": "40"
},
{
"addressId": "371",
"locDescId": "3",
"locDescType": "PART LOT",
"locDescValue": "50"
},
{
"addressId": "371",
"locDescId": "4",
"locDescType": "BLOCK",
"locDescValue": "60"
}
]
}
},
{
"buildingId": "663280148",
"unitNum": "3",
"addrStreeNumFrom": "5",
"addrStreetName": "LAKEVIEW",
"addrStreetTypeCode": "AVE",
"addrCityName": "KINGSTON",
"addrProvinceCode": "ON",
"locationDescriptions": {
"locationDescription": [
{
"addressId": "372",
"locDescId": "1",
"locDescType": "LOT",
"locDescValue": "200"
},
{
"addressId": "372",
"locDescId": "2",
"locDescType": "CONC",
"locDescValue": "600"
},
{
"addressId": "372",
"locDescId": "3",
"locDescType": "PART LOT",
"locDescValue": "500"
},
{
"addressId": "372",
"locDescId": "4",
"locDescType": "BLOCK",
"locDescValue": "900"
}
]
}
}
]
From there you can perform a simple loop against the Array to identify the building which is currently being processed and then utilize the locationDescription as needed.
Hope this helps.
--David

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎02-27-2020 07:47 AM
Hello,
I would suggest using XMLHelper script to convert your returned XML into an Object. From there you can extract the different building and location details into an Array. Something like so:
var helper =new XMLHelper(responseBody);
var objHlpr = helper.toObject();
var buildingArr = objHlpr['soapenv:Body']['NS1:Get_BuildingResponse']['buildings']['building'];
The resulting Array would contain the following values:
[
{
"buildingId": "663280148",
"unitNum": "1",
"addrStreeNumFrom": "5",
"addrStreetName": "LAKEVIEW",
"addrStreetTypeCode": "AVE",
"addrCityName": "KINGSTON",
"addrProvinceCode": "ON",
"locationDescriptions": {
"locationDescription": [
{
"addressId": "370",
"locDescId": "1",
"locDescType": "LOT",
"locDescValue": "1"
},
{
"addressId": "370",
"locDescId": "2",
"locDescType": "CONC",
"locDescValue": "2"
},
{
"addressId": "370",
"locDescId": "3",
"locDescType": "PART LOT",
"locDescValue": "4"
},
{
"addressId": "370",
"locDescId": "4",
"locDescType": "BLOCK",
"locDescValue": "5"
}
]
}
},
{
"buildingId": "663280148",
"unitNum": "2",
"addrStreeNumFrom": "5",
"addrStreetName": "LAKEVIEW",
"addrStreetTypeCode": "AVE",
"addrCityName": "KINGSTON",
"addrProvinceCode": "ON",
"locationDescriptions": {
"locationDescription": [
{
"addressId": "371",
"locDescId": "1",
"locDescType": "LOT",
"locDescValue": "20"
},
{
"addressId": "371",
"locDescId": "2",
"locDescType": "CONC",
"locDescValue": "40"
},
{
"addressId": "371",
"locDescId": "3",
"locDescType": "PART LOT",
"locDescValue": "50"
},
{
"addressId": "371",
"locDescId": "4",
"locDescType": "BLOCK",
"locDescValue": "60"
}
]
}
},
{
"buildingId": "663280148",
"unitNum": "3",
"addrStreeNumFrom": "5",
"addrStreetName": "LAKEVIEW",
"addrStreetTypeCode": "AVE",
"addrCityName": "KINGSTON",
"addrProvinceCode": "ON",
"locationDescriptions": {
"locationDescription": [
{
"addressId": "372",
"locDescId": "1",
"locDescType": "LOT",
"locDescValue": "200"
},
{
"addressId": "372",
"locDescId": "2",
"locDescType": "CONC",
"locDescValue": "600"
},
{
"addressId": "372",
"locDescId": "3",
"locDescType": "PART LOT",
"locDescValue": "500"
},
{
"addressId": "372",
"locDescId": "4",
"locDescType": "BLOCK",
"locDescValue": "900"
}
]
}
}
]
From there you can perform a simple loop against the Array to identify the building which is currently being processed and then utilize the locationDescription as needed.
Hope this helps.
--David
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎02-27-2020 11:45 AM
I got really excited about this and then promptly tripped over a small detail - this is a scoped application.
XMLHelper isn't available in scoped apps.
The scoped equivalent is XMLDocument2 which is what I am already using:
//PARSE RESPONSE & WRITE TO FIELDS
var xmlDoc = new XMLDocument2();
xmlDoc.parseXML(responseBody);
Back to square 0.

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎02-27-2020 12:13 PM
You can modify the XMLHelper script include to be accessible from 'All application scopes' then it can be used with the scoped app. We have done this exact thing to be able to utilize across scopes. If that is not an option for you then you can also create your own script include from within your application scope that is a copy of XMLHelper. Simply modify the above script to call your newly created script include and it will work just the same.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎02-28-2020 07:49 AM
Progress!
I created a scoped version of XMLHelper and I'm calling it successfully and passing in the responseBody.
The error I'm stuck at is: Cannot find function parse in object function GlideXMLUtil() {
[native code, arity=0]
}
.
I can see the line in the XMLHelper script include where it's getting stuck:
setXML : function(xmlParam) {
this.xml = xmlParam;
// if xml is string, or it looks like a string (has trimLeft function and is object)
// then we want to parse it as a string
if (typeof xmlParam == 'string' || (typeof xmlParam == 'object' && xmlParam && xmlParam.trimLeft))
var temp = xmlParam.substring(1, 100);
gs.info('setXML function - 1 - typeof = ' + typeof xmlParam);
gs.info('setXML function - 1 - temp = ' + temp);
this.xml = GlideXMLUtil.parse(xmlParam); //<<<<<ERRROR
gs.info('setXML function - 2');
},
typeof = string
temp = is propertly returning the first 100 chars of responseBody.
The documentation on GlideXMLUtil is ... sparse. Any thoughts?
TIA!