# Source code for obspy.io.seiscomp.core

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    """
    SC3ML function used for both inventory and event module.

    :author:
        EOST (École et Observatoire des Sciences de la Terre)
    :copyright:
        The ObsPy Development Team (devs@obspy.org)
    :license:
        GNU Lesser General Public License, Version 3
        (https://www.gnu.org/copyleft/lesser.html)
    """
    from __future__ import (absolute_import, division, print_function,
                            unicode_literals)
    from future.builtins import *  # NOQA

    import os
    import re

    from lxml import etree

    from obspy.io.quakeml.core import _xml_doc_from_anything

    # SC3ML version for which an XSD file is available
    SUPPORTED_XSD_VERSION = ['0.3', '0.5', '0.6', '0.7', '0.8', '0.9']

    def _is_sc3ml(path_or_file_object):
        """
        Simple function checking if the passed object contains a valid sc3ml file
        according to the list of versions given in parameters. Returns True of
        False.

        The test is not exhaustive - it only checks the root tag but that should
        be good enough for most real world use cases. If the schema is used to
        test for a StationXML file, many real world files are false negatives as
        they don't adhere to the standard.

        :type path_or_file_object: str
        :param path_or_file_object: File name or file like object.
        :rtype: bool
        :return: `True` if file is a SC3ML file.
        """
        if hasattr(path_or_file_object, "tell") and hasattr(path_or_file_object,
                                                            "seek"):
            current_position = path_or_file_object.tell()

        if isinstance(path_or_file_object, etree._Element):
            xmldoc = path_or_file_object
        else:
            try:
                xmldoc = _xml_doc_from_anything(path_or_file_object)
            except ValueError:
                return False
            finally:
                # Make sure to reset file pointer position.
                try:
                    path_or_file_object.seek(current_position, 0)
                except Exception:
                    pass

        if hasattr(xmldoc, "getroot"):
            root = xmldoc.getroot()
        else:
            root = xmldoc

        match = re.match(
            r'{http://geofon\.gfz-potsdam\.de/ns/seiscomp3-schema/([-+]?'
            r'[0-9]*\.?[0-9]+)}', root.tag)

        return match is not None

    def validate(path_or_object, version='0.9', verbose=False):
        """
        Check if the given file is a valid SC3ML file.

        :type path_or_object: str
        :param path_or_object: File name or file like object. Can also be an etree
            element.
        :type version: str
        :param version: Version of the SC3ML schema to validate against.
        :type verbose: bool
        :param verbose: Print error log if True.
        :rtype: bool
        :return: `True` if SC3ML file is valid.
        """
        if version not in SUPPORTED_XSD_VERSION:
            raise ValueError('%s is not a supported version. Use one of these '
                             'versions: [%s].'
                             % (version, ', '.join(SUPPORTED_XSD_VERSION)))

        # Get the schema location.
        xsd_filename = 'sc3ml_%s.xsd' % version
        schema_location = os.path.join(os.path.dirname(__file__), 'data',
                                       xsd_filename)
        xmlschema = etree.XMLSchema(etree.parse(schema_location))

        if hasattr(path_or_object, "tell") and hasattr(path_or_object, "seek"):
            current_position = path_or_object.tell()

        if isinstance(path_or_object, etree._Element):
            xmldoc = path_or_object
        else:
            try:
                xmldoc = _xml_doc_from_anything(path_or_object)
            except ValueError:
                return False
            finally:
                # Make sure to reset file pointer position.
                try:
                    path_or_object.seek(current_position, 0)
                except Exception:
                    pass

        valid = xmlschema.validate(xmldoc)

        # Pretty error printing if the validation fails.
        if verbose and valid is not True:
            print("Error validating SC3ML file:")
            for entry in xmlschema.error_log:
                print("\t%s" % entry)

        return valid

### Thank you!

We would like to thank our contributors, whose efforts make this software what it is. These people have helped by writing code and documentation, and by testing. They have created and maintained this product, its associated libraries and applications, our build tools and our web sites.

#### Contributors

- Ackerley, Nick
- Allgeyer, Sebastien
- Ammon, Charles J.
- Antunes, Emanuel
- Arnarsson, Ólafur St.
- Bank, Markus
- Barsch, Robert
- Behr, Yannik
- Bernardi, Fabrizio
- Bernauer, Felix
- Bes de Berc, Maxime
- Beyreuther, Moritz
- Boltz, Shawn
- Bonaimé, Sébastien
- Carothers, Lloyd
- Chamberlain, Calum
- Chambers, Derrick
- Chen, Zhao
- Clark, Adam
- Danecek, Peter
- Egdorf, Sven
- Engels, Fabian
- Ermert, Laura
- Eulenfeld, Tom

- Fabbri, Tommaso
- Falco, Nicholas
- Fee, Jeremy
- Grellier, Clément
- Grunberg, Marc
- Hammer, Conny
- Heimann, Sebastian
- Heiniger, Lukas
- Hope, Gaute
- Igel, Heiner
- Inza, Adolfo
- Isken, Marius
- Ketchum, David
- Koymans, Mathijs
- Kremers, Simon
- Kress, Victor
- Krieger, Lars
- Krischer, Lion
- Kula, Damian
- Käufl, Paul
- Köhler, Andreas
- Lecocq, Thomas
- Leeman, John
- Legovini, Paride

- Lesage, Philippe
- Li, Yulin
- Lomax, Anthony
- Lopes, Rui L.
- MacCarthy, Jonathan
- Maggi, Alessia
- Martin, Henri
- Medlin, Andrew
- Megies, Tobias
- Meschede, Matthias
- Michelini, Alberto
- Miller, Nathaniel C.
- Morgenstern, Bernhard
- Nof, Ran Novitsky
- Panning, Mark P.
- Parker, Tom
- Pestourie, Romain
- Rapagnani, Giovanni
- Reyes, Celso
- Ringler, Adam
- Rothenhäusler, Nicolas
- Russo, Emiliano
- Sales de Andrade, Elliott

- Satriano, Claudio
- Saul, Joachim
- Scheingraber, Chris
- Schneider, Simon
- Sippl, Christian
- Snoke, Arthur
- Stange, Stefan
- Stähler, Simon C.
- Sullivan, Benjamin
- Tian, Dongdong
- Trabant, Chad
- Trani, Luca
- Uieda, Leonardo
- Walker, Andrew
- Walther, Marcus
- Wassermann, Joachim
- Williams, Mark C.
- Winkelman, Andrew
- Zaccarelli, Riccardo
- Zad, Seyed Kasra Hosseini
- Zhu, Lijun
- van Driel, Martin
- van Wijk, Kasper

#### Funds

ObsPy was partially funded by the

- German Science Foundation (DFG) via grant DFG IG 16/9-1
- German Ministry for Education and Research (BMBF), GEOTECHNOLOGIEN grant 03G0646H.
- NERA project (Network of European Research Infrastructures for Earthquake Risk Assessment and Mitigation) under the European Community's Seventh Framework Programme (FP7/2007-2013) grant agreement n° 262330
- Leibniz Institute for Applied Geophysics (LIAG)
- VERCE EU-FP7 project (no. 283543)