Need Help Parsing XML data

This is a legacy forum which is locked for new topics. New topics should be started in one of the other forums under Extending Indigo
Forum rules
This is a legacy forum which is locked for new topics. New topics should be started in one of the other forums under Extending Indigo
BillC
Posts: 238
Joined: Sun Mar 09, 2008 4:51 pm

Need Help Parsing XML data

Post by BillC »

Absolute novice at Python here.

I'm attempting to build a plug-in that will create a device and extract XML data from an internal web page...very similar to the NOAA plugin, which I'm using as a model. Although the XML data resides on an internal server, it's an embedded device* and I have no control over the data format. I've read the XML DOM documentation and am still lost, but I think I've identified the problem. The problem is that the XML data is formatted differently from the NOAA sites, and I can't figure out how to code the parsing.

I can access the data in two forms:

Code: Select all

<Devices>
   <Device Name="Date" Value="12/17/2011"/>
   <Device Name="Time" Value="08:37:45"/>
   <Device Name="HP_Fan" Value="1.000000"/>
   <Device Name="PropaneHeating" Value="0.000000"/>
   <Device Name="HP_Defrost" Value="0.000000"/>
   <Device Name="HP_VaporT" Value="132.574996"/>
   <Device Name="HP_LiquidT" Value="69.912498"/>
   <Device Name="HP_Cooling" Value="0.000000"/>
   <Device Name="HP_Heating" Value="1.000000"/>
</Devices>
or

Code: Select all

<devices>
  <device>
      <name>date</name>
      <value>12/17/2011</value>
  </device>
  <device>
      <name>time</name>
      <value>10:24:54</value>
  </device>
{....etc....]
</devices>
The code in the NOAA script fails (I get "-data unavailable-" for all elements).

Code: Select all

for state,fieldName in fields.iteritems():
				try:
					newValue = theDocTree.getElementsByTagName(fieldName)[0].childNodes[0].data
				except IndexError:
					newValue = "- data unavailable -"
				self.updateDeviceState(device, state, newValue)
I'm pretty sure that the problem is due to the different structure. Would appreciate help with a code segment that will work on either of the data structures I have available (the first one seems simpler but can use either).


* the device is a "Web Energy Logger" that provides 1-wire access to, among other things, thermostat "calls" beyond those that the Insteon/Venstar interface is capable of accessing. http://www.welserver.com/
User avatar
jay (support)
Site Admin
Posts: 19232
Joined: Wed Mar 19, 2008 11:52 am
Location: Austin, Texas
Contact:

Re: Need Help Parsing XML data

Post by jay (support) »

The NOAA plugin looks up fields from a dictionary that maps the XML field name to the device state (specified in the Devices.xml). I don't think that pattern will work for you because it looks like each "Device" is, in fact, a different device, not just states on the same device (though I could be wrong).

The NOAA XML feed is quite flat and doesn't have repetitive elements. Your feed has multiple elements of the same name (either "Device" or "device" depending on which feed you use). So, you'll need to get all "Device" elements from the top-level element ("Devices"). Then iterate over those elements pulling out the "Name" and "Value" attributes.

The rough sequence of events would be (using the first XML feed as an example):
  1. parse the tree into a DOM object (the parseString() method in the NOAA plugin as example)
  2. call the getElementsByTagName('Device') method on the DOM objectwhich will return a list of the 'Device' elements
  3. for each of those returned device elements, call getAttribute('Name') and getAttribute('Value'). Those will return the name string and value string respectively.
So, for each "Device" element, you now have the name and value. I'm not sure what you want to do with that data - you could look to see if a device with that name exists and if so update a state with the value and if not create the device.
Jay (Indigo Support)
Twitter | Facebook | LinkedIn
BillC
Posts: 238
Joined: Sun Mar 09, 2008 4:51 pm

Re: Need Help Parsing XML data

Post by BillC »

Jay, thanks very much. This code works, with one exception:

Code: Select all

for state,fieldName in fields.iteritems():
			try:
				for node in theDocTree.getElementsByTagName("Device"):
					name = node.getAttribute("Name")
					value = node.getAttribute("Value")
					if name == fieldName:
						newValue = value
			except IndexError:
				newValue = "- data unavailable -"
			self.updateDeviceState(device, state, newValue)
I'm using the data in the same way as that in the NOAA plugin...making it available in an Indigo Device for triggers and control pages...the NOAA code works very well.

I now have one remaining problem: Fixed, my error.

Thanks again.
User avatar
jay (support)
Site Admin
Posts: 19232
Joined: Wed Mar 19, 2008 11:52 am
Location: Austin, Texas
Contact:

Re: Need Help Parsing XML data

Post by jay (support) »

I don't see anything in the code that's trying to treat it as anything but a string (you'd have to explicitly convert it to another data type). Try inserting an indigo.server.log statement after you get the value to see what the value is at that point.

Also - just a bit of an efficiency thought: you might want to go through the inner for loop first - building a temp dictionary of name:value entries - then, iterate through fields getting the appropriate value out of the temp dictionary. That way you aren't looping through every "Device" element for each entry in fields.
Jay (Indigo Support)
Twitter | Facebook | LinkedIn
Locked

Return to “Extending Indigo with Plugins and Python”