def _qname_matches(tag, namespace, qname):
    """Logic determines if a QName matches the desired local tag and namespace.

    This is used in XmlElement.get_elements and XmlElement.get_attributes to
    find matches in the element's members (among all expected-and-unexpected
    elements-and-attributes).

    Args:
      expected_tag: string
      expected_namespace: string
      qname: string in the form '{xml_namespace}localtag' or 'tag' if there is
             no namespace.

    Returns:
      boolean True if the member's tag and namespace fit the expected tag and
      namespace.
    """
    # If there is no expected namespace or tag, then everything will match.
    if qname is None:
        member_tag = None
        member_namespace = None
    else:
        if qname.startswith('{'):
            member_namespace = qname[1:qname.index('}')]
            member_tag = qname[qname.index('}') + 1:]
        else:
            member_namespace = None
            member_tag = qname
    return ((tag is None and namespace is None)
            # If there is a tag, but no namespace, see if the local tag
            # matches.
            or (namespace is None and member_tag == tag)
            # There was no tag, but there was a namespace so see if the namespaces
            # match.
            or (tag is None and member_namespace == namespace)
            # There was no tag, and the desired elements have no namespace, so check
            # to see that the member's namespace is None.
            or (tag is None and namespace == ''
                and member_namespace is None)
            # The tag and the namespace both match.
            or (tag == member_tag
                and namespace == member_namespace)
            # The tag matches, and the expected namespace is the empty namespace,
            # check to make sure the member's namespace is None.
            or (tag == member_tag and namespace == ''
                and member_namespace is None))