Parsing XML with name/value pairs as attributes

Parsing XML with name/value pairs as attributes

  
I am very new to the OutSystems Platform and am having a bit of an issue with parsing an XML file that I am getting as a response to a RESTful webservice call.  I can see that I am actually getting a good response fromt he web serivce, and using XMLDocument_selectSingleNode and passing that to XmlAttribute_GetValue, I can even see a single value.  The trouble comes because I want to pull all of the record from the XML (several hundred records) into a db table(ultimately).

The returned XML looks something like:
<webServiceResponse><response ResponseName="GET_COMPANY_LAST_LOCATION_RESPONSE">
    <responseList>
      <responseItem id="DVN" value="992010"></responseItem>
      <responseItem id="ActivityType" value="In Motion"></responseItem>
      <responseItem id="LastLatitude" value="43.59252"></responseItem>
      <responseItem id="LastLongitude" value="-111.137"></responseItem>
      <responseItem id="LastActivityDate" value="2013-01-17 20:43:50.0"></responseItem>
    </responseList>
    <responseList>
      <responseItem id="DVN" value="992011"></responseItem>
      <responseItem id="ActivityType" value="Device Unplugged"></responseItem>
      <responseItem id="LastLatitude" value="43.50984"></responseItem>
      <responseItem id="LastLongitude" value="-112.0052"></responseItem>
      <responseItem id="LastActivityDate" value="2012-05-08 17:25:10.0"></responseItem>
    </responseList>
    <responseList>
      <responseItem id="DVN" value="992012"> </responseItem>
      <responseItem id="ActivityType" value="Stopped"></responseItem>
      <responseItem id="LastLatitude" value="46.22679"></responseItem>
      <responseItem id="LastLongitude" value="-119.23491"></responseItem>
      <responseItem id="LastActivityDate" value="2013-01-17 18:57:59.0"></responseItem>
    </responseList>
  </response></webServiceResponse>

I am taking this XML, which is returned as text, pushing it through Regex_Replace to pull off the <webServiceResponse> and </webServiceResponse>.  I take the results of that and use that as the input to Serialization_XmlToRecordList.  I have a record list local variable that points to a structure called response, which has a single attribute called responseList and is of type record list.  The record definition is structure called responseList, which also has a single attribute called responseItem, which points to another structure called responseItem.  The responseItem structure has attributes Attr_DVN, Attr_Activity, Attr_Latitude, Attr_Longitude and Attr_ActivityDate.  When I run this I get an error that says "Object reference not set to an instance of an object.".  If I change this so that the <response> and </response> are removed and I use a record list local that points to the responseList structure I get an error message about multiple root elements.

My intention is to push all of this data into an entity and have it run as a timer so that I can report on the locaiton of the vehicles near real time.

Any assitance in helping me understand where I went wrong, or what I am missing would be greatly appreciated.

Regards,
Paul
Hi Paul

It seems that the Serialization_XmlToRecordList action will not fully support that XML construct. Basically, it assumes that the data is avaliable as InnerText and not as XmlElement attributes, thus, it will not find any data.

In addition, the data structure uses multiple chained lists, so that could also be a problem.

Nevertheless, you can use the Xml extension additional actions to load that XML into the database. All you need is to iterate over the responseList nodes and their Child nodes to get the correspondent information, using the XmlDocument_SelectNodes, XmlNodeList_item and XmlElement_GetChildByIndex actions.

I've uploaded a sample OML with the logic to import your Xml snippet into an Entity. Check it out.

Cheers

Miguel Simões João
Hi Paul,

You can also take a look at the XMLRecords extension (http://www.outsystems.com/forge/153/XML+Records/) which handles the parsing for you.

The idea behind this extension is that it converts between XML and OutSystems structures, you define a set of structures that match the schema of your XML and then you can have the extension parse the XML and fill in your structures with the appropriate values.
It also works the other way around, taking the values from your structures and outputing then to XML.

In this case the challenge is to create a set of OutSystems structures that correctly represent the schema of the XML document you are trying to process.

You can find further information on the component page and the download itself includes a sample eSpace which shows how you can use the extension.

Best regards,
Gonçalo Fonseca
Hi Miguel,
Thank You very much.  This is exactly what I needed to see.  Very much appreciated.

Gonçalo,
I have actually started with the XML Records extension, but cound not figure out how to build the structures to match the layout of the xml.

I am not overjoyed with the format of the data, as it seems like it would have been easier to put the data in inner text rather than attributes.  Unfortunately sometime you are stuck with what you get. 

Thanks again for the assistance.
Paul
Hi! 
What if the xml is like this?

<webServiceResponse><response ResponseName="GET_COMPANY_LAST_LOCATION_RESPONSE">
    <ResponseMain>
     <ResponseChild TransID ="1" Code="TS1">
         <responseList Code="1TS" Note="Test1">
            <responseItem id="DVN" value="992010"></responseItem>
            <responseItem id="ActivityType" value="In Motion"></responseItem>
            <responseItem id="LastLatitude" value="43.59252"></responseItem>
            <responseItem id="LastLongitude" value="-111.137"></responseItem>
            <responseItem id="LastActivityDate" value="2013-01-17 20:43:50.0"></responseItem>
         </responseList>
         <responseList Code="2TS" Note="Test2">
             <responseItem id="DVN" value="992011"></responseItem>
             <responseItem id="ActivityType" value="Device Unplugged"></responseItem>
             <responseItem id="LastLatitude" value="43.50984"></responseItem>
             <responseItem id="LastLongitude" value="-112.0052"></responseItem>
             <responseItem id="LastActivityDate" value="2012-05-08 17:25:10.0"></responseItem>
         </responseList>
     </ResponseChild>
     <ResponseChild TransID ="2" Code="TS1">
<responseList Code="1TS" Note="Test1">
            <responseItem id="DVN" value="992010"></responseItem>
            <responseItem id="ActivityType" value="In Motion"></responseItem>
            <responseItem id="LastLatitude" value="43.59252"></responseItem>
            <responseItem id="LastLongitude" value="-111.137"></responseItem>
            <responseItem id="LastActivityDate" value="2013-01-17 20:43:50.0"></responseItem>
         </responseList>
         <responseList Code="2TS" Note="Test2">
             <responseItem id="DVN" value="992011"></responseItem>
             <responseItem id="ActivityType" value="Device Unplugged"></responseItem>
             <responseItem id="LastLatitude" value="43.50984"></responseItem>
             <responseItem id="LastLongitude" value="-112.0052"></responseItem>
             <responseItem id="LastActivityDate" value="2012-05-08 17:25:10.0"></responseItem>
         </responseList>
     </ResponseChild>
     <ResponseChild TransID ="3" Code="TS1">
<responseList Code="1TS" Note="Test1">
            <responseItem id="DVN" value="992010"></responseItem>
            <responseItem id="ActivityType" value="In Motion"></responseItem>
            <responseItem id="LastLatitude" value="43.59252"></responseItem>
            <responseItem id="LastLongitude" value="-111.137"></responseItem>
            <responseItem id="LastActivityDate" value="2013-01-17 20:43:50.0"></responseItem>
         </responseList>
         <responseList Code="2TS" Note="Test2">
             <responseItem id="DVN" value="992011"></responseItem>
             <responseItem id="ActivityType" value="Device Unplugged"></responseItem>
             <responseItem id="LastLatitude" value="43.50984"></responseItem>
             <responseItem id="LastLongitude" value="-112.0052"></responseItem>
             <responseItem id="LastActivityDate" value="2012-05-08 17:25:10.0"></responseItem>
         </responseList>
     </ResponseChild>
   </ResponseMain>
  </response></webServiceResponse>


Basically What i want to know is how i can get the data/records of a child inside another child. Thank you in advance!:)