Get values form XML using ElementTree

I’m trying to get values from a XML file like this:

<?xml version="1.0"?>
<DeviceStorage xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Objects>
<Object Type="OBJECT_ANALOG_OUTPUT" Instance="5">
<Properties>
<Property Id="PROP_OBJECT_IDENTIFIER" Tag="BACNET_APPLICATION_TAG_OBJECT_ID">
<Value>OBJECT_ANALOG_OUTPUT:5</Value>
</Property>
<Property Id="PROP_OBJECT_NAME" Tag="BACNET_APPLICATION_TAG_CHARACTER_STRING">
<Value>B'JC2415'DUV'Y1</Value>
</Property>
<Property Id="PROP_OBJECT_TYPE" Tag="BACNET_APPLICATION_TAG_ENUMERATED">
<Value>1</Value>
</Property>
<Property Id="3006" Tag="BACNET_APPLICATION_TAG_ENUMERATED">
<Value>3</Value>
</Property>
<Property Id="PROP_DESCRIPTION" Tag="BACNET_APPLICATION_TAG_CHARACTER_STRING">
<Value>Analog out Y1</Value>
</Property>
<Property Id="3001" Tag="BACNET_APPLICATION_TAG_OBJECT_ID">
<Value>201:54</Value>
</Property>
<Property Id="PROP_PROFILE_NAME" Tag="BACNET_APPLICATION_TAG_CHARACTER_STRING">
<Value>7-BA-PX-AO-SBCv10.02</Value>
</Property>
<Property Id="3121" Tag="BACNET_APPLICATION_TAG_CHARACTER_STRING">
<Value>Building</Value>
<Value>JET-C2.4-15</Value>
<Value>DUV</Value>
<Value>Analog out Y1</Value>
</Property>
<Property Id="3234" Tag="BACNET_APPLICATION_TAG_CHARACTER_STRING">
<Value>B'JC2415'DUV'Y1</Value>
</Property>
<Property Id="PROP_PRESENT_VALUE" Tag="BACNET_APPLICATION_TAG_REAL">
<Value>0</Value>
</Property>
<Property Id="PROP_STATUS_FLAGS" Tag="BACNET_APPLICATION_TAG_BIT_STRING">
<Value>0000</Value>
</Property>
<Property Id="PROP_EVENT_STATE" Tag="BACNET_APPLICATION_TAG_ENUMERATED">
<Value>0</Value>
</Property>
<Property Id="PROP_RELIABILITY" Tag="BACNET_APPLICATION_TAG_ENUMERATED">
<Value>0</Value>
</Property>
<Property Id="PROP_OUT_OF_SERVICE" Tag="BACNET_APPLICATION_TAG_BOOLEAN">
<Value>False</Value>
</Property>
<Property Id="PROP_UNITS" Tag="BACNET_APPLICATION_TAG_ENUMERATED">
<Value>98</Value>
</Property>
<Property Id="PROP_RESOLUTION" Tag="BACNET_APPLICATION_TAG_REAL">
<Value>0.1</Value>
</Property>
<Property Id="PROP_PRIORITY_ARRAY" Tag="BACNET_APPLICATION_TAG_NULL">
<Value />
<Value />
<Value />
<Value />
<Value />
<Value />
<Value />
<Value />
<Value />
<Value />
<Value />
<Value />
<Value />
<Value />
<Value />
<Value />
</Property>
<Property Id="PROP_RELINQUISH_DEFAULT" Tag="BACNET_APPLICATION_TAG_REAL">
<Value>0</Value>
</Property>
<Property Id="PROP_COV_INCREMENT" Tag="BACNET_APPLICATION_TAG_REAL">
<Value>0.1</Value>
</Property>
<Property Id="PROP_TIME_DELAY" Tag="BACNET_APPLICATION_TAG_UNSIGNED_INT">
<Value>1</Value>
</Property>
<Property Id="PROP_NOTIFICATION_CLASS" Tag="BACNET_APPLICATION_TAG_UNSIGNED_INT">
<Value>32</Value>
</Property>
<Property Id="PROP_HIGH_LIMIT" Tag="BACNET_APPLICATION_TAG_REAL">
<Value>100</Value>
</Property>
<Property Id="PROP_LOW_LIMIT" Tag="BACNET_APPLICATION_TAG_REAL">
<Value>0</Value>
</Property>
<Property Id="PROP_DEADBAND" Tag="BACNET_APPLICATION_TAG_REAL">
<Value>0.5</Value>
</Property>
<Property Id="PROP_LIMIT_ENABLE" Tag="BACNET_APPLICATION_TAG_BIT_STRING">
<Value>11</Value>
</Property>
<Property Id="PROP_EVENT_ENABLE" Tag="BACNET_APPLICATION_TAG_BIT_STRING">
<Value>111</Value>
</Property>
<Property Id="PROP_ACKED_TRANSITIONS" Tag="BACNET_APPLICATION_TAG_BIT_STRING">
<Value>111</Value>
</Property>
<Property Id="PROP_NOTIFY_TYPE" Tag="BACNET_APPLICATION_TAG_ENUMERATED">
<Value>0</Value>
</Property>
<Property Id="PROP_EVENT_TIME_STAMPS" Tag="BACNET_APPLICATION_TAG_CONTEXT_SPECIFIC_DECODED">
<Value>1/1/0001 12:00:00 AM;1/1/0001 12:00:00 AM</Value>
<Value>1/1/0001 12:00:00 AM;1/1/0001 12:00:00 AM</Value>
<Value>1/1/0001 12:00:00 AM;1/1/0001 12:00:00 AM</Value>
</Property>
<Property Id="PROP_DEVICE_TYPE" Tag="BACNET_APPLICATION_TAG_CHARACTER_STRING">
<Value />
</Property>
<Property Id="3000" Tag="BACNET_APPLICATION_TAG_CHARACTER_STRING">
<Value />
</Property>
<Property Id="3005" Tag="BACNET_APPLICATION_TAG_ENUMERATED">
<Value>4</Value>
</Property>
<Property Id="3059" Tag="BACNET_APPLICATION_TAG_ENUMERATED">
<Value>81</Value>
<Value>6</Value>
<Value>3</Value>
<Value>3</Value>
<Value>104</Value>
<Value>4</Value>
<Value>3</Value>
<Value>3</Value>
<Value>35</Value>
<Value>10</Value>
<Value>1</Value>
<Value>1</Value>
<Value>36</Value>
<Value>5</Value>
<Value>1</Value>
<Value>0</Value>
<Value>130</Value>
<Value>5</Value>
<Value>1</Value>
<Value>0</Value>
<Value>3011</Value>
<Value>10</Value>
<Value>3</Value>
<Value>3</Value>
<Value>45</Value>
<Value>10</Value>
<Value>5</Value>
<Value>5</Value>
<Value>59</Value>
<Value>10</Value>
<Value>5</Value>
<Value>5</Value>
<Value>25</Value>
<Value>10</Value>
<Value>1</Value>
<Value>1</Value>
<Value>113</Value>
<Value>4</Value>
<Value>3</Value>
<Value>3</Value>
<Value>3122</Value>
<Value>10</Value>
<Value>3</Value>
<Value>3</Value>
<Value>3114</Value>
<Value>10</Value>
<Value>3</Value>
<Value>3</Value>
<Value>17</Value>
<Value>7</Value>
<Value>3</Value>
<Value>0</Value>
<Value>72</Value>
<Value>10</Value>
<Value>5</Value>
<Value>0</Value>
<Value>3243</Value>
<Value>7</Value>
<Value>3</Value>
<Value>0</Value>
<Value>0</Value>
<Value>5</Value>
<Value>1</Value>
<Value>0</Value>
<Value>3014</Value>
<Value>5</Value>
<Value>3</Value>
<Value>0</Value>
<Value>3015</Value>
<Value>5</Value>
<Value>3</Value>
<Value>0</Value>
<Value>3019</Value>
<Value>8</Value>
<Value>5</Value>
<Value>3</Value>
<Value>3017</Value>
<Value>4</Value>
<Value>1</Value>
<Value>1</Value>
<Value>3018</Value>
<Value>4</Value>
<Value>1</Value>
<Value>1</Value>
<Value>3123</Value>
<Value>4</Value>
<Value>3</Value>
<Value>3</Value>
<Value>3124</Value>
<Value>3</Value>
<Value>5</Value>
<Value>5</Value>
<Value>3023</Value>
<Value>8</Value>
<Value>5</Value>
<Value>3</Value>
<Value>3054</Value>
<Value>4</Value>
<Value>1</Value>
<Value>1</Value>
<Value>3055</Value>
<Value>4</Value>
<Value>1</Value>
<Value>1</Value>
<Value>3126</Value>
<Value>8</Value>
<Value>5</Value>
<Value>5</Value>
<Value>3021</Value>
<Value>8</Value>
<Value>3</Value>
<Value>3</Value>
<Value>52</Value>
<Value>10</Value>
<Value>5</Value>
<Value>5</Value>
<Value>85</Value>
<Value>2</Value>
<Value>5</Value>
<Value>5</Value>
<Value>3211</Value>
<Value>2</Value>
<Value>5</Value>
<Value>0</Value>
<Value>3210</Value>
<Value>5</Value>
<Value>0</Value>
<Value>0</Value>
<Value>111</Value>
<Value>5</Value>
<Value>5</Value>
<Value>0</Value>
<Value>103</Value>
<Value>5</Value>
<Value>5</Value>
<Value>1</Value>
<Value>87</Value>
<Value>5</Value>
<Value>3</Value>
<Value>0</Value>
<Value>3236</Value>
<Value>1</Value>
<Value>3</Value>
<Value>0</Value>
</Property>
<Property Id="3074" Tag="BACNET_APPLICATION_TAG_ENUMERATED">
<Value>5</Value>
</Property>
<Property Id="3126" Tag="BACNET_APPLICATION_TAG_UNSIGNED_INT">
<Value>0</Value>
</Property>
<Property Id="3008" Tag="BACNET_APPLICATION_TAG_REAL">
<Value>0</Value>
</Property>
<Property Id="3009" Tag="BACNET_APPLICATION_TAG_REAL">
<Value>100</Value>
</Property>
<Property Id="3114" Tag="BACNET_APPLICATION_TAG_UNSIGNED_INT">
<Value>3</Value>
</Property>
<Property Id="3211" Tag="BACNET_APPLICATION_TAG_REAL">
<Value>0</Value>
</Property>
<Property Id="3011" Tag="BACNET_APPLICATION_TAG_BOOLEAN">
<Value>False</Value>
</Property>
<Property Id="3014" Tag="BACNET_APPLICATION_TAG_DATETIME">
<Value>1/1/0001 12:00:00 AM</Value>
</Property>
<Property Id="3015" Tag="BACNET_APPLICATION_TAG_CHARACTER_STRING">
<Value />
</Property>
<Property Id="3016" Tag="BACNET_APPLICATION_TAG_NULL" />
<Property Id="3019" Tag="BACNET_APPLICATION_TAG_CHARACTER_STRING">
<Value>T=1.1</Value>
</Property>
<Property Id="3017" Tag="BACNET_APPLICATION_TAG_REAL">
<Value>100</Value>
</Property>
<Property Id="3018" Tag="BACNET_APPLICATION_TAG_REAL">
<Value>0</Value>
</Property>
<Property Id="3021" Tag="BACNET_APPLICATION_TAG_ENUMERATED">
<Value>2</Value>
</Property>
<Property Id="3023" Tag="BACNET_APPLICATION_TAG_CHARACTER_STRING">
<Value />
</Property>
<Property Id="3054" Tag="BACNET_APPLICATION_TAG_REAL">
<Value>0.01</Value>
</Property>
<Property Id="3055" Tag="BACNET_APPLICATION_TAG_REAL">
<Value>0</Value>
</Property>
<Property Id="3210" Tag="BACNET_APPLICATION_TAG_BOOLEAN">
<Value>False</Value>
</Property>
<Property Id="3123" Tag="BACNET_APPLICATION_TAG_UNSIGNED_INT">
<Value>0</Value>
</Property>
<Property Id="3124" Tag="BACNET_APPLICATION_TAG_REAL">
<Value>0</Value>
</Property>
<Property Id="3122" Tag="BACNET_APPLICATION_TAG_UNSIGNED_INT">
<Value>2</Value>
</Property>
<Property Id="3212" Tag="BACNET_APPLICATION_TAG_REAL">
<Value>0.1</Value>
</Property>
<Property Id="PROP_MAX_PRES_VALUE" Tag="BACNET_APPLICATION_TAG_REAL">
<Value>100</Value>
</Property>
<Property Id="PROP_MIN_PRES_VALUE" Tag="BACNET_APPLICATION_TAG_REAL">
<Value>0</Value>
</Property>
<Property Id="3236" Tag="BACNET_APPLICATION_TAG_BOOLEAN">
<Value>False</Value>
</Property>
<Property Id="3243" Tag="BACNET_APPLICATION_TAG_BOOLEAN">
<Value>False</Value>
</Property>
</Properties>
</Object>
</Objects>
</DeviceStorage>

It has multiple <Object> </Object> pairs. My code can get the tag but can’t get the value inside <Value></Value>

import xml.etree.ElementTree as ET
xmlfile = 'AS01.xml'
tree = ET.parse(xmlfile)
root = tree.getroot()
lst = tree.findall('Objects/Object/Properties')
for item in lst:
for prop in item:
obj_tag = prop.attrib['Tag']
obj_value = prop.get('Value')
print(obj_tag, obj_value)

For each <Object> I need the values for Type and Instance:

<Object Type="OBJECT_ANALOG_OUTPUT" Instance="5">
OBJECT_ANALOG_OUTPUT
5

And several values based on Property Id, for example:

<Property Id="PROP_OBJECT_NAME" Tag="BACNET_APPLICATION_TAG_CHARACTER_STRING"><Value>B'JC2415'DUV'Y1</Value>
PROP_OBJECT_NAME
B'JC2415'DUV'Y1

Any suggestion how to solve this problem?

EDIT:

This is how I solved the problem. I’s not nice, but works for me:

import xml.etree.ElementTree as ET
xmlfile = 'AS01.xml'
tree = ET.parse(xmlfile)
root = tree.getroot()
PROP_OBJECT_IDENTIFIER = ''
PROP_OBJECT_NAME = ''
PROP_DESCRIPTION = ''
BACNET_APPLICATION_TAG_CHARACTER_STRING = ''
def format_string(obj_ident, obj_name,obj_desc,obj_addr):
# Format the recovered values so I can pipe them into CSV files
OBJECT_IDENTIFIER=''
OBJECT_INSTANCE=''
OBJECT_PATH=''
OBJECT_NAME=''
OBJECT_BUS=''
OBJECT_ADDR=''
str_colon = ':'
str_apo = '''
str_eq = '='
if str_colon in obj_ident:                      # Separate Identifier and instance number
cnt = obj_ident.rfind(str_colon)
cntp = cnt+1
OBJECT_IDENTIFIER = obj_ident[0:cnt]
OBJECT_INSTANCE = obj_ident[cntp:]
if str_apo in obj_name:                         # Separate object path and name
cnt = obj_name.rfind(str_apo)
cntp = cnt+1
OBJECT_PATH = obj_name[0:cnt]
OBJECT_NAME = obj_name[cntp:]
if str_eq in obj_addr:                          # Separate address type and the actual addres
cnt = obj_addr.rfind(str_eq)
cntp = cnt+1
OBJECT_BUS = obj_addr[0:cnt]
OBJECT_ADDR = obj_addr[cntp:]
print(OBJECT_IDENTIFIER,',',OBJECT_INSTANCE,',',OBJECT_PATH,',',OBJECT_NAME,',',OBJECT_BUS,',',OBJECT_ADDR,',',obj_desc)
for obj in tree.findall('Objects/Object'):
for prop in obj.findall('Properties/Property'):
obj_id = prop.attrib['Id']
obj_tag = prop.attrib['Tag']
lst = prop.findall('Value')                 # Check for Value field
lst_count = len(lst)                    
if lst_count > 0:                           # If Value field exists
obj_value = prop.find('Value').text
elif lst_count == 0:                        # If Value field is missing
obj_value = ''
if obj_id == 'PROP_OBJECT_IDENTIFIER':      # Select only the necessary objects
PROP_OBJECT_IDENTIFIER = obj_value
if obj_id == 'PROP_OBJECT_NAME':
PROP_OBJECT_NAME = obj_value
if obj_id == 'PROP_DESCRIPTION':
PROP_DESCRIPTION = obj_value
if obj_id == '3019':
BACNET_APPLICATION_TAG_CHARACTER_STRING = obj_value
format_string(PROP_OBJECT_IDENTIFIER,PROP_OBJECT_NAME,PROP_DESCRIPTION,BACNET_APPLICATION_TAG_CHARACTER_STRING)
PROP_OBJECT_IDENTIFIER = ''
PROP_OBJECT_NAME = ''
PROP_DESCRIPTION = ''
BACNET_APPLICATION_TAG_CHARACTER_STRING = ''

Output:

OBJECT_ANALOG_OUTPUT , 5 , B'JC2415'DUV , Y1 , T , 1.1 , Analog out Y1
OBJECT_ANALOG_OUTPUT , 6 , B'JC2415'DUV , Y2 , T , 1.2 , Analog out Y2
OBJECT_ANALOG_OUTPUT , 7 , B'JC2415'PVV , Y1 , T , 1.3 , Analog out Y1
OBJECT_ANALOG_OUTPUT , 8 , B'JC2415'PVV , Y2 , T , 1.4 , Analog out Y2

Answer

Not sure I get the question correctly but for the values I would go for:

values = [i.text for i in tree.findall('.//*/Value')]

and for the “Object” properties:

types=[i.get('Type') for i in tree.findall('.//*Object/[@Type]')]
instances=[i.get('Instance') for i in a.findall('.//*Object/[@Instance]')]