Construct a Resource from an etree.

        Parameters:
         etree - the etree to parse
         resource_class - class of Resource object to create

        The parsing is properly namespace aware but we search just
        for the elements wanted and leave everything else alone. Will
        raise an error if there are multiple <loc> or multiple <lastmod>
        elements. Otherwise, provided there is a <loc> element then will
        go ahead and extract as much as possible.

        All errors raised are SitemapParseError with messages intended
        to help debug problematic sitemap XML.

def resource_from_etree(self, etree, resource_class):
        """Construct a Resource from an etree.

        Parameters:
         etree - the etree to parse
         resource_class - class of Resource object to create

        The parsing is properly namespace aware but we search just
        for the elements wanted and leave everything else alone. Will
        raise an error if there are multiple <loc> or multiple <lastmod>
        elements. Otherwise, provided there is a <loc> element then will
        go ahead and extract as much as possible.

        All errors raised are SitemapParseError with messages intended
        to help debug problematic sitemap XML.
        """
        loc_elements = etree.findall('{' + SITEMAP_NS + "}loc")
        if (len(loc_elements) > 1):
            raise SitemapParseError(
                "Multiple <loc> elements while parsing <url> in sitemap")
        elif (len(loc_elements) == 0):
            raise SitemapParseError(
                "Missing <loc> element while parsing <url> in sitemap")
        else:
            loc = loc_elements[0].text
        if (loc is None or loc == ''):
            raise SitemapParseError(
                "Bad <loc> element with no content while parsing <url> in sitemap")
        # must at least have a URI, make this object
        resource = resource_class(uri=loc)
        # and hopefully a lastmod datetime (but none is OK)
        lastmod_elements = etree.findall('{' + SITEMAP_NS + "}lastmod")
        if (len(lastmod_elements) > 1):
            raise SitemapParseError(
                "Multiple <lastmod> elements while parsing <url> in sitemap")
        elif (len(lastmod_elements) == 1):
            resource.lastmod = lastmod_elements[0].text
        # proceed to look for other resource attributes in an rs:md element
        md_elements = etree.findall('{' + RS_NS + "}md")
        if (len(md_elements) > 1):
            raise SitemapParseError(
                "Found multiple (%d) <rs:md> elements for %s", (len(md_elements), loc))
        elif (len(md_elements) == 1):
            # have on element, look at attributes
            md = self.md_from_etree(md_elements[0], context=loc)
            # simple attributes that map directly to Resource object attributes
            for att in ('capability', 'change', 'length', 'path', 'mime_type'):
                if (att in md):
                    setattr(resource, att, md[att])
            # The ResourceSync beta spec lists md5, sha-1 and sha-256 fixity
            # digest types. Parse and warn of errors ignored.
            if ('hash' in md):
                try:
                    resource.hash = md['hash']
                except ValueError as e:
                    self.logger.warning("%s in <rs:md> for %s" % (str(e), loc))
        # look for rs:ln elements (optional)
        ln_elements = etree.findall('{' + RS_NS + "}ln")
        if (len(ln_elements) > 0):
            resource.ln = []
            for ln_element in ln_elements:
                resource.ln.append(self.ln_from_etree(ln_element, loc))
        return(resource)