diff --git a/.gitattributes b/.gitattributes
index 5a93f60cf07099cb618578e200679e8269286ac1..1d366b15371ad6e867b0df30b1a7c15f83842ce2 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1703,6 +1703,7 @@ LCS/PyCommon/test/t_util.sh -text
 LCS/PyCommon/test_utils.py -text
 LCS/PyCommon/threading_utils.py -text
 LCS/PyCommon/util.py -text
+LCS/PyCommon/xmlparse.py -text
 LCS/PyStationModel/CMakeLists.txt -text
 LCS/PyStationModel/antennasets_parser.py -text
 LCS/PyStationModel/test/CMakeLists.txt -text
diff --git a/LCS/PyCommon/CMakeLists.txt b/LCS/PyCommon/CMakeLists.txt
index 41bd1f54a00764f033b14688eca1aed2fecb142f..126bec92a1ca358382db30f4f921e6348e3a695d 100644
--- a/LCS/PyCommon/CMakeLists.txt
+++ b/LCS/PyCommon/CMakeLists.txt
@@ -25,6 +25,7 @@ set(_py_files
   datetimeutils.py
   flask_utils.py
   subprocess_utils.py
+  xmlparse.py
   test_utils.py)
 
 python_install(${_py_files} DESTINATION lofar/common)
diff --git a/LCS/PyCommon/xmlparse.py b/LCS/PyCommon/xmlparse.py
new file mode 100644
index 0000000000000000000000000000000000000000..22d22b8037b2c1b587bf6601e53303a18852ffde
--- /dev/null
+++ b/LCS/PyCommon/xmlparse.py
@@ -0,0 +1,15 @@
+from lxml import etree
+from io import BytesIO
+
+from typing import Union
+
+def parse_xml_string_or_bytestring(xml_content: Union[str, bytes], parser=None) -> etree:
+    """
+    Parse the given xml content and returns a Etree
+    :param xml_content: content of the xml file
+    :return: the parsed content in the form of an element tree
+    """
+    if isinstance(bytes, xml_content):
+        return etree.parse(BytesIO(xml_content), parser=parser)
+    else:
+        return etree.fromstring(xml_content, parser=parser)
\ No newline at end of file
diff --git a/SAS/SpecificationServices/lib/lofarxml_to_momxml_translator.py b/SAS/SpecificationServices/lib/lofarxml_to_momxml_translator.py
index adb1702d52251fe353b7d309f11a43f592b6365f..91d4acf4b8eb8b0397d7b7c0c997346c6d91b616 100644
--- a/SAS/SpecificationServices/lib/lofarxml_to_momxml_translator.py
+++ b/SAS/SpecificationServices/lib/lofarxml_to_momxml_translator.py
@@ -51,7 +51,7 @@ import datetime
 from .config import VALIDATION_SERVICENAME
 from .validation_service_rpc import ValidationRPC
 from .specification_service import _parse_relation_tree, make_key, _parse_project_code
-
+from lofar.common.xmlparse import parse_xml_string_or_bytestring
 from lofar.messaging import DEFAULT_BROKER, DEFAULT_BUSNAME
 
 from io import BytesIO
@@ -742,7 +742,7 @@ class LofarXmlToMomXmlTranslator():
 
         # Parse specification
         parser = etree.XMLParser(remove_blank_text=True)  # <-- prevent that prettyprinting breaks
-        spectree = etree.parse(BytesIO(spec_xml.encode('UTF-8')), parser=parser).getroot()
+        spectree = parse_xml_string_or_bytestring(spec_xml, parser=parser).getroot()
 
         nsmap = {"lofar": "http://www.astron.nl/MoM2-Lofar",
                  "mom2": "http://www.astron.nl/MoM2",
diff --git a/SAS/SpecificationServices/lib/specification_service.py b/SAS/SpecificationServices/lib/specification_service.py
index 370d109e041c94aa4cf7aef37c762f06a51558d4..8ea22f2b9e1b942de07b5891a526db09f5ff63b9 100644
--- a/SAS/SpecificationServices/lib/specification_service.py
+++ b/SAS/SpecificationServices/lib/specification_service.py
@@ -31,7 +31,7 @@ from lofar.messaging import RPCService, ToBus, EventMessage, DEFAULT_BROKER, DEF
 from lofar.mom.momqueryservice.momqueryrpc import MoMQueryRPC
 from lofar.specificationservices.translation_service_rpc import TranslationRPC
 from lofar.specificationservices.validation_service_rpc import ValidationRPC
-from lxml import etree
+from lofar.common.xmlparse import parse_xml_string_or_bytestring
 
 from .config import \
     SPECIFICATION_SERVICENAME, \
@@ -170,7 +170,7 @@ class SpecificationHandler(ServiceMessageHandler):
         E.g. activities have to be in new folders
         """
 
-        doc = etree.parse(BytesIO(lofar_xml.encode('utf-8')))
+        doc = parse_xml_string_or_bytestring(lofar_xml)
         spec = doc.getroot()
 
         if spec.tag != "{http://www.astron.nl/LofarSpecification}specification":
diff --git a/SAS/SpecificationServices/lib/translation_service.py b/SAS/SpecificationServices/lib/translation_service.py
index b9ebe5fa54fa08ffa5abdb21b3874f00bb8f3f66..352da0bb934466bca9e2979b772b0b69042953ea 100644
--- a/SAS/SpecificationServices/lib/translation_service.py
+++ b/SAS/SpecificationServices/lib/translation_service.py
@@ -45,6 +45,8 @@ from lofar.specificationservices.telescope_model_xml_generator_type1 import Tele
 logger = logging.getLogger(__name__)
 from lxml import etree
 from io import BytesIO
+from lofar.common.xmlparse import parse_xml_string_or_bytestring
+
 
 from lofar.messaging import RPCService, ServiceMessageHandler, DEFAULT_BROKER, DEFAULT_BUSNAME
 from lofar.common.util import waitForInterrupt
@@ -73,7 +75,7 @@ class SpecificationTranslationHandler(ServiceMessageHandler):
         try:
             # pick the specification element
             parser = etree.XMLParser(remove_blank_text=True)
-            doc = etree.parse(BytesIO(trigger_spec.encode('UTF-8')), parser=parser)
+            doc = parse_xml_string_or_bytestring(trigger_spec, parser=parser)
             # spec = doc.getroot().find('{http://www.astron.nl/LofarSpecification}specification')
             root = doc.getroot()
             if not "trigger" in root.tag:
diff --git a/SAS/SpecificationServices/lib/validation_service.py b/SAS/SpecificationServices/lib/validation_service.py
index 73ea20dd748c4c40d83006b339661ea37e242a0d..c536eebc2bf08c6557c92281ec7b9f501e47f978 100644
--- a/SAS/SpecificationServices/lib/validation_service.py
+++ b/SAS/SpecificationServices/lib/validation_service.py
@@ -30,6 +30,7 @@ from lxml import etree
 import os
 from lofar.messaging import ServiceMessageHandler, DEFAULT_BROKER, DEFAULT_BUSNAME, RPCService
 from lofar.common.util import waitForInterrupt
+from lofar.common.xmlparse import parse_xml_string_or_bytestring
 
 from .config import TRIGGER_XSD, LOFARSPEC_XSD, MOMSPEC_XSD, VALIDATION_SERVICENAME
 
@@ -39,7 +40,7 @@ def _validateXSD(xml, xsdpath):
     '''validates given xml against given xsd file'''
 
     logger.info("Validating against " + str(xsdpath))
-    logger.debug("XML: "+xml)
+    logger.debug("XML: %s", xml)
 
     xsdpath = os.path.expandvars(xsdpath)
 
@@ -50,7 +51,7 @@ def _validateXSD(xml, xsdpath):
 
         # Try to parse the XML
         try:
-            doc = etree.parse(BytesIO(xml.encode('utf8')))
+            doc = parse_xml_string_or_bytestring(BytesIO(xml.encode('utf8')))
         except etree.LxmlError as err:
             logger.error(err)
             return {"valid": False, "error": "XML could not be parsed: %s" % (err,)}