summaryrefslogtreecommitdiffstats
path: root/util/local_database/xpathlite.py
diff options
context:
space:
mode:
Diffstat (limited to 'util/local_database/xpathlite.py')
-rw-r--r--util/local_database/xpathlite.py113
1 files changed, 82 insertions, 31 deletions
diff --git a/util/local_database/xpathlite.py b/util/local_database/xpathlite.py
index 7b5da5d..94bc23f 100644
--- a/util/local_database/xpathlite.py
+++ b/util/local_database/xpathlite.py
@@ -53,6 +53,11 @@ class DraftResolution:
contributed = 'contributed'
approved = 'approved'
+class Error:
+ def __init__(self, msg):
+ self.msg = msg
+ def __str__(self):
+ return self.msg
def findChild(parent, tag_name, arg_value, draft=None):
for node in parent.childNodes:
@@ -74,7 +79,7 @@ def findChild(parent, tag_name, arg_value, draft=None):
return node
return False
-def _findEntry(file, path, draft=None):
+def _findEntryInFile(file, path, draft=None, attribute=None):
doc = False
if doc_cache.has_key(file):
doc = doc_cache[file]
@@ -88,23 +93,47 @@ def _findEntry(file, path, draft=None):
if draft is not None:
last_entry = tag_spec_list[-1]
tag_spec_list = tag_spec_list[:-1]
- for tag_spec in tag_spec_list:
+ for i in range(len(tag_spec_list)):
+ tag_spec = tag_spec_list[i]
tag_name = tag_spec
arg_value = ''
left_bracket = tag_spec.find('[')
if left_bracket != -1:
tag_name = tag_spec[:left_bracket]
arg_value = tag_spec[left_bracket+1:-1]
+ alias = findChild(elt, 'alias', None)
+ if alias and alias.attributes['source'].nodeValue == 'locale':
+ path = alias.attributes['path'].nodeValue
+ aliaspath = tag_spec_list[:i] + path.split("/")
+ def resolve(x, y):
+ if y == '..':
+ return x[:-1]
+ return x + [y]
+ # resolve all dot-dot parts of the path
+ aliaspath = reduce(resolve, aliaspath, [])
+ # remove attribute specification that our xpathlite doesnt support
+ aliaspath = map(lambda x: x.replace("@type=", "").replace("'", ""), aliaspath)
+ # append the remaining path
+ aliaspath = aliaspath + tag_spec_list[i:]
+ aliaspath = "/".join(aliaspath)
+ # "locale" aliases are special - we need to start lookup from scratch
+ return (None, aliaspath)
elt = findChild(elt, tag_name, arg_value)
if not elt:
- return ""
+ return ("", None)
if last_entry is not None:
elt = findChild(elt, last_entry, '', draft)
if not elt:
- return ""
- return elt.firstChild.nodeValue
+ return ("", None)
+ if attribute is not None:
+ if elt.attributes.has_key(attribute):
+ return (elt.attributes[attribute].nodeValue, None)
+ return (None, None)
+ return (elt.firstChild.nodeValue, None)
def findAlias(file):
+ if not doc_cache.has_key(file):
+ return False
doc = doc_cache[file]
alias_elt = findChild(doc.documentElement, "alias", "")
if not alias_elt:
@@ -113,37 +142,59 @@ def findAlias(file):
return False
return alias_elt.attributes['source'].nodeValue
-def findEntry(base, path, draft=None):
- file = base + ".xml"
+def _findEntry(base, path, draft=None, attribute=None):
+ file = base
+ if base.endswith(".xml"):
+ file = base
+ base = base[:-4]
+ else:
+ file = base + ".xml"
+ (dirname, filename) = os.path.split(base)
+ items = filename.split("_")
+ # split locale name into items and iterate through them from back to front
+ # example: az_Latn_AZ => [az_Latn_AZ, az_Latn, az]
+ items = reversed(map(lambda x: "_".join(items[:x+1]), range(len(items))))
+ for item in items:
+ file = dirname + "/" + item + ".xml"
+ if os.path.isfile(file):
+ alias = findAlias(file)
+ if alias:
+ # if alias is found we should follow it and stop processing current file
+ # see http://www.unicode.org/reports/tr35/#Common_Elements
+ aliasfile = os.path.dirname(file) + "/" + alias + ".xml"
+ if not os.path.isfile(aliasfile):
+ raise Error("findEntry: fatal error: found an alias '%s' to '%s', but the alias file couldnt be found" % (filename, alias))
+ # found an alias, recurse into parsing it
+ result = _findEntry(aliasfile, path, draft, attribute)
+ return result
+ (result, aliaspath) = _findEntryInFile(file, path, draft, attribute)
+ if aliaspath:
+ # start lookup again because of the alias source="locale"
+ return _findEntry(base, aliaspath, draft, attribute)
+ if result:
+ return result
+ return None
+
+def findEntry(base, path, draft=None, attribute=None):
+ file = base
+ if base.endswith(".xml"):
+ file = base
+ base = base[:-4]
+ else:
+ file = base + ".xml"
+ (dirname, filename) = os.path.split(base)
- if os.path.isfile(file):
- result = _findEntry(file, path, draft)
+ result = None
+ while path:
+ result = _findEntry(base, path, draft, attribute)
if result:
return result
-
- alias = findAlias(file)
- if alias:
- file = os.path.dirname(base) + "/" + alias + ".xml"
- if os.path.isfile(file):
- result = _findEntry(file, path, draft)
- if result:
- return result
-
- file = base[:-3] + ".xml"
- if os.path.isfile(file):
- result = _findEntry(file, path, draft)
+ (result, aliaspath) = _findEntryInFile(dirname + "/root.xml", path, draft, attribute)
if result:
return result
- alias = findAlias(file)
- if alias:
- file = os.path.dirname(base) + "/" + alias + ".xml"
- if os.path.isfile(file):
- result = _findEntry(file, path, draft)
- if result:
- return result
+ if not aliaspath:
+ raise Error("findEntry: fatal error: %s: did not found key %s" % (filename, path))
+ path = aliaspath
- if not draft:
- file = os.path.dirname(base) + "/root.xml"
- result = _findEntry(file, path, draft)
return result