code: def _get_elements(self, name=''):
          
          qname = self._qname(name)
          rdf = self._get_rdf_root()
          for rdfdesc in rdf.findall('rdf:Description[@rdf:about=""]', self.NS):
              if qname and qname in rdfdesc.keys():
                  yield (rdfdesc, qname, rdfdesc.get(qname), rdf)
              elif not qname:
                  for k, v in rdfdesc.items():
                      if v:
                          yield (rdfdesc, k, v, rdf)
              xpath = qname if name else '*'
              for node in rdfdesc.findall(xpath, self.NS):
                  if node.text and node.text.strip():
                      yield (node, None, node.text, rdfdesc)
                      continue
                  values = self._get_subelements(node)
                  yield (node, None, values, rdfdesc)
docs: Get elements from XMP
  
          Core routine to find elements matching name within the XMP and yield
          them.
  
          For XMP spec 7.9.2.2, rdf:Description with property attributes,
          we yield the node which will have the desired as one of its attributes.
          qname is returned so that the node.attrib can be used to locate the
          source.
  
          For XMP spec 7.5, simple valued XMP properties, we yield the node,
          None, and the value. For structure or array valued properties we gather
          the elements. We ignore qualifiers.
  
          Args:
              name (str): a prefixed name or QName to look for within the
                  data section of the XMP; looks for all data keys if omitted
  
          Yields:
              tuple: (node, qname_attrib, value, parent_node)