Cracking XML or HTML with regular expressions can be an exercise in futility. Pyparsing includes an expression-builder helper method, makeHTMLTags, that will make very real-world tolerant parsers and will generate dict-like return values.
from pyparsing import *
dynTag,endDyn = makeHTMLTags("dyn")
sample = """
<dyn type="dataFrame" name="Main Map" property="reference scale"/>
<dyn type="dataFrame" name="Main Map" property="time"/>
<dyn type="page" property="name"/>
<dyn type="page" property="number"/>
<dyn type="page" property="index"/>
<dyn type="page" property="count"/>
<dyn type="page" property="attribute" field="<Field Name>" domainlookup="true"/>
<dyn type="page" property="attribute" field="<Field Name>" />
"""
import pprint
for dyn in dynTag.searchString(sample):
pprint.pprint(dyn.asDict())
if "domainlookup" in dyn:
print "domainlookup =",dyn.domainlookup
print
Parsing your sample gives:
{'empty': True,
'name': 'Main Map',
'property': 'reference scale',
'startDyn': (['dyn', (['type', 'dataFrame'], {}), (['name', 'Main Map'], {}), (['property', 'reference scale'], {}), True], {'type': [('dataFrame', 1)], 'property': [('reference scale', 3)], 'tag': [('dyn', 0)], 'name': [('Main Map', 2)], 'empty': [(True, 4)]}),
'tag': 'dyn',
'type': 'dataFrame'}
{'empty': True,
'name': 'Main Map',
'property': 'time',
'startDyn': (['dyn', (['type', 'dataFrame'], {}), (['name', 'Main Map'], {}), (['property', 'time'], {}), True], {'type': [('dataFrame', 1)], 'property': [('time', 3)], 'tag': [('dyn', 0)], 'name': [('Main Map', 2)], 'empty': [(True, 4)]}),
'tag': 'dyn',
'type': 'dataFrame'}
{'empty': True,
'property': 'name',
'startDyn': (['dyn', (['type', 'page'], {}), (['property', 'name'], {}), True], {'type': [('page', 1)], 'property': [('name', 2)], 'tag': [('dyn', 0)], 'empty': [(True, 3)]}),
'tag': 'dyn',
'type': 'page'}
{'empty': True,
'property': 'number',
'startDyn': (['dyn', (['type', 'page'], {}), (['property', 'number'], {}), True], {'type': [('page', 1)], 'property': [('number', 2)], 'tag': [('dyn', 0)], 'empty': [(True, 3)]}),
'tag': 'dyn',
'type': 'page'}
{'empty': True,
'property': 'index',
'startDyn': (['dyn', (['type', 'page'], {}), (['property', 'index'], {}), True], {'type': [('page', 1)], 'property': [('index', 2)], 'tag': [('dyn', 0)], 'empty': [(True, 3)]}),
'tag': 'dyn',
'type': 'page'}
{'empty': True,
'property': 'count',
'startDyn': (['dyn', (['type', 'page'], {}), (['property', 'count'], {}), True], {'type': [('page', 1)], 'property': [('count', 2)], 'tag': [('dyn', 0)], 'empty': [(True, 3)]}),
'tag': 'dyn',
'type': 'page'}
{'domainlookup': 'true',
'empty': True,
'field': '<Field Name>',
'property': 'attribute',
'startDyn': (['dyn', (['type', 'page'], {}), (['property', 'attribute'], {}), (['field', '<Field Name>'], {}), (['domainlookup', 'true'], {}), True], {'field': [('<Field Name>', 3)], 'tag': [('dyn', 0)], 'domainlookup': [('true', 4)], 'property': [('attribute', 2)], 'type': [('page', 1)], 'empty': [(True, 5)]}),
'tag': 'dyn',
'type': 'page'}
domainlookup = true
{'empty': True,
'field': '<Field Name>',
'property': 'attribute',
'startDyn': (['dyn', (['type', 'page'], {}), (['property', 'attribute'], {}), (['field', '<Field Name>'], {}), True], {'field': [('<Field Name>', 3)], 'property': [('attribute', 2)], 'tag': [('dyn', 0)], 'empty': [(True, 4)], 'type': [('page', 1)]}),
'tag': 'dyn',
'type': 'page'}
Note that the resulting ParseResults structures will let you access the parsed attributes like object attributes (dyn.domainlookup) or dict keys (dyn["domainlookup"]).