docs: def fromxml(node):
          """Return a CLAMProvenanceData instance from the given XML description. Node can be a string or an lxml.etree._Element."""
          if not isinstance(node,ElementTree._Element): #pylint: disable=protected-access
              node = parsexmlstring(node)
          if node.tag == 'provenance': #pylint: disable=too-many-nested-blocks
              if node.attrib['type'] == 'clam':
                  serviceid = node.attrib['id']
                  servicename = node.attrib['name']
                  serviceurl = node.attrib['url']
                  timestamp = node.attrib['timestamp']
                  outputtemplate = node.attrib['outputtemplate']
                  outputtemplatelabel = node.attrib['outputtemplatelabel']
                  inputfiles = []
                  parameters = []
                  for subnode in node:
                      if subnode.tag == 'inputfile':
                          filename = node.attrib['name']
                          metadata = None
                          for subsubnode in subnode:
                              if subsubnode.tag == 'CLAMMetaData':
                                  metadata = CLAMMetaData.fromxml(subsubnode)
                                  break
                          inputfiles.append( (filename, metadata) )
                      elif subnode.tag == 'parameters':
                          for subsubnode in subnode:
                              if subsubnode.tag in vars(clam.common.parameters):
                                  parameters.append(vars(clam.common.parameters)[subsubnode.tag].fromxml(subsubnode))
                              else:
                                  raise Exception("Expected parameter class '" + subsubnode.tag + "', but not defined!")
                  return CLAMProvenanceData(serviceid,servicename,serviceurl,outputtemplate, outputtemplatelabel, inputfiles, parameters, timestamp)
              else:
                  raise NotImplementedError