def parse_xcu(raw, origin=u'%origin%'):
 ans = {}
 root = etree.fromstring(raw)
 for node in XPath(u'//prop[@oor:name="Format"]/value[text()="DICT_SPELL"]/../..')(root):
  value = XPath(u'descendant::prop[@oor:name="Locations"]/value')(node)
  if (len(value[0]) == 0):
   paths = u''.join(XPath(u'descendant::prop[@oor:name="Locations"]/value/text()')(node)).replace(u'%origin%', origin).split()
  else:
   paths = [c.text.replace(u'%origin%', origin) for v in value for c in v.iterchildren(u'*') if c.text]
  (aff, dic) = (paths if paths[0].endswith(u'.aff') else reversed(paths))
  locales = u''.join(XPath(u'descendant::prop[@oor:name="Locales"]/value/text()')(node)).split()
  ans[(dic, aff)] = locales
 return ans

def parse_xcu ( raw , origin = u'%origin%' ) : ans = { } root = etree . fromstring ( raw ) for node in XPath ( u'//prop[@oor:name="Format"]/value[text()="DICT_SPELL"]/../..' ) ( root ) : value = XPath ( u'descendant::prop[@oor:name="Locations"]/value' ) ( node ) if ( len ( value [ 0 ] ) == 0 ) : paths = u'' . join ( XPath ( u'descendant::prop[@oor:name="Locations"]/value/text()' ) ( node ) ) . replace ( u'%origin%' , origin ) . split ( ) else : paths = [ c . text . replace ( u'%origin%' , origin ) for v in value for c in v . iterchildren ( u'*' ) if c . text ] ( aff , dic ) = ( paths if paths [ 0 ] . endswith ( u'.aff' ) else reversed ( paths ) ) locales = u'' . join ( XPath ( u'descendant::prop[@oor:name="Locales"]/value/text()' ) ( node ) ) . split ( ) ans [ ( dic , aff ) ] = locales return ans
get the dictionary and affix file names as well as supported locales for each dictionary .