Parse a UNTL XML file object into a pyuntl element tree.

    You can also pass this a string as file input like so:
    import StringIO
    untlxml2py(StringIO.StringIO(untl_string))
774069
def untlxml2py(untl_filename):
    
    # Create a stack to hold parents.
    parent_stack = []
    # Use iterparse to open the file and loop through elements.
    for event, element in iterparse(untl_filename, events=('start', 'end')):
        if NAMESPACE_REGEX.search(element.tag, 0):
            element_tag = NAMESPACE_REGEX.search(element.tag, 0).group(1)
        else:
            element_tag = element.tag
        # Process the element if it exists in UNTL.
        if element_tag in PYUNTL_DISPATCH:
            # If it is the element's opening tag,
            # add it to the parent stack.
            if event == 'start':
                parent_stack.append(PYUNTL_DISPATCH[element_tag]())
            # If it is the element's closing tag,
            # remove element from stack. Add qualifier and content.
            elif event == 'end':
                child = parent_stack.pop()
                if element.text is not None:
                    content = element.text.strip()
                    if content != '':
                        child.set_content(element.text)
                if element.get('qualifier', False):
                    child.set_qualifier(element.get('qualifier'))

                # Add the element to its parent.
                if len(parent_stack) > 0:
                    parent_stack[-1].add_child(child)
                # If it doesn't have a parent, it is the root element,
                # so return it.
                else:
                    return child
        else:
            raise PyuntlException(
                'Element "%s" not in UNTL dispatch.' % (element_tag)
            )
1113681
def parsetuple(self,xmltuple):
    
    # first extract all the table and columns from the tuple from the
    # children of the ligo lightweight parent tuple
    table = {}
    tupleidx = 0
    for tag in xmltuple[2]:
      if tag[0] == 'Table' or tag[0] == 'table':
        tab = tag[1]['Name'].encode('ascii').lower()
        try:
          tab = self.tabrx.match(tab).group(2)
        except AttributeError:
          raise LIGOLwParseError, 'unable to parse a valid table name '+tab
        # initalize the table dictionary for this table
        table[tab] = { 
          'pos' : tupleidx,
          'column' : {},
          'stream' : (), 
          'query' : ''
          }
        # parse for columns in the tables children
        # look for the column name and type in the attributes
        # store the index in which the columns were found as
        # we need this to decode the stream later
        for subtag in tag[2]:
          if subtag[0] == 'Column' or subtag[0] == 'column':
            col = subtag[1]['Name'].encode('ascii').lower()
            try:
              col = self.colrx.match(col).group(3)
            except AttributeError:
              raise LIGOLwParseError, 'unable to parse a valid column name '+col
            try:
              typ = subtag[1]['Type'].encode('ascii').lower()
            except KeyError:
              raise LIGOLwParseError, 'type is missing for column '+col
            table[tab]['column'][col] = typ
            table[tab].setdefault('orderedcol',[]).append(col)
      tupleidx += 1

    # now iterate the dictionary of tables we have created looking for streams
    for tab in table.keys():
      for tag in xmltuple[2][table[tab]['pos']][2]:
        if tag[0] == 'Stream' or tag[0] == 'stream':
          # store the stream delimiter and create the esacpe regex
          try:
            delim = tag[1]['Delimiter'].encode('ascii')
          except KeyError:
            raise LIGOLwParseError, 'stream is missing delimiter'
          if delim != ',':
            raise LIGOLwParseError, 'unable to handle stream delimiter: '+delim

          # If the result set is empty tag[2] is an empty array, which causes
          # the next step to fail.  Add an empty string in this case.
          if len(tag[2]) == 0:
            tag[2].append("")


          # strip newlines from the stream and parse it
          stream = csv.reader([re.sub(r'\n','',tag[2][0])],LIGOLWStream).next()

          # turn the csv stream into a list of lists
          slen = len(stream)
          ntyp = len(table[tab]['column'])
          mlen, lft = divmod(slen,ntyp)
          if lft != 0:
            raise LIGOLwParseError, 'invalid stream length for given columns'
          lst = [[None] * ntyp for i in range(mlen)]

          # translate the stream data to the correct data types
          for i in range(slen):
            j, k = divmod(i,ntyp)
            try:
              thiscol = table[tab]['orderedcol'][k]
              if len( stream[i] ) == 0:
                lst[j][k] = None
              else:
                lst[j][k] = self.types[table[tab]['column'][thiscol]](stream[i])
            except (KeyError, ValueError), errmsg:
              msg = "stream translation error (%s) " % str(errmsg)
              msg += "for column %s in table %s: %s -> %s" \
                % (tab,thiscol,stream[i],str(table[tab])) 
              raise LIGOLwParseError, msg
          table[tab]['stream'] = map(tuple,lst)

    # return the created table to the caller
    return table
480752
def _parse_xml(self):
        
        import xml.etree.ElementTree as ET
        from os import path
        #This dict has the keys of XML tags that are required in order for the
        #CI server to run the repo. When each one is parsed, we change its value
        #to True and then check that they are all true at the end.
        required = {"testing": False, "wiki": False}
        #Make sure the file exists and then import it as XML and read the values out.
        if path.isfile(self.filepath):
            tree = ET.parse(self.filepath)
            vms("Parsing XML tree from {}.".format(self.filepath), 2)
            root = tree.getroot()
            if root.tag != "cirepo":
                raise ValueError("The root tag in a continuous integration settings XML "
                                 "file should be a <cirepo> tag.")

            self._parse_repo(root)
            for child in root:
                if child.tag == "cron":
                    if self.server is not None:
                        self.server.cron.settings[self.name] = CronSettings(child)
                if child.tag == "testing":
                    self.testing = TestingSettings(child)
                if child.tag == "static":
                    self.static = StaticSettings(child)
                if child.tag == "wiki":
                    self.wiki["user"] = get_attrib(child, "user", "wiki")
                    self.wiki["password"] = get_attrib(child, "password", "wiki")
                    self.wiki["basepage"] = get_attrib(child, "basepage", "wiki")
                if child.tag in required:
                    required[child.tag] = True

            if not all(required.values()):
                tags = ', '.join(["<{}>".format(t) for t in required])
                raise ValueError("{} are required tags in the repo's XML settings file.".format(tags))
691058
def xml_to_root(xml: Union[str, IO]) -> ElementTree.Element:
    
    if isinstance(xml, str):
        if '<' in xml:
            return ElementTree.fromstring(xml)
        else:
            with open(xml) as fh:
                xml_to_root(fh)
    tree = ElementTree.parse(xml)
    return tree.getroot()
434745
def parsexml(Class, node, doc, **kwargs): #pylint: disable=bad-classmethod-argument
        

        assert issubclass(Class, AbstractElement)

        if doc.preparsexmlcallback:
            result = doc.preparsexmlcallback(node)
            if not result:
                return None
            if isinstance(result, AbstractElement):
                return result



        dcoi = node.tag.startswith('{' + NSDCOI + '}')
        args = []
        if not kwargs: kwargs = {}
        text = None #for dcoi support
        if (Class.TEXTCONTAINER or Class.PHONCONTAINER) and node.text:
            args.append(node.text)


        for subnode in node: #pylint: disable=too-many-nested-blocks
            #don't trip over comments
            if isinstance(subnode, ElementTree._Comment): #pylint: disable=protected-access
                if (Class.TEXTCONTAINER or Class.PHONCONTAINER) and subnode.tail:
                    args.append(subnode.tail)
            else:
                if subnode.tag.startswith('{' + NSFOLIA + '}'):
                    if doc.debug >= 1: print("[PyNLPl FoLiA DEBUG] Processing subnode " + subnode.tag[nslen:],file=stderr)
                    try:
                        e = doc.parsexml(subnode, Class)
                    except ParseError as e:
                        raise #just re-raise deepest parseError
                    except Exception as e:
                        #Python 3 will preserve full original traceback, Python 2 does not, original cause is explicitly passed to ParseError anyway:
                        raise ParseError("FoLiA exception in handling of <" + subnode.tag[len(NSFOLIA)+2:] + "> @ line " + str(subnode.sourceline) + ": [" + e.__class__.__name__ + "] " + str(e), cause=e)
                    if e is not None:
                        args.append(e)
                    if (Class.TEXTCONTAINER or Class.PHONCONTAINER) and subnode.tail:
                        args.append(subnode.tail)
                elif subnode.tag.startswith('{' + NSDCOI + '}'):
                    #Dcoi support
                    if Class is Text and subnode.tag[nslendcoi:] == 'body':
                        for subsubnode in subnode:
                            if doc.debug >= 1: print("[PyNLPl FoLiA DEBUG] Processing DCOI subnode " + subnode.tag[nslendcoi:],file=stderr)
                            e = doc.parsexml(subsubnode, Class)
                            if e is not None:
                                args.append(e)
                    else:
                        if doc.debug >= 1: print( "[PyNLPl FoLiA DEBUG] Processing DCOI subnode " + subnode.tag[nslendcoi:],file=stderr)
                        e = doc.parsexml(subnode, Class)
                        if e is not None:
                            args.append(e)
                elif doc.debug >= 1:
                    print("[PyNLPl FoLiA DEBUG] Ignoring subnode outside of FoLiA namespace: " + subnode.tag,file=stderr)



        if dcoi:
            dcoipos = dcoilemma = dcoicorrection = dcoicorrectionoriginal = None
        for key, value in node.attrib.items():
            if key[0] == '{' or key =='XMLid':
                if key == '{http://www.w3.org/XML/1998/namespace}id' or key == 'XMLid':
                    key = 'id'
                elif key.startswith( '{' + NSFOLIA + '}'):
                    key = key[nslen:]
                    if key == 'id':
                        #ID in FoLiA namespace is always a reference, passed in kwargs as follows:
                        key = 'idref'
                elif Class.XLINK and key.startswith('{http://www.w3.org/1999/xlink}'):
                    key = key[30:]
                    if key != 'href':
                        key = 'xlink' + key #xlinktype, xlinkrole, xlinklabel, xlinkshow, etc..
                elif key.startswith('{' + NSDCOI + '}'):
                    key = key[nslendcoi:]

            #D-Coi support:
            if dcoi:
                if Class is Word and key == 'pos':
                    dcoipos = value
                    continue
                elif Class is Word and  key == 'lemma':
                    dcoilemma = value
                    continue
                elif Class is Word and  key == 'correction':
                    dcoicorrection = value #class
                    continue
                elif Class is Word and  key == 'original':
                    dcoicorrectionoriginal = value
                    continue
                elif Class is Gap and  key == 'reason':
                    key = 'class'
                elif Class is Gap and  key == 'hand':
                    key = 'annotator'
                elif Class is Division and  key == 'type':
                    key = 'cls'

            kwargs[key] = value

        #D-Coi support:
        if dcoi and TextContent in Class.ACCEPTED_DATA and node.text:
            text = node.text.strip()

            kwargs['text'] = text
            if not AnnotationType.TOKEN in doc.annotationdefaults:
                doc.declare(AnnotationType.TOKEN, set='http://ilk.uvt.nl/folia/sets/ilktok.foliaset')

        if doc.debug >= 1: print("[PyNLPl FoLiA DEBUG] Found " + node.tag[nslen:],file=stderr)
        instance = Class(doc, *args, **kwargs)
        #if id:
        #    if doc.debug >= 1: print >>stderr, "[PyNLPl FoLiA DEBUG] Adding to index: " + id
        #    doc.index[id] = instance
        if dcoi:
            if dcoipos:
                if not AnnotationType.POS in doc.annotationdefaults:
                    doc.declare(AnnotationType.POS, set='http://ilk.uvt.nl/folia/sets/cgn-legacy.foliaset')
                instance.append( PosAnnotation(doc, cls=dcoipos) )
            if dcoilemma:
                if not AnnotationType.LEMMA in doc.annotationdefaults:
                    doc.declare(AnnotationType.LEMMA, set='http://ilk.uvt.nl/folia/sets/mblem-nl.foliaset')
                instance.append( LemmaAnnotation(doc, cls=dcoilemma) )
            if dcoicorrection and dcoicorrectionoriginal and text:
                if not AnnotationType.CORRECTION in doc.annotationdefaults:
                    doc.declare(AnnotationType.CORRECTION, set='http://ilk.uvt.nl/folia/sets/dcoi-corrections.foliaset')
                instance.correct(generate_id_in=instance, cls=dcoicorrection, original=dcoicorrectionoriginal, new=text)

        if doc.parsexmlcallback:
            result = doc.parsexmlcallback(instance)
            if not result:
                return None
            if isinstance(result, AbstractElement):
                return result

        return instance
329369
def raw_xml(self) -> _RawXML:
        
        if self._xml:
            return self._xml
        else:
            return etree.tostring(self.element, encoding='unicode').strip().encode(self.encoding)
318353
def lxml(self) -> _LXML:
        
        if self._lxml is None:
            self._lxml = etree.fromstring(self.raw_xml)

        return self._lxml
451024
def parse_simpleexprsp(self, tup_tree):
        # pylint: disable=unused-argument
        
        raise CIMXMLParseError(
            _format("Internal Error: Parsing support for element {0!A} is not "
                    "implemented", name(tup_tree)),
            conn_id=self.conn_id)
1094171
def parse_fast(xmlfile, element_name, attrnames, warn=False, optional=False):
    
    prefixedAttrnames = [_prefix_keyword(a, warn) for a in attrnames]
    if optional:
        pattern = ''.join(['<%s' % element_name] +
                          ['(\\s+%s="(?P<%s>[^"]*?)")?' % a for a in zip(attrnames, prefixedAttrnames)])
    else:
        pattern = '.*'.join(['<%s' % element_name] +
                            ['%s="([^"]*)"' % attr for attr in attrnames])
    Record = namedtuple(element_name, prefixedAttrnames)
    reprog = re.compile(pattern)
    for line in open(xmlfile):
        m = reprog.search(line)
        if m:
            if optional:
                yield Record(**m.groupdict())
            else:
                yield Record(*m.groups())
1364407
def decode(data):
    
    dom = None
    try:
        dom = dhtmlparser.parseString(data)
    except Exception, e:
        raise MetaParsingException("Can't parse your XML data: %s" % e.message)

    root = dom.find("root")

    # check whether there is <root>s
    if not root:
        raise MetaParsingException("All elements have to be inside <root>.")

    # and make sure, that there is not too many <root>s
    if len(root) > 1:
        raise MetaParsingException("Too many <root> elements in your XML!")

    items = root[0].find("item")

    # check for items
    if not items:
        raise MetaParsingException("There are no <items> in your XML <root>!")

    decoded = []
    for item in items:
        if "key" not in item.params:
            raise MetaParsingException(
                "There is no 'key' parameter in %s." % str(item)
            )

        decoded.append([
            item.params["key"],
            item.getContent().strip()
        ])

    decoded = validator.check_structure(decoded)

    return decoded
1298300
def XML_fromstring(content, source=None):
    
    try:
        tree = ET.fromstring(content)
    except ET.ParseError as err:
        x_parse_error(err, content, source)
    return tree
197161
def parse(celf, s) :
        ""

        def from_string_elts(celf, attrs, tree) :
            elts = dict((k, attrs[k]) for k in attrs)
            child_tags = dict \
              (
                (childclass.tag_name, childclass)
                for childclass in tuple(celf.tag_elts.values()) + (Introspection.Annotation,)
              )
            children = []
            for child in tree :
                if child.tag not in child_tags :
                    raise KeyError("unrecognized tag %s" % child.tag)
                #end if
                childclass = child_tags[child.tag]
                childattrs = {}
                for attrname in childclass.tag_attrs :
                    if hasattr(childclass, "tag_attrs_optional") and attrname in childclass.tag_attrs_optional :
                        childattrs[attrname] = child.attrib.get(attrname, None)
                    else :
                        if attrname not in child.attrib :
                            raise ValueError("missing %s attribute for %s tag" % (attrname, child.tag))
                        #end if
                        childattrs[attrname] = child.attrib[attrname]
                    #end if
                #end for
                if hasattr(childclass, "attr_convert") :
                    for attr in childclass.attr_convert :
                        if attr in childattrs :
                            childattrs[attr] = childclass.attr_convert[attr](childattrs[attr])
                        #end if
                    #end for
                #end if
                children.append(from_string_elts(childclass, childattrs, child))
            #end for
            for child_tag, childclass in tuple(celf.tag_elts.items()) + ((), (("annotations", Introspection.Annotation),))[tree.tag != "annotation"] :
                for child in children :
                    if isinstance(child, childclass) :
                        if child_tag not in elts :
                            elts[child_tag] = []
                        #end if
                        elts[child_tag].append(child)
                    #end if
                #end for
            #end for
            return \
                celf(**elts)
        #end from_string_elts

    #begin parse
        tree = XMLElementTree.fromstring(s)
        assert tree.tag == "node", "root of introspection tree must be <node> tag"
        return \
            from_string_elts(Introspection, {}, tree)
991922
def newTextLen(content, len):
    
    ret = libxml2mod.xmlNewTextLen(content, len)
    if ret is None:raise treeError('xmlNewTextLen() failed')
    return xmlNode(_obj=ret)
361138
def parseURIRaw(str, raw):
    
    ret = libxml2mod.xmlParseURIRaw(str, raw)
    if ret is None:raise uriError('xmlParseURIRaw() failed')
    return URI(_obj=ret)
1333409
def ln_from_etree(self, ln_element, context=''):
        
        ln = {}
        # grab all understood attributes into ln dict
        for att in ('hash', 'href', 'length', 'modified',
                    'path', 'rel', 'pri', 'mime_type'):
            xml_att = self._xml_att_name(att)
            val = ln_element.attrib.get(xml_att, None)
            if (val is not None):
                ln[att] = val
        # now do some checks and conversions...
        # href (MANDATORY)
        if ('href' not in ln):
            raise SitemapParseError(
                "Missing href in <rs:ln> in %s" %
                (context))
        # rel (MANDATORY)
        if ('rel' not in ln):
            raise SitemapParseError("Missing rel in <rs:ln> in %s" % (context))
        # length in bytes
        if ('length' in ln):
            try:
                ln['length'] = int(ln['length'])
            except ValueError as e:
                raise SitemapParseError(
                    "Invalid length attribute value in <rs:ln> for %s" %
                    (context))
        # pri - priority, must be a number between 1 and 999999
        if ('pri' in ln):
            try:
                ln['pri'] = int(ln['pri'])
            except ValueError as e:
                raise SitemapParseError(
                    "Invalid pri attribute in <rs:ln> for %s" %
                    (context))
            if (ln['pri'] < 1 or ln['pri'] > 999999):
                raise SitemapParseError(
                    "Bad pri attribute value in <rs:ln> for %s" %
                    (context))
        return(ln)
64128
def _etree_py26_write(f, tree):
    
    f.write("<?xml version='1.0' encoding='utf-8'?>\n".encode('utf-8'))

    if etree.VERSION[:3] == '1.2':
        def fixtag(tag, namespaces):
            if tag == XML_NS + 'lang':
                return 'xml:lang', ""
            if '}' in tag:
                j = tag.index('}') + 1
                tag = tag[j:]
                xmlns = ''
            if tag == 'feed':
                xmlns = ('xmlns', str('http://www.w3.org/2005/Atom'))
                namespaces['http://www.w3.org/2005/Atom'] = 'xmlns'
            return tag, xmlns
    else:
        fixtag = etree.fixtag

    old_fixtag = etree.fixtag
    etree.fixtag = fixtag
    try:
        tree.write(f, encoding=str('utf-8'))
    finally:
        etree.fixtag = old_fixtag
346991
def xml(self):
        
        try:
            from lxml import etree
            return etree.fromstring(self.content)
        except ImportError as ie:
            raise DependencyException(ie)