Updates the attributes of the specified XML tag using the globals
    dictionary for those tags that are supported.

def _update_from_globals(xtag, xmlglobals, container):
    """Updates the attributes of the specified XML tag using the globals
    dictionary for those tags that are supported.
    """
    #We also need to perform a globals update on each of the *original* child tags
    #in the current tag being updated.
    for child in list(xtag):
        _update_from_globals(child, xmlglobals, xtag)

    #If the tag doesn't have a value that is in the global defaults
    #then we automatically copy it over.
    if "defaults" in xmlglobals:
        #Iterate over the attributes that we have default values for.
        for key in xmlglobals["defaults"]:
            if key not in xtag.attrib:
                overwrite = True
                #If the key is a limited one, then it only gets copied to
                #tags that we know can actually use the attribute.
                if key in limited:
                    overwrite = (xtag.tag in monitored and key in monitored[xtag.tag])
                if overwrite:
                    xtag.attrib[key] = xmlglobals["defaults"][key]

    #For the global tags, we just want to update using the default values
    #They aren't allowed to reference other globals.
    if container is None:
        return                
                    
    def update_tag(xtag, gtag):
        """Updates the missing attributes in xtag with those from gtag."""
        for attr, value in gtag.attr.items():
            if attr not in xtag.attrib:
                xtag.attr[attr] = value
                
    def resolve_global(xtag, xmlglobals, xtagname, gtagname, attrib, container, op, gassumed):
        """Adds the child in xmlglobals with the relevant id to the tag.

        :arg xtag: the tag with the reference to a global tag.
        :arg xmlglobals: the dictionary of global tags extracted from <global>.
        :arg tagname: the name of the global tag to look for.
        :arg attrib: the name of the attribute in 'xtag' that references the
          global tag to process.
        :arg container: for "op"=="append", the XMLElement to append the global
          tag to as a subelement.
        :arg op: one of ["append", "update"]. For "append" the global tag is appended
          as a subelement to 'container'. For "update", the attributes of the global
          tag are copied to 'xtag'.
        :arg gassumed: when True, the 'attrib' being examined is assumed to reference
          only tags in <globals>, so no 'global:' prefix is required before attributes.
        """
        if attrib not in xtag.attrib:
            return False

        result = False
        if xtag.tag == xtagname and (gassumed or "global:" in xtag.attrib[attrib]):
            #We allow a ';'-separated list of global tag names, all of
            #which are appended to the child's subelements list.
            i = -1
            for sattr in xtag.attrib[attrib].split(";"):
                gid = sattr.strip().split(":")[1] if ":" in sattr else sattr.strip()
                #Since ordering matters, if the id starts with ^, we insert it at
                #the beginning of the subelements list instead of appending
                if gid[0] == '^':
                    insert = True
                    gid = gid[1::]
                    i += 1
                else:
                    insert = False
                    
                if gtagname in xmlglobals and gid.lower() in xmlglobals[gtagname]:
                    gtag = xmlglobals[gtagname][gid.lower()]
                    if op == "append":
                        if insert:
                            container.insert(i, gtag)
                        else:
                            container.append(gtag)
                    elif op == "update":
                        update_tag(xtag, gtag)
                    result = True
                else:
                    from fortpy.msg import warn
                    wstr = 'The global tag of type <{}> for <{} {}="{}"> does not exist.'
                    warn(wstr.format(gtagname, xtagname, attrib, xtag.attrib[attrib]))

            #Overwrite the name of the tag to not have the 'global:' in it anymore.
            xtag.attrib[attrib] = xtag.attrib[attrib].replace("global:", "")

        return result
                
    #Next, we just need to check the attributes of the tag that are allowed
    #to point to global tag children.
    i = 0
    #The order of these is xtagname, gtagname, xtagattrib, container, op, gassumed
    tags = [("assignment", "value", "value", xtag, "append", False),
            ("target", "output", "compareto", container, "append", False),
            ("test", "input", "inputs", xtag, "append", True),
            ("test", "global", "globals", xtag, "append", True),
            ("test", "assignment", "assignments", xtag, "append", True),
            ("test", "mapping", "mappings", xtag, "append", True),
            ("group", "input", "inputs", xtag, "append", True),
            ("group", "global", "globals", xtag, "append", True),
            ("group", "assignment", "assignments", xtag, "append", True),
            ("group", "mapping", "mappings", xtag, "append", True)]

    while i < len(tags):
        resolve_global(xtag, xmlglobals, *tags[i])
        i += 1

    if xtag.tag in ["test", "group"]:
        _handle_ignores(xtag)

    if xtag.tag == "auto":
        _expand_autotag(xtag, container)