diff options
Diffstat (limited to 'util/local_database/xpathlite.py')
-rw-r--r-- | util/local_database/xpathlite.py | 113 |
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 |