[pycsw] 01/02: New upstream version 2.2.0+dfsg

Johan Van de Wauw johanvdw-guest at moszumanska.debian.org
Thu Mar 22 00:40:22 UTC 2018


This is an automated email from the git hooks/post-receive script.

johanvdw-guest pushed a commit to branch master
in repository pycsw.

commit 1ecf5fb72ea77f09b18a17640526deeea73f1474
Author: Johan Van de Wauw <johan at gisky.be>
Date:   Thu Mar 22 01:31:59 2018 +0100

    New upstream version 2.2.0+dfsg
---
 .coveragerc                                        |   12 +
 .dockerignore                                      |   23 +
 .github/ISSUE_TEMPLATE.md                          |   16 +-
 .travis.yml                                        |   74 +-
 CODE_OF_CONDUCT.md                                 |   46 +
 CONTRIBUTING.rst                                   |    4 +-
 Dockerfile                                         |  117 ++
 MANIFEST.in                                        |    1 +
 README.rst                                         |   23 +
 README.txt                                         |   12 -
 VERSION.txt                                        |    2 +-
 bin/pycsw-admin.py                                 |    3 -
 default-sample.cfg                                 |    6 +-
 .../docker-stack-pycsw.cfg                         |   12 +-
 .../formats/fmt_json.py => docker/docker-stack.yml |   43 +-
 docker/entrypoint.py                               |  178 +++
 default-sample.cfg => docker/pycsw.cfg             |   10 +-
 docs/_templates/indexsidebar.html                  |    2 +-
 docs/administration.rst                            |   11 +-
 docs/conf.py                                       |   19 +
 docs/docker.rst                                    |  169 +++
 docs/geonode.rst                                   |    2 +
 docs/hhypermap.rst                                 |    8 +-
 docs/index.rst                                     |    2 +
 docs/installation.rst                              |    2 +-
 docs/locale/zh/LC_MESSAGES/administration.po       |  383 +++++
 docs/locale/zh/LC_MESSAGES/api.po                  |   57 +
 docs/locale/zh/LC_MESSAGES/ckan.po                 |   57 +
 docs/locale/zh/LC_MESSAGES/committers.po           |   96 ++
 docs/locale/zh/LC_MESSAGES/configuration.po        |  482 +++++++
 docs/locale/zh/LC_MESSAGES/contributing.po         |  354 +++++
 docs/locale/zh/LC_MESSAGES/csw-support.po          |   65 +
 docs/locale/zh/LC_MESSAGES/distributedsearching.po |  156 ++
 docs/locale/zh/LC_MESSAGES/geonode.po              |   61 +
 docs/locale/zh/LC_MESSAGES/hhypermap.po            |   72 +
 docs/locale/zh/LC_MESSAGES/index.po                |   35 +
 docs/locale/zh/LC_MESSAGES/installation.po         |  270 ++++
 docs/locale/zh/LC_MESSAGES/introduction.po         |  558 +++++++
 docs/locale/zh/LC_MESSAGES/json.po                 |   35 +
 docs/locale/zh/LC_MESSAGES/license.po              |   78 +
 docs/locale/zh/LC_MESSAGES/migration-guide.po      |   57 +
 docs/locale/zh/LC_MESSAGES/oaipmh.po               |   41 +
 docs/locale/zh/LC_MESSAGES/odc.po                  |   70 +
 docs/locale/zh/LC_MESSAGES/opensearch.po           |   56 +
 docs/locale/zh/LC_MESSAGES/outputschemas.po        |   96 ++
 docs/locale/zh/LC_MESSAGES/profiles.po             |  277 ++++
 docs/locale/zh/LC_MESSAGES/repofilters.po          |  179 +++
 docs/locale/zh/LC_MESSAGES/repositories.po         |   91 ++
 docs/locale/zh/LC_MESSAGES/sitemaps.po             |   31 +
 docs/locale/zh/LC_MESSAGES/soap.po                 |   28 +
 docs/locale/zh/LC_MESSAGES/sru.po                  |   39 +
 docs/locale/zh/LC_MESSAGES/support.po              |   31 +
 docs/locale/zh/LC_MESSAGES/testing.po              |  248 ++++
 docs/locale/zh/LC_MESSAGES/tools.po                |   91 ++
 docs/locale/zh/LC_MESSAGES/transactions.po         |  274 ++++
 docs/odc.rst                                       |    2 +
 docs/repositories.rst                              |   32 +
 docs/requirements-mocked.txt                       |    5 +
 docs/testing.rst                                   |  356 ++++-
 docs/transactions.rst                              |    4 +-
 etc/pycsw.desktop                                  |    1 -
 pavement.py                                        |  213 +--
 pycsw/__init__.py                                  |    6 +-
 pycsw/core/admin.py                                |   58 +-
 pycsw/core/config.py                               |    8 +-
 pycsw/core/etree.py                                |   12 +
 pycsw/core/formats/fmt_json.py                     |   27 +-
 pycsw/core/log.py                                  |    2 +-
 pycsw/core/metadata.py                             |  281 +++-
 pycsw/core/repository.py                           |  240 +++-
 pycsw/core/util.py                                 |  495 +++----
 pycsw/oaipmh.py                                    |   12 +-
 pycsw/ogc/csw/csw2.py                              |  161 ++-
 pycsw/ogc/csw/csw3.py                              |  194 +--
 pycsw/ogc/fes/fes1.py                              |   27 +-
 pycsw/ogc/fes/fes2.py                              |   27 +-
 pycsw/ogc/gml/gml3.py                              |   14 +-
 pycsw/opensearch.py                                |   37 +-
 pycsw/plugins/profiles/apiso/apiso.py              |    3 -
 pycsw/plugins/profiles/ebrim/ebrim.py              |    3 -
 pycsw/plugins/repository/geonode/geonode_.py       |  150 --
 pycsw/plugins/repository/hhypermap/__init__.py     |   29 -
 pycsw/plugins/repository/hhypermap/hhypermap.py    |  251 ----
 pycsw/plugins/repository/odc/odc.py                |    4 +-
 pycsw/server.py                                    |  188 ++-
 pycsw/sru.py                                       |    7 +-
 pycsw/wsgi.py                                      |  201 ++-
 requirements-dev.txt                               |   11 +-
 requirements.txt                                   |    8 +-
 setup.py                                           |  131 +-
 tests/conftest.py                                  |  115 ++
 ...te_get_f4692ec5-9547-4a05-88ab-e6154af2640a.xml |  310 ----
 ...30_get_2b06a5c8-0df2-4af1-8d2e-a425de11c845.xml |  493 -------
 ...30_get_43cd6471-6ac7-45bd-8ff9-148cb2de9a52.xml |  493 -------
 ...30_get_6a9d0558-9d87-495b-b999-b49a3ef1cf99.xml |  493 -------
 ...30_get_6e9cba43-5e27-415d-adbd-a92851c2c173.xml |  493 -------
 ...30_get_7e82446a-b5dc-43fe-9a73-4cc1f2f2f0bf.xml |  493 -------
 ...30_get_8025978e-1a35-4d70-80c2-e8329e0c7864.xml |  493 -------
 .../suites_csw30_get_GetCapabilities-base-url.xml  |  493 -------
 ...suites_csw30_get_GetCapabilities-no-version.xml |  493 -------
 .../expected/suites_csw30_get_GetCapabilities.xml  |  493 -------
 ...30_get_c03d173a-3f42-4956-89c8-1fe02c3a0873.xml |  493 -------
 ...30_get_e67ca935-d65d-4d8c-8302-1405333dded0.xml |  493 -------
 .../expected/suites_csw30_post_GetCapabilities.xml |  493 -------
 ...efault_post_Exception-GetRecords-badsrsname.xml |    7 -
 .../suites_harvesting_post_Harvest-wmts.xml        | 1517 --------------------
 .../suites_harvesting_post_Harvest-wps.xml         |   17 -
 ..._Harvest-zzz-post-GetRecords-filter-wfs-iso.xml |  370 -----
 tests/functionaltests/conftest.py                  |  570 ++++++++
 .../suites/apiso-inspire/default.cfg               |    0
 .../expected/get_GetCapabilities-lang.xml}         |    0
 .../expected/get_GetCapabilities.xml}              |    0
 .../suites/apiso-inspire/get/requests.txt          |    2 +
 .../suites/apiso/data/3e9a8c05.xml                 |    0
 .../suites/apiso/data/README.txt                   |    0
 .../data/T_aerfo_RAS_1991_GR800P001800000012.xml   |    0
 .../data/T_aerfo_RAS_1991_GR800P001800000013.xml   |    0
 .../data/T_aerfo_RAS_1991_GR800P001800000014.xml   |    0
 .../data/T_aerfo_RAS_1991_GR800P001800000015.xml   |    0
 .../suites/apiso/data/T_ortho_RAS_1998_284404.xml  |    0
 .../suites/apiso/data/T_ortho_RAS_1998_288395.xml  |    0
 .../suites/apiso/data/T_ortho_RAS_1998_288398.xml  |    0
 .../suites/apiso/data/T_ortho_RAS_1998_288401.xml  |    0
 .../suites/apiso/data/T_ortho_RAS_1998_288404.xml  |    0
 .../suites/apiso/data/T_pmoed_DTM_1996_276395.xml  |    0
 .../suites/apiso/data/T_pmoed_DTM_1996_276398.xml  |    0
 .../suites/apiso/data/T_pmoed_DTM_1996_276401.xml  |    0
 .../suites/apiso/data/T_pmoed_DTM_1996_276404.xml  |    0
 .../suites/apiso/data/T_pmoed_DTM_1996_280395.xml  |    0
 .../suites/apiso/data/pacioos-NS06agg.xml          |    0
 .../suites/apiso/data/test.xml                     |    0
 .../{ => functionaltests}/suites/apiso/default.cfg |    0
 .../suites/apiso/expected/post_DescribeRecord.xml} |    0
 .../apiso/expected/post_GetCapabilities.xml}       |    0
 .../apiso/expected/post_GetDomain-property.xml}    |    0
 .../apiso/expected/post_GetRecordById-brief.xml}   |    0
 .../apiso/expected/post_GetRecordById-full-dc.xml} |    0
 .../apiso/expected/post_GetRecordById-full.xml}    |    0
 .../expected/post_GetRecordById-srv-brief.xml}     |    0
 .../expected/post_GetRecords-all-csw-output.xml}   |    0
 .../suites/apiso/expected/post_GetRecords-all.xml} |    0
 .../apiso/expected/post_GetRecords-cql-title.xml}  |    0
 .../expected/post_GetRecords-elementname.xml}      |    0
 ...ords-filter-and-nested-spatial-or-dateline.xml} |    0
 .../expected/post_GetRecords-filter-anytext.xml}   |    0
 .../post_GetRecords-filter-bbox-csw-output.xml}    |    0
 .../expected/post_GetRecords-filter-bbox.xml}      |    0
 .../post_GetRecords-filter-servicetype.xml}        |    0
 .../suites/apiso/post/DescribeRecord.xml           |    0
 .../suites/apiso/post/GetCapabilities.xml          |    0
 .../suites/apiso/post/GetDomain-property.xml       |    0
 .../suites/apiso/post/GetRecordById-brief.xml      |    0
 .../suites/apiso/post/GetRecordById-full-dc.xml    |    0
 .../suites/apiso/post/GetRecordById-full.xml       |    0
 .../suites/apiso/post/GetRecordById-srv-brief.xml  |    0
 .../apiso/post/GetRecords-all-csw-output.xml       |    0
 .../suites/apiso/post/GetRecords-all.xml           |    0
 .../suites/apiso/post/GetRecords-cql-title.xml     |    0
 .../suites/apiso/post/GetRecords-elementname.xml   |    0
 ...cords-filter-and-nested-spatial-or-dateline.xml |    0
 .../apiso/post/GetRecords-filter-anytext.xml       |    0
 .../post/GetRecords-filter-bbox-csw-output.xml     |    0
 .../suites/apiso/post/GetRecords-filter-bbox.xml   |    0
 .../apiso/post/GetRecords-filter-servicetype.xml   |    0
 .../{ => functionaltests}/suites/atom/default.cfg  |    0
 .../atom/expected/get_opensearch-description.xml}  |    0
 .../expected/get_opensearch-ogc-bbox-and-time.xml} |    0
 .../atom/expected/get_opensearch-ogc-bbox.xml}     |    0
 .../get_opensearch-ogc-count-and-page1.xml}        |    0
 .../get_opensearch-ogc-count-and-page2.xml}        |    0
 .../expected/get_opensearch-ogc-q-and-bbox.xml}    |    0
 .../expected/get_opensearch-ogc-q-and-time.xml}    |    0
 .../suites/atom/expected/get_opensearch-ogc-q.xml} |    0
 .../atom/expected/get_opensearch-ogc-time.xml}     |    0
 .../atom/expected/get_opensearch-ogc-timeend.xml}  |    0
 .../expected/get_opensearch-ogc-timestart.xml}     |    0
 .../suites/atom/expected/get_opensearch.xml}       |    0
 .../suites/atom/expected/post_DescribeRecord.xml}  |    0
 .../suites/atom/expected/post_GetCapabilities.xml} |    0
 .../atom/expected/post_GetRecords-filter-bbox.xml} |    0
 tests/functionaltests/suites/atom/get/requests.txt |   12 +
 .../suites/atom/post/DescribeRecord.xml            |    0
 .../suites/atom/post/GetCapabilities.xml           |    0
 .../suites/atom/post/GetRecords-filter-bbox.xml    |    0
 .../suites/cite/data/README.txt                    |    0
 ...Record_19887a8a-f6b0-4a63-ae56-7fba0e17801f.xml |    0
 ...Record_1ef30a8b-876d-4828-9246-c37ab4510bbd.xml |    0
 ...Record_66ae76b7-54ba-489b-a582-0f0633d96493.xml |    0
 ...Record_6a3de50b-fa66-4b58-a0e6-ca146fdd18d4.xml |    0
 ...Record_784e2afd-a9fd-44a6-9a92-a3848371c8ec.xml |    0
 ...Record_829babb0-b2f1-49e1-8cd5-7b489fe71a1e.xml |    0
 ...Record_88247b56-4cbc-4df9-9860-db3f8042e357.xml |    0
 ...Record_94bc9c83-97f6-4b40-9eb8-a8e8787a5c63.xml |    0
 ...Record_9a669547-b69b-469f-a11f-2d875366bbdc.xml |    0
 ...Record_a06af396-3105-442d-8b40-22b57a90d2f2.xml |    0
 ...Record_ab42a8c4-95e8-4630-bf79-33e59241605a.xml |    0
 ...Record_e9330592-0932-474b-be34-c3a3bb67c7db.xml |    0
 .../{ => functionaltests}/suites/cite/data/cite.db |  Bin
 .../{ => functionaltests}/suites/cite/default.cfg  |    0
 .../get_27e17158-c57a-4493-92ac-dba8934cf462.xml}  |    2 +
 .../get_27f69b66-5f05-4311-a89c-73ca55c2686b.xml}  |    0
 .../get_2ab7d1fa-885b-459f-80e4-b6282eab4f8c.xml}  |    2 +
 .../get_37aa90e2-6ff0-420c-af15-8b9463099a73.xml}  |    0
 .../get_3a8a3c47-455f-4f49-9078-03119f3e70b3.xml}  |    0
 .../get_4515831f-834a-4699-95f6-ab0c2cbfcfd0.xml}  |    0
 .../get_477b23a3-baa9-47c8-9541-5fe27735ed49.xml}  |    3 +
 .../get_48f26761-3a9d-48db-bee1-da089f5fb857.xml}  |    2 +
 .../get_4e38092f-1586-44b8-988e-0acfa5855916.xml}  |    0
 .../get_55c38f00-2553-42c1-99ab-33edbb561ad7.xml}  |    3 +
 .../get_5ab5db18-c87a-4fbf-a8d8-b7289b09ac81.xml}  |    0
 .../get_6a4f57ca-a1bd-4802-89c2-44860dbdb0f0.xml}  |    0
 .../get_6c375703-9c00-4aef-bec7-d2e964f849eb.xml}  |    0
 .../get_80f31def-4185-48b9-983a-960566918eae.xml}  |    3 +
 .../get_8e2232ed-05d9-44ae-8b04-0911cbe6a507.xml}  |    0
 .../get_9697f0aa-3b6a-4125-83a5-61e8826127c4.xml}  |    3 +
 .../get_9bfd17fa-15dc-4a10-8fa7-b3cff7013dd7.xml}  |    0
 .../get_b81c3595-06d6-4693-82ea-1ff8650755ac.xml}  |    0
 .../get_ba5fc729-3b71-47a0-b7d0-42ec565cd185.xml}  |    2 +
 .../get_c4ea754f-c158-4d8d-8253-dc8f86021b52.xml}  |    0
 .../get_f4692ec5-9547-4a05-88ab-e6154af2640a.xml}  |    2 +
 .../get_f997f25e-c865-4d53-a362-0ed1846337f2.xml}  |    0
 .../post_0c976d98-c896-4b10-b1fe-a22ef50434e7.xml} |    0
 .../post_19d2a6ed-be28-4866-ae15-e3bb634486cb.xml} |    0
 .../post_1ab55aa3-6685-4595-8ecd-45987a7b8b59.xml} |    0
 .../post_1c958b7a-ca09-4c38-98bd-ef1d1d28cc14.xml} |    0
 .../post_1c97fc1a-61cd-4c1d-8054-933e17a6c5ee.xml} |    0
 .../post_2102a460-5d62-465f-9668-d70b3faafbfa.xml} |    0
 .../post_225f455a-0035-486b-a94e-fee7ae881b2b.xml} |    0
 .../post_2d53ffea-60e4-4652-abf5-36eb23042fd5.xml} |    0
 .../post_34a019a9-1581-42cb-9827-fbfdda2773b7.xml} |    0
 .../post_3e76fd38-e035-41c9-83dc-61356f680c97.xml} |    0
 .../post_418a6fb0-a89c-4a94-afc9-3f8168eb2980.xml} |    0
 .../post_420b745e-0c4b-404e-9f2d-61fa580ff05a.xml} |    0
 .../post_4735d649-a2b1-42fd-a101-14e1d7e4607f.xml} |    0
 .../post_5c5861bc-f742-40a5-9998-5342615d674b.xml} |    0
 .../post_6e736fd0-c266-4852-9eb3-0656f5d0f5c4.xml} |    0
 .../post_73f1551c-e269-4ef9-9dae-e535b5eebfc7.xml} |    0
 .../post_78297c88-4850-4927-adc6-511cd9a3d539.xml} |    0
 .../post_7c89cdf5-0def-4cfb-8c55-2b8ffea5d92f.xml} |    0
 .../post_7e2cd105-daec-4d25-bc8e-d49d21364912.xml} |    0
 .../post_87f2f670-9cd6-4907-b82c-1b46a7dd2a78.xml} |    0
 .../post_88b4e1ba-3bd4-4cbe-81e5-e004056d6ca3.xml} |    0
 .../post_898cd63b-2585-4ec0-8720-d554bd324174.xml} |    0
 .../post_8fb13dc3-5818-45e2-9e29-46abc16e7d38.xml} |    0
 .../post_928c1896-52d4-4ac7-9832-f98e3eb65f02.xml} |    0
 .../post_93bdbb9d-2734-4f01-92fb-48634cca41de.xml} |    0
 .../post_948b39d5-bb4f-45b8-a8f2-4ff9501aaedd.xml} |    0
 .../post_9fd64fcc-f69c-4626-b72e-5c7776a29aa9.xml} |    0
 .../post_a06d04ab-e0d0-4a86-bfe8-71460f41fe37.xml} |    0
 .../post_ad61686c-d304-42d1-b845-8c1f3070c83e.xml} |    0
 .../post_af39c020-7b1d-429c-b474-f45c3164cb79.xml} |    0
 .../post_b90e2de6-3d25-4298-a13e-dc9492a8fc73.xml} |    0
 .../post_ba9b0107-dcee-46ef-823a-a2e25a911a96.xml} |    0
 .../post_bb66ebc5-7121-48b5-9f53-b56537d9561b.xml} |    0
 .../post_c02d1c85-df9f-45ee-bea7-345c35e02a98.xml} |    0
 .../post_c311a342-72e3-4983-be39-868e6ed9740f.xml} |    0
 .../post_c38916c2-4bc6-446d-b7aa-ab006d6ba31c.xml} |    0
 .../post_c8588f47-8e65-45f5-ad34-ff4524cad84d.xml} |    0
 .../post_da228d4c-e1be-43d7-9ccb-c3f27ee32541.xml} |    0
 .../post_dc92c2c4-87d8-4a13-964e-ff9b0e0c27b3.xml} |    0
 .../post_dcb13791-379e-4739-bcd4-dbaa69f0efdb.xml} |    0
 .../post_e308f030-c097-4036-a838-44bad74c9ef7.xml} |    0
 .../post_e6e9efb2-e2b7-4b0a-a3a2-7deea3f9b8e2.xml} |    0
 .../post_f7976c55-a156-4421-8199-bc0487da4b0f.xml} |    0
 .../post_f7d79701-f10b-4087-a33c-f62df0a04fd1.xml} |    0
 .../post_fc1bc094-88f1-4851-bc2b-dfc56be9f3c7.xml} |    0
 .../post_fe20960f-a26c-4f13-852d-470a0d3233f9.xml} |    0
 tests/functionaltests/suites/cite/get/requests.txt |   22 +
 .../post/0c976d98-c896-4b10-b1fe-a22ef50434e7.xml  |    0
 .../post/19d2a6ed-be28-4866-ae15-e3bb634486cb.xml  |    0
 .../post/1ab55aa3-6685-4595-8ecd-45987a7b8b59.xml  |    0
 .../post/1c958b7a-ca09-4c38-98bd-ef1d1d28cc14.xml  |    0
 .../post/1c97fc1a-61cd-4c1d-8054-933e17a6c5ee.xml  |    0
 .../post/2102a460-5d62-465f-9668-d70b3faafbfa.xml  |    0
 .../post/225f455a-0035-486b-a94e-fee7ae881b2b.xml  |    0
 .../post/2d53ffea-60e4-4652-abf5-36eb23042fd5.xml  |    0
 .../post/34a019a9-1581-42cb-9827-fbfdda2773b7.xml  |    0
 .../post/3e76fd38-e035-41c9-83dc-61356f680c97.xml  |    0
 .../post/418a6fb0-a89c-4a94-afc9-3f8168eb2980.xml  |    0
 .../post/420b745e-0c4b-404e-9f2d-61fa580ff05a.xml  |    0
 .../post/4735d649-a2b1-42fd-a101-14e1d7e4607f.xml  |    0
 .../post/5c5861bc-f742-40a5-9998-5342615d674b.xml  |    0
 .../post/6e736fd0-c266-4852-9eb3-0656f5d0f5c4.xml  |    0
 .../post/73f1551c-e269-4ef9-9dae-e535b5eebfc7.xml  |    0
 .../post/78297c88-4850-4927-adc6-511cd9a3d539.xml  |    0
 .../post/7c89cdf5-0def-4cfb-8c55-2b8ffea5d92f.xml  |    0
 .../post/7e2cd105-daec-4d25-bc8e-d49d21364912.xml  |    0
 .../post/87f2f670-9cd6-4907-b82c-1b46a7dd2a78.xml  |    0
 .../post/88b4e1ba-3bd4-4cbe-81e5-e004056d6ca3.xml  |    0
 .../post/898cd63b-2585-4ec0-8720-d554bd324174.xml  |    0
 .../post/8fb13dc3-5818-45e2-9e29-46abc16e7d38.xml  |    0
 .../post/928c1896-52d4-4ac7-9832-f98e3eb65f02.xml  |    0
 .../post/93bdbb9d-2734-4f01-92fb-48634cca41de.xml  |    0
 .../post/948b39d5-bb4f-45b8-a8f2-4ff9501aaedd.xml  |    0
 .../post/9fd64fcc-f69c-4626-b72e-5c7776a29aa9.xml  |    0
 .../post/a06d04ab-e0d0-4a86-bfe8-71460f41fe37.xml  |    0
 .../post/ad61686c-d304-42d1-b845-8c1f3070c83e.xml  |    0
 .../post/af39c020-7b1d-429c-b474-f45c3164cb79.xml  |    0
 .../post/b90e2de6-3d25-4298-a13e-dc9492a8fc73.xml  |    0
 .../post/ba9b0107-dcee-46ef-823a-a2e25a911a96.xml  |    0
 .../post/bb66ebc5-7121-48b5-9f53-b56537d9561b.xml  |    0
 .../post/c02d1c85-df9f-45ee-bea7-345c35e02a98.xml  |    0
 .../post/c311a342-72e3-4983-be39-868e6ed9740f.xml  |    0
 .../post/c38916c2-4bc6-446d-b7aa-ab006d6ba31c.xml  |    0
 .../post/c8588f47-8e65-45f5-ad34-ff4524cad84d.xml  |    0
 .../post/da228d4c-e1be-43d7-9ccb-c3f27ee32541.xml  |    0
 .../post/dc92c2c4-87d8-4a13-964e-ff9b0e0c27b3.xml  |    0
 .../post/dcb13791-379e-4739-bcd4-dbaa69f0efdb.xml  |    0
 .../post/e308f030-c097-4036-a838-44bad74c9ef7.xml  |    0
 .../post/e6e9efb2-e2b7-4b0a-a3a2-7deea3f9b8e2.xml  |    0
 .../post/f7976c55-a156-4421-8199-bc0487da4b0f.xml  |    0
 .../post/f7d79701-f10b-4087-a33c-f62df0a04fd1.xml  |    0
 .../post/fc1bc094-88f1-4851-bc2b-dfc56be9f3c7.xml  |    0
 .../post/fe20960f-a26c-4f13-852d-470a0d3233f9.xml  |    0
 .../{ => functionaltests}/suites/csw30/default.cfg |    0
 .../get_002258f0-627f-457f-b2ad-025777c77ac8.xml}  |    0
 .../get_045c600d-973d-41eb-9f60-eba1b717b720.xml}  |    0
 .../get_0bbcf862-5211-4351-9988-63f8bec49c98.xml}  |    0
 .../get_0bdf8457-971e-4ed1-be4a-5feca4dcd8fa.xml}  |    1 +
 .../get_0d8bbdec-0846-42ca-8dc8-b7f4cba41d67.xml}  |    0
 .../get_0e1dca37-477a-4060-99fe-7799b52d656c.xml}  |    0
 .../get_13c87956-51a4-4780-a8e9-6e0b5c0bb473.xml}  |    0
 .../get_151d982f-ebd3-4cb2-b507-a667713a1e92.xml}  |    0
 .../get_1869e495-1a61-4713-8285-76d1336ee1a6.xml}  |    0
 .../get_1bcb42a9-538c-4f0a-9d4c-d6f10b720aa6.xml}  |    0
 .../get_22f44168-2ccf-4801-ad96-204212566d56.xml}  |    1 +
 .../get_2499a9c9-8d33-449c-bc92-d494adfcc84d.xml}  |    1 +
 .../get_27f4f39c-d92a-4e3c-b961-c6aa8c24e513.xml}  |    1 +
 .../get_28e569df-8596-4128-8d9a-29ad03138915.xml}  |    0
 .../get_2b06a5c8-0df2-4af1-8d2e-a425de11c845.xml}  |    1 +
 .../get_2ba1418a-444d-4cce-9cfe-4c94efcf8b55.xml}  |    0
 .../get_397fe17a-d5b4-4f96-8cc4-4ce467ed4d0a.xml}  |    0
 .../get_3dcd1b15-73d2-4b7d-a3e3-ff15bf14aae4.xml}  |    0
 .../get_405e1ff1-5c75-4846-a28b-cfaff2a6921a.xml}  |    0
 .../get_43cd6471-6ac7-45bd-8ff9-148cb2de9a52.xml}  |    1 +
 .../get_4566d2ec-1283-4a02-baed-a74fc5b47e37.xml}  |    0
 .../get_461bd4c5-6623-490d-9036-d91a2201e87b.xml}  |    0
 .../get_5496894a-3877-4f62-a20b-5d7126f94925.xml}  |    0
 .../get_5a015f6a-bf14-4977-b1e3-6577eb0223c8.xml}  |    0
 .../get_5c3a2390-1fb9-43f0-b96c-f48c7a69c990.xml}  |    0
 .../get_5e9e67dc-18d6-4645-8111-c6263c88a61f.xml}  |    1 +
 .../get_604d9379-741c-42e5-b4cf-92e56c87fa64.xml}  |    0
 .../get_60e6af95-d5fc-465a-82e2-fd2e6d85e4af.xml}  |    0
 .../get_62ad94c2-b558-4265-a427-23d6677975d6.xml}  |    0
 .../get_6a5e247b-0961-4b8a-a0d6-35a491d9cfe7.xml}  |    0
 .../get_6a9d0558-9d87-495b-b999-b49a3ef1cf99.xml}  |    1 +
 .../get_6bd790c9-6019-4652-9c91-330a894d6700.xml}  |    0
 .../get_6e9cba43-5e27-415d-adbd-a92851c2c173.xml}  |    1 +
 .../get_7630d230-e142-4a09-accf-f091000b90cd.xml}  |    0
 .../get_7e82446a-b5dc-43fe-9a73-4cc1f2f2f0bf.xml}  |    1 +
 .../get_8025978e-1a35-4d70-80c2-e8329e0c7864.xml}  |    1 +
 .../get_8184ae4f-536d-4978-8b28-ad703be96967.xml}  |    0
 .../get_88f63a89-664f-4315-b4f8-04a0b33803a7.xml}  |    0
 .../get_8987f8f0-4d93-4481-968c-a2ccbd6b8be2.xml}  |    0
 .../get_8e5fa0f6-3f29-4d1f-abe2-d9866f3def98.xml}  |    0
 .../get_9000ec29-5649-474e-b2d6-55c00f8a52c0.xml}  |    0
 .../get_91914d35-7bbf-45e6-9b37-5ef484869a4e.xml}  |    0
 .../get_92d4844d-57d5-4cf3-8f47-ba50e369dc04.xml}  |    0
 .../get_9c0e2a4b-b4e6-41c0-b630-c8c99fc89ff3.xml}  |    0
 .../get_9d7ffac8-9798-428d-8e27-3cd12497ee6b.xml}  |    0
 .../get_Exception-GetDomain-value-reference.xml}   |    0
 .../csw30/expected/get_Exception-GetDomain.xml}    |    0
 .../expected/get_Exception-GetRecordById-404.xml}  |    0
 .../get_Exception-GetRecordById-dc.xml.xml}        |    0
 .../get_Exception-GetRepositoryItem-notfound.xml}  |    0
 .../expected/get_Exception-invalid-request.xml}    |    0
 .../expected/get_GetCapabilities-base-url.xml}     |    1 +
 .../expected/get_GetCapabilities-no-version.xml}   |    1 +
 .../suites/csw30/expected/get_GetCapabilities.xml} |    1 +
 .../csw30/expected/get_GetDomain-parameter.xml}    |    0
 .../expected/get_GetDomain-value-reference.xml}    |    0
 .../csw30/expected/get_GetRepositoryItem.xml}      |    0
 .../csw30/expected/get_OpenSearch-description.xml} |    0
 .../get_a2f18643-e24e-4fa5-b780-6de4a2dbc814.xml}  |    0
 .../get_abc90c8c-5868-4405-a73e-64c849be3b2a.xml}  |    0
 .../get_ad0c0571-09ed-436a-9a4f-a5de744c88fe.xml}  |    0
 .../get_af502903-f4ee-47ee-b76e-af878d238bcc.xml}  |    0
 .../get_b2aafc3f-4f35-47bc-affd-08590972deae.xml}  |    0
 .../get_b6069623-f7d8-4021-8582-98f0aea0f763.xml}  |    0
 .../get_b9a07a54-75a8-45bd-b341-2823600211e3.xml}  |    2 +-
 .../get_baa4a7d0-0c01-42b6-adc3-0d03e9949fa3.xml}  |    0
 .../get_bfbe6409-f64a-4c89-acb3-50f260a5c743.xml}  |    0
 .../get_bfe20134-d1da-42ef-9c0f-8e1307bbf92b.xml}  |    0
 .../get_c03d173a-3f42-4956-89c8-1fe02c3a0873.xml}  |    1 +
 .../get_cb43d8c3-e14c-4a9f-9231-4384b7dd21f3.xml}  |    0
 .../get_d03c6fd3-e821-4a26-b62f-d20a474e25af.xml}  |    0
 .../get_d4ccbf96-a529-480e-a53d-5b88dc1dea7f.xml}  |    0
 .../get_d94c801a-1207-4897-b84a-53f3a192515b.xml}  |    0
 .../get_da859e34-91fc-495a-8c09-285a40c0900b.xml}  |    0
 .../get_dc246fb8-5af5-4fda-82bb-c18b3ecd439c.xml}  |    0
 .../get_de016645-6d5c-4855-943c-2db07ae9f49a.xml}  |    0
 .../get_dff3ec6b-bb2d-4887-bd17-8fcf15def042.xml}  |    0
 .../get_e38e6bfb-8ac4-4ae4-8b87-0aafbc8d3c6b.xml}  |    0
 .../get_e67ca935-d65d-4d8c-8302-1405333dded0.xml}  |    1 +
 .../get_e7704509-3441-458f-8ef0-e333c6b6043f.xml}  |    0
 .../get_f1223a49-6d08-44ff-97fe-4c32cbbfad82.xml}  |    0
 .../get_f89dd4e1-3a81-4433-afd2-a3fa1bdb1e18.xml}  |    0
 ...post_Exception-GetDomain-parametername-bad.xml} |    0
 ...ost_Exception-GetDomain-valuereference-bad.xml} |    0
 .../expected/post_Exception-GetRecordById-404.xml} |    0
 .../post_Exception-GetRecordById-bad-esn.xml}      |    0
 .../csw30/expected/post_Exception-bad-xml.xml}     |    0
 .../csw30/expected/post_Exception-not-xml.xml}     |    0
 .../csw30/expected/post_GetCapabilities.xml}       |    1 +
 .../expected/post_GetDomain-parametername.xml}     |    0
 .../expected/post_GetDomain-valuereference.xml}    |    0
 .../csw30/expected/post_GetRecordById-dc-full.xml} |    0
 .../csw30/expected/post_GetRecordById-dc.xml}      |    0
 .../functionaltests/suites/csw30/get/requests.txt  |   82 ++
 .../post/Exception-GetDomain-parametername-bad.xml |    0
 .../Exception-GetDomain-valuereference-bad.xml     |    0
 .../csw30/post/Exception-GetRecordById-404.xml     |    0
 .../csw30/post/Exception-GetRecordById-bad-esn.xml |    0
 .../suites/csw30/post/Exception-bad-xml.xml        |    0
 .../suites/csw30/post/Exception-not-xml.xml        |    0
 .../suites/csw30/post/GetCapabilities.xml          |    0
 .../suites/csw30/post/GetDomain-parametername.xml  |    0
 .../suites/csw30/post/GetDomain-valuereference.xml |    0
 .../suites/csw30/post/GetRecordById-dc-full.xml    |    0
 .../suites/csw30/post/GetRecordById-dc.xml         |    0
 .../suites/default/default.cfg                     |    0
 .../get_Exception-GetRepositoryItem-notfound.xml}  |    0
 ...ception-GetRepositoryItem-service-invalid1.xml} |    0
 ...ception-GetRepositoryItem-service-invalid2.xml} |    0
 ...xception-GetRepositoryItem-version-invalid.xml} |    0
 .../get_GetCapabilities-invalid-request.xml}       |    0
 .../default/expected/get_GetCapabilities.xml}      |    0
 .../default/expected/get_GetRecords-all.xml}       |    0
 .../expected/get_GetRecords-empty-maxrecords.xml}  |    0
 ...s-filter-cql-title-or-abstract-with-spaces.xml} |    0
 ...et_GetRecords-filter-cql-title-or-abstract.xml} |    0
 ...-title-with-spaces-or-abstract-with-spaces.xml} |    0
 ...s-filter-cql-title-with-spaces-or-abstract.xml} |    0
 ...et_GetRecords-filter-cql-title-with-spaces.xml} |    0
 .../expected/get_GetRecords-filter-cql-title.xml}  |    0
 .../default/expected/get_GetRecords-filter.xml}    |    0
 .../expected/get_GetRecords-sortby-asc.xml}        |    0
 .../expected/get_GetRecords-sortby-desc.xml}       |    0
 .../get_GetRecords-sortby-invalid-order.xml}       |    0
 ...get_GetRecords-sortby-invalid-propertyname.xml} |    0
 .../default/expected/get_GetRepositoryItem.xml}    |    0
 .../default/expected/post_DescribeRecord-json.xml} |    2 +-
 .../default/expected/post_DescribeRecord.xml}      |    0
 .../post_Exception-GetRecords-badsrsname.xml}      |    2 +-
 .../post_Exception-GetRecords-elementname.xml}     |    0
 .../post_Exception-GetRecords-invalid-xml.xml}     |    0
 .../expected/post_GetCapabilities-SOAP.xml}        |    0
 .../expected/post_GetCapabilities-sections.xml}    |    0
 .../post_GetCapabilities-updatesequence.xml}       |    0
 .../default/expected/post_GetCapabilities.xml}     |    0
 .../default/expected/post_GetDomain-parameter.xml} |    0
 .../default/expected/post_GetDomain-property.xml}  |    0
 .../default/expected/post_GetRecordById-json.xml}  |    2 +-
 .../default/expected/post_GetRecordById.xml}       |    0
 .../default/expected/post_GetRecords-all-json.xml} |    2 +-
 .../post_GetRecords-all-resulttype-hits.xml}       |    0
 .../post_GetRecords-all-resulttype-validate.xml}   |    0
 .../expected/post_GetRecords-all-sortby-bbox.xml}  |    0
 .../default/expected/post_GetRecords-all.xml}      |    0
 .../post_GetRecords-bbox-filter-crs84.xml}         |    0
 .../post_GetRecords-cql-title-and-abstract.xml}    |    0
 .../expected/post_GetRecords-cql-title.xml}        |    0
 .../post_GetRecords-distributedsearch.xml}         |    0
 .../expected/post_GetRecords-elementname.xml}      |    0
 .../default/expected/post_GetRecords-end.xml}      |    0
 .../post_GetRecords-filter-and-bbox-freetext.xml}  |    0
 .../post_GetRecords-filter-and-nested-or.xml}      |    0
 .../post_GetRecords-filter-and-nested-or2.xml}     |    0
 .../post_GetRecords-filter-anytext-and-not.xml}    |    0
 .../post_GetRecords-filter-anytext-equal.xml}      |    0
 .../expected/post_GetRecords-filter-anytext.xml}   |    0
 .../post_GetRecords-filter-bbox-reproject.xml}     |    0
 .../post_GetRecords-filter-bbox-sortby.xml}        |    0
 .../expected/post_GetRecords-filter-bbox.xml}      |    0
 .../expected/post_GetRecords-filter-between.xml}   |    0
 .../post_GetRecords-filter-function-bad.xml}       |    0
 .../expected/post_GetRecords-filter-function.xml}  |    0
 .../expected/post_GetRecords-filter-not-bbox.xml}  |    0
 .../post_GetRecords-filter-or-bbox-freetext.xml}   |    0
 .../post_GetRecords-filter-or-nested-and.xml}      |    0
 .../post_GetRecords-filter-or-title-abstract.xml}  |    0
 .../expected/post_GetRecords-maxrecords.xml}       |    0
 .../expected/post_GetRecords-requestid.xml}        |    0
 .../default/expected/post_Harvest-default.xml}     |    0
 .../expected/post_Harvest-response-handler.xml}    |    0
 .../default/expected/post_Transaction-delete.xml}  |    0
 .../default/expected/post_Transaction-insert.xml}  |    0
 .../expected/post_Transaction-update-full.xml}     |    0
 .../post_Transaction-update-recordproperty.xml}    |    0
 .../suites/default/get/requests.txt                |   20 +
 .../suites/default/post/DescribeRecord-json.xml    |    0
 .../suites/default/post/DescribeRecord.xml         |    0
 .../post/Exception-GetRecords-badsrsname.xml       |    0
 .../post/Exception-GetRecords-elementname.xml      |    0
 .../post/Exception-GetRecords-invalid-xml.xml      |    0
 .../suites/default/post/GetCapabilities-SOAP.xml   |    0
 .../default/post/GetCapabilities-sections.xml      |    0
 .../post/GetCapabilities-updatesequence.xml        |    0
 .../suites/default/post/GetCapabilities.xml        |    0
 .../suites/default/post/GetDomain-parameter.xml    |    0
 .../suites/default/post/GetDomain-property.xml     |    0
 .../suites/default/post/GetRecordById-json.xml     |    0
 .../suites/default/post/GetRecordById.xml          |    0
 .../suites/default/post/GetRecords-all-json.xml    |    0
 .../post/GetRecords-all-resulttype-hits.xml        |    0
 .../post/GetRecords-all-resulttype-validate.xml    |    0
 .../default/post/GetRecords-all-sortby-bbox.xml    |    0
 .../suites/default/post/GetRecords-all.xml         |    0
 .../default/post/GetRecords-bbox-filter-crs84.xml  |    0
 .../post/GetRecords-cql-title-and-abstract.xml     |    0
 .../suites/default/post/GetRecords-cql-title.xml   |    0
 .../default/post/GetRecords-distributedsearch.xml  |    0
 .../suites/default/post/GetRecords-elementname.xml |    0
 .../suites/default/post/GetRecords-end.xml         |    0
 .../post/GetRecords-filter-and-bbox-freetext.xml   |    0
 .../post/GetRecords-filter-and-nested-or.xml       |    0
 .../post/GetRecords-filter-and-nested-or2.xml      |    0
 .../post/GetRecords-filter-anytext-and-not.xml     |    0
 .../post/GetRecords-filter-anytext-equal.xml       |    0
 .../default/post/GetRecords-filter-anytext.xml     |    0
 .../post/GetRecords-filter-bbox-reproject.xml      |    0
 .../default/post/GetRecords-filter-bbox-sortby.xml |    0
 .../suites/default/post/GetRecords-filter-bbox.xml |    0
 .../default/post/GetRecords-filter-between.xml     |    0
 .../post/GetRecords-filter-function-bad.xml        |    0
 .../default/post/GetRecords-filter-function.xml    |    0
 .../default/post/GetRecords-filter-not-bbox.xml    |    0
 .../post/GetRecords-filter-or-bbox-freetext.xml    |    0
 .../post/GetRecords-filter-or-nested-and.xml       |    0
 .../post/GetRecords-filter-or-title-abstract.xml   |    0
 .../suites/default/post/GetRecords-maxrecords.xml  |    0
 .../suites/default/post/GetRecords-requestid.xml   |    0
 .../suites/default/post/Harvest-default.xml        |    0
 .../default/post/Harvest-response-handler.xml      |    0
 .../suites/default/post/Transaction-delete.xml     |    0
 .../suites/default/post/Transaction-insert.xml     |    0
 .../default/post/Transaction-update-full.xml       |    0
 .../post/Transaction-update-recordproperty.xml     |    0
 tests/{ => functionaltests}/suites/dif/default.cfg |    0
 .../suites/dif/expected/post_DescribeRecord.xml}   |    0
 .../suites/dif/expected/post_GetCapabilities.xml}  |    0
 .../dif/expected/post_GetRecords-filter-bbox.xml}  |    0
 .../suites/dif/post/DescribeRecord.xml             |    0
 .../suites/dif/post/GetCapabilities.xml            |    0
 .../suites/dif/post/GetRecords-filter-bbox.xml     |    0
 .../{ => functionaltests}/suites/ebrim/default.cfg |    0
 .../suites/ebrim/expected/post_DescribeRecord.xml} |    0
 .../ebrim/expected/post_GetCapabilities.xml}       |    0
 .../expected/post_GetRecords-filter-bbox-full.xml} |    0
 .../expected/post_GetRecords-filter-bbox.xml}      |    0
 .../suites/ebrim/post/DescribeRecord.xml           |    0
 .../suites/ebrim/post/GetCapabilities.xml          |    0
 .../ebrim/post/GetRecords-filter-bbox-full.xml     |    0
 .../suites/ebrim/post/GetRecords-filter-bbox.xml   |    0
 .../{ => functionaltests}/suites/fgdc/default.cfg  |    0
 .../suites/fgdc/expected/post_DescribeRecord.xml}  |    0
 .../suites/fgdc/expected/post_GetCapabilities.xml} |    0
 .../fgdc/expected/post_GetRecords-filter-bbox.xml} |    0
 .../suites/fgdc/post/DescribeRecord.xml            |    0
 .../suites/fgdc/post/GetCapabilities.xml           |    0
 .../suites/fgdc/post/GetRecords-filter-bbox.xml    |    0
 .../{ => functionaltests}/suites/gm03/default.cfg  |    0
 .../suites/gm03/expected/post_GetCapabilities.xml} |    0
 .../gm03/expected/post_GetRecords-filter-bbox.xml} |    0
 .../suites/gm03/post/GetCapabilities.xml           |    0
 .../suites/gm03/post/GetRecords-filter-bbox.xml    |    0
 .../suites/harvesting/default.cfg                  |    0
 ...get_Exception-Harvest-invalid-resourcetype.xml} |    2 +-
 ...get_Exception-Harvest-missing-resourcetype.xml} |    0
 .../get_Exception-Harvest-missing-source.xml}      |    0
 .../get_Exception-Harvest-waf-bad-value.xml}       |    0
 ...get_Exception-Harvest-waf-no-records-found.xml} |    0
 .../expected/post_Clear-000-delete-all.xml}        |    0
 .../expected/post_Exception-Havest-csw-404.xml}    |    0
 .../harvesting/expected/post_GetCapabilities.xml}  |    2 +
 .../expected/post_GetDomain-parameter.xml}         |    1 +
 .../harvesting/expected/post_Harvest-csw-iso.xml}  |    0
 .../harvesting/expected/post_Harvest-csw-run1.xml} |    0
 .../harvesting/expected/post_Harvest-csw-run2.xml} |    0
 .../harvesting/expected/post_Harvest-dc.xml}       |    0
 .../harvesting/expected/post_Harvest-fgdc.xml}     |    0
 .../harvesting/expected/post_Harvest-iso.xml}      |    0
 .../harvesting/expected/post_Harvest-rdf.xml}      |    0
 .../harvesting/expected/post_Harvest-sos100.xml}   |    0
 .../harvesting/expected/post_Harvest-sos200.xml}   |    0
 .../harvesting/expected/post_Harvest-waf.xml}      |    0
 .../harvesting/expected/post_Harvest-wcs.xml}      |    0
 .../harvesting/expected/post_Harvest-wfs110.xml}   |    0
 .../harvesting/expected/post_Harvest-wfs200.xml    |   57 +
 .../harvesting/expected/post_Harvest-wms-run1.xml} |    0
 .../harvesting/expected/post_Harvest-wms-run2.xml} |    0
 .../harvesting/expected/post_Harvest-wmts.xml}     |   32 +-
 .../harvesting/expected/post_Harvest-wps.xml       |   57 +
 ..._Harvest-zzz-post-GetRecords-filter-ows-dc.xml} |    2 +-
 ...zzz-post-GetRecords-filter-sos-abstract-dc.xml} |    0
 ..._Harvest-zzz-post-GetRecords-filter-sos-dc.xml} |    0
 ...Harvest-zzz-post-GetRecords-filter-sos-iso.xml} |    0
 ..._Harvest-zzz-post-GetRecords-filter-wfs-iso.xml | 1041 ++++++++++++++
 ..._Harvest-zzz-post-GetRecords-filter-wms-dc.xml} |    2 +-
 ...Harvest-zzz-post-GetRecords-filter-wms-iso.xml} |    2 +-
 ...rvest-zzz-post-GetRecords-filter-wms-layer.xml} |    0
 ...vest-zzz-post-GetRecords-filter-wps-process.xml |   62 +
 .../expected/post_Transaction-000-delete-all.xml}  |    2 +-
 .../suites/harvesting/get/requests.txt             |    0
 .../harvesting/post/Clear-000-delete-all.xml       |    0
 .../harvesting/post/Exception-Havest-csw-404.xml   |    0
 .../suites/harvesting/post/GetCapabilities.xml     |    0
 .../suites/harvesting/post/GetDomain-parameter.xml |    0
 .../suites/harvesting/post/Harvest-csw-iso.xml     |    0
 .../suites/harvesting/post/Harvest-csw-run1.xml    |    0
 .../suites/harvesting/post/Harvest-csw-run2.xml    |    0
 .../suites/harvesting/post/Harvest-dc.xml          |    0
 .../suites/harvesting/post/Harvest-fgdc.xml        |    0
 .../suites/harvesting/post/Harvest-iso.xml         |    0
 .../suites/harvesting/post/Harvest-rdf.xml         |    0
 .../suites/harvesting/post/Harvest-sos100.xml      |    0
 .../suites/harvesting/post/Harvest-sos200.xml      |    0
 .../suites/harvesting/post/Harvest-waf.xml         |    0
 .../suites/harvesting/post/Harvest-wcs.xml         |    0
 .../suites/harvesting/post/Harvest-wfs110.xml}     |    0
 .../suites/harvesting/post/Harvest-wfs200.xml}     |    4 +-
 .../suites/harvesting/post/Harvest-wms-run1.xml    |    0
 .../suites/harvesting/post/Harvest-wms-run2.xml    |    0
 .../suites/harvesting/post/Harvest-wmts.xml        |    2 +-
 .../suites/harvesting/post/Harvest-wps.xml         |    0
 .../Harvest-zzz-post-GetRecords-filter-ows-dc.xml  |    0
 ...-zzz-post-GetRecords-filter-sos-abstract-dc.xml |    0
 .../Harvest-zzz-post-GetRecords-filter-sos-dc.xml  |    0
 .../Harvest-zzz-post-GetRecords-filter-sos-iso.xml |    0
 .../Harvest-zzz-post-GetRecords-filter-wfs-iso.xml |    0
 .../Harvest-zzz-post-GetRecords-filter-wms-dc.xml  |    0
 .../Harvest-zzz-post-GetRecords-filter-wms-iso.xml |    0
 ...arvest-zzz-post-GetRecords-filter-wms-layer.xml |    0
 ...est-zzz-post-GetRecords-filter-wps-process.xml} |   20 +-
 .../harvesting/post/Transaction-000-delete-all.xml |    0
 .../suites/manager/default.cfg                     |    0
 .../expected/post_Clear-000-delete-all.xml}        |    0
 .../manager/expected/post_GetCapabilities.xml}     |    2 +
 .../manager/expected/post_GetDomain-parameter.xml} |    1 +
 .../expected/post_Transaction-000-delete-all.xml}  |    0
 .../expected/post_Transaction-dc-01-insert.xml}    |    0
 .../post_Transaction-dc-02-update-full.xml}        |    0
 .../expected/post_Transaction-fgdc-01-insert.xml}  |    0
 .../post_Transaction-fgdc-02-update-recprop.xml}   |    0
 .../post_Transaction-fgdc-03-delete-all.xml}       |    0
 .../post_Transaction-iso-00-delete-all.xml}        |    0
 .../expected/post_Transaction-iso-01-insert.xml}   |    0
 .../post_Transaction-iso-02-update-full.xml}       |    0
 .../post_Transaction-iso-03-update-recprop.xml}    |    0
 ...ansaction-iso-04-update-recprop-no-matches.xml} |    0
 .../expected/post_Transaction-iso-05-delete.xml}   |    0
 .../expected/post_Transaction-xxx-delete-all.xml}  |    0
 .../suites/manager/post/Clear-000-delete-all.xml   |    0
 .../suites/manager/post/GetCapabilities.xml        |    0
 .../suites/manager/post/GetDomain-parameter.xml    |    0
 .../manager/post/Transaction-000-delete-all.xml    |    0
 .../manager/post/Transaction-dc-01-insert.xml      |    0
 .../manager/post/Transaction-dc-02-update-full.xml |    0
 .../manager/post/Transaction-fgdc-01-insert.xml    |    0
 .../post/Transaction-fgdc-02-update-recprop.xml    |    0
 .../post/Transaction-fgdc-03-delete-all.xml        |    0
 .../manager/post/Transaction-iso-00-delete-all.xml |    0
 .../manager/post/Transaction-iso-01-insert.xml     |    0
 .../post/Transaction-iso-02-update-full.xml        |    0
 .../post/Transaction-iso-03-update-recprop.xml     |    0
 ...ransaction-iso-04-update-recprop-no-matches.xml |    0
 .../manager/post/Transaction-iso-05-delete.xml     |    0
 .../manager/post/Transaction-xxx-delete-all.xml    |    0
 .../suites/oaipmh/default.cfg                      |    0
 .../get_GetRecord_bad_metadata_prefix.xml}         |    0
 .../suites/oaipmh/expected/get_GetRecord_dc.xml}   |    0
 .../suites/oaipmh/expected/get_GetRecord_iso.xml}  |    0
 .../oaipmh/expected/get_GetRecord_oai_dc.xml}      |    0
 .../suites/oaipmh/expected/get_Identify.xml}       |    0
 .../get_ListIdentifiers_bad_metadata_prefix.xml}   |    0
 .../oaipmh/expected/get_ListIdentifiers_dc.xml}    |    0
 .../oaipmh/expected/get_ListIdentifiers_iso.xml}   |    0
 ...et_ListIdentifiers_missing_metadata_prefix.xml} |    0
 .../expected/get_ListIdentifiers_oai_dc.xml}       |    0
 .../oaipmh/expected/get_ListMetadataFormats.xml}   |    0
 .../suites/oaipmh/expected/get_ListRecords_dc.xml} |    0
 .../get_ListRecords_dc_bad_metadata_prefix.xml}    |    0
 .../oaipmh/expected/get_ListRecords_iso19139.xml}  |    0
 .../oaipmh/expected/get_ListRecords_oai_dc.xml}    |    0
 .../suites/oaipmh/expected/get_ListSets.xml}       |    0
 .../suites/oaipmh/expected/get_bad_verb.xml}       |    0
 .../suites/oaipmh/expected/get_empty.xml}          |    0
 .../suites/oaipmh/expected/get_empty_with_amp.xml} |    0
 .../suites/oaipmh/expected/get_illegal_verb.xml}   |    0
 .../functionaltests/suites/oaipmh/get/requests.txt |   20 +
 .../suites/repofilter/default.cfg                  |    0
 .../expected/post_GetRecordById-masked.xml}        |    0
 .../repofilter/expected/post_GetRecords-all.xml}   |    0
 .../repofilter/post/GetRecordById-masked.xml       |    0
 .../suites/repofilter/post/GetRecords-all.xml      |    0
 tests/{ => functionaltests}/suites/sru/default.cfg |    0
 .../suites/sru/expected/get_explain.xml}           |    0
 .../suites/sru/expected/get_search.xml}            |    0
 .../suites/sru/expected/get_search_cql.xml}        |    0
 .../suites/sru/expected/get_search_maxrecords.xml} |    0
 .../get_search_startrecord_maxrecords.xml}         |    0
 tests/functionaltests/suites/sru/get/requests.txt  |    5 +
 .../{ => functionaltests}/suites/utf-8/default.cfg |    0
 .../utf-8/expected/post_GetCapabilities.xml}       |    0
 .../suites/utf-8/post/GetCapabilities.xml          |    0
 tests/functionaltests/test_suites_functional.py    |  395 +++++
 tests/gen_html.py                                  |   25 +-
 tests/index.html                                   | 1118 ++++++++++-----
 tests/run_tests.py                                 |  577 --------
 tests/suites/apiso-inspire/get/requests.txt        |    2 -
 tests/suites/atom/get/requests.txt                 |   12 -
 tests/suites/cite/get/requests.txt                 |   22 -
 tests/suites/csw30/get/requests.txt                |   82 --
 tests/suites/default/get/requests.txt              |   20 -
 tests/suites/harvesting/data/.gitkeep              |    0
 tests/suites/manager/data/.gitkeep                 |    0
 tests/suites/oaipmh/get/requests.txt               |   20 -
 tests/suites/sru/get/requests.txt                  |    5 -
 tests/unittests/test_fmt_json.py                   |   93 ++
 .../unittests/test_metadata.py                     |   35 +-
 .../unittests/test_ogc_csw_csw3.py                 |   21 +-
 .../unittests/test_opensearch.py                   |   43 +-
 tests/unittests/test_repository.py                 |   66 +
 tests/unittests/test_util.py                       |  252 ++++
 tests/unittests/test_wsgi.py                       |  153 ++
 tox.ini                                            |   18 +
 726 files changed, 10627 insertions(+), 11022 deletions(-)

diff --git a/.coveragerc b/.coveragerc
new file mode 100644
index 0000000..f6f4d2f
--- /dev/null
+++ b/.coveragerc
@@ -0,0 +1,12 @@
+[run]
+branch = True
+source = pycsw
+
+[paths]
+source =
+    pycsw
+    .tox/*/lib/python*/site-packages/pycsw
+    /usr/local/lib/python*/dist-packages/pycsw
+
+[report]
+show_missing = True
\ No newline at end of file
diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 0000000..2163322
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1,23 @@
+# build artifacts
+*.pyc
+*.egg-info
+build
+dist
+docs/_build
+MANIFEST
+
+# testing artifacts
+tests/index.html
+tests/results
+**.cache
+.coverage
+.tox
+
+# test configurations
+/default.cfg
+
+# git stuff
+.git
+
+# pycharm ide
+.idea
diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md
index 6f75fc0..702cceb 100644
--- a/.github/ISSUE_TEMPLATE.md
+++ b/.github/ISSUE_TEMPLATE.md
@@ -6,15 +6,15 @@
 - Python version:
 - pycsw version:
 - source/distribution
- - [ ] git clone
- - [ ] DebianGIS/UbuntuGIS
- - [ ] PyPI
- - [ ] zip/tar.gz
- - [ ] other (please specify):
+  - [ ] git clone
+  - [ ] DebianGIS/UbuntuGIS
+  - [ ] PyPI
+  - [ ] zip/tar.gz
+  - [ ] other (please specify):
 - web server
- - [ ] Apache/mod_wsgi
- - [ ] CGI
- - [ ] other (please specify): 
+  - [ ] Apache/mod_wsgi
+  - [ ] CGI
+  - [ ] other (please specify): 
 
 # Steps to Reproduce
 
diff --git a/.travis.yml b/.travis.yml
index 714532b..55aab98 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,38 +1,64 @@
 language: python
 
-sudo: required
+cache: pip
+
 dist: trusty
 
-python:
-  - "2.6"
-  - "2.7"
-  - "3.4"
-  - "3.5"
+jobs:
+  include:
+
+    - stage: unit-test
+      python: "2.7"
+      env: TOXENV=py27-sqlite
+      install: pip install codecov tox
+      script: tox -- --exitfirst -m unit
+      after_success: codecov --disable search --flags unittests
+
+    - stage: unit-test
+      python: "3.4"
+      env: TOXENV=py34-sqlite
+      install: pip install codecov tox
+      script: tox -- --exitfirst -m unit
+      after_success: codecov --disable search --flags unittests
+
+    - stage: unit-test
+      python: "3.5"
+      env: TOXENV=py35-sqlite
+      install: pip install codecov tox
+      script: tox -- --exitfirst -m unit
+      after_success: codecov --disable search --flags unittests
+
+    - stage: integration-test
+      python: "2.7"
+      env: TOXENV=py27-sqlite
+      install: pip install codecov tox
+      script: tox -- --exitfirst -m functional -k 'not harvesting'
+      after_success: codecov --disable search --flags integrationtests
+
+    - stage: integration-test
+      python: "3.4"
+      env: TOXENV=py34-sqlite
+      install: pip install codecov tox
+      script: tox -- --exitfirst -m functional -k 'not harvesting'
+      after_success: codecov --disable search --flags integrationtests
+
+    - stage: integration-test
+      python: "3.5"
+      env: TOXENV=py35-sqlite
+      install: pip install codecov tox
+      script: tox -- --exitfirst -m functional -k 'not harvesting'
+      after_success: codecov --disable search --flags integrationtests
 
-#matrix:
-#  allow_failures:
-#    - python: "3.4"
 
 addons:
   apt:
     packages:
-      - libgeos-c1
+      - libgeos-dev
+      - libpq-dev
       - libxml2-dev
+      - libxslt1-dev
+      - libz-dev
 
-before_script:
-  - pycsw-admin.py -c get_sysprof
-
-install:
-  - pip install -r requirements.txt
-  - pip install -r requirements-dev.txt
-  - pip install -r requirements-standalone.txt
-  - python setup.py -q install
-
-script:
-  - paver test
-
-after_script:
-  - paver stop
 
 notifications:
   irc:
diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md
new file mode 100644
index 0000000..80fe6be
--- /dev/null
+++ b/CODE_OF_CONDUCT.md
@@ -0,0 +1,46 @@
+# Contributor Covenant Code of Conduct
+
+## Our Pledge
+
+In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
+
+## Our Standards
+
+Examples of behavior that contributes to creating a positive environment include:
+
+* Using welcoming and inclusive language
+* Being respectful of differing viewpoints and experiences
+* Gracefully accepting constructive criticism
+* Focusing on what is best for the community
+* Showing empathy towards other community members
+
+Examples of unacceptable behavior by participants include:
+
+* The use of sexualized language or imagery and unwelcome sexual attention or advances
+* Trolling, insulting/derogatory comments, and personal or political attacks
+* Public or private harassment
+* Publishing others' private information, such as a physical or electronic address, without explicit permission
+* Other conduct which could reasonably be considered inappropriate in a professional setting
+
+## Our Responsibilities
+
+Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
+
+Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
+
+## Scope
+
+This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
+
+## Enforcement
+
+Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at pycsw-devel at lists.osgeo.org. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
+
+Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
+
+## Attribution
+
+This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
+
+[homepage]: http://contributor-covenant.org
+[version]: http://contributor-covenant.org/version/1/4/
diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst
index e551cc6..89b42c5 100644
--- a/CONTRIBUTING.rst
+++ b/CONTRIBUTING.rst
@@ -3,7 +3,7 @@ Contributing to pycsw
 
 The pycsw project openly welcomes contributions (bug reports, bug fixes, code
 enhancements/features, etc.).  This document will outline some guidelines on
-contributing to pycsw.  As well, the pycsw `community </community.html>`_ is a great place to
+contributing to pycsw.  As well, the pycsw `community <http://pycsw.org/community/>`_ is a great place to
 get an idea of how to connect and participate in pycsw community and development.
 
 pycsw has the following modes of contribution:
@@ -147,4 +147,4 @@ your own repository to ensure your pycsw repository is up to date with pycsw mas
 .. _`pylint`: http://www.logilab.org/857
 .. _`Sphinx`: http://sphinx-doc.org/
 .. _`developer tasks`: https://github.com/geopython/pycsw/wiki/Developer-Tasks
-.. _`mailing list`: http://pycsw.org/community.html#mailing_list
+.. _`mailing list`: http://pycsw.org/community#mailing-list
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..82ce805
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,117 @@
+# =================================================================
+#
+# Authors: Ricardo Garcia Silva <ricardo.garcia.silva at gmail.com>
+#
+# Copyright (c) 2017 Ricardo Garcia Silva
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation
+# files (the "Software"), to deal in the Software without
+# restriction, including without limitation the rights to use,
+# copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following
+# conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+#
+# =================================================================
+FROM alpine:3.4
+
+# There's bug in libxml2 v2.9.4 that prevents using an XMLParser with a schema
+# file.
+#
+# https://bugzilla.gnome.org/show_bug.cgi?id=766834
+#
+# It seems to have been fixed upstream, but the fix has not been released into
+# a new libxml2 version. As a workaround, we are sticking with the previous
+# version, which works fine.
+# This means that we need to use alpine's archives for version 3.1, which are
+# the ones that contain the previous version of libxml2
+#
+# Also, for some unkwnon reason, alpine 3.1 version of libxml2 depends on
+# python2. We'd rather use python3 for pycsw, so we install it too.
+RUN echo 'http://dl-cdn.alpinelinux.org/alpine/v3.1/main' >> /etc/apk/repositories \
+  && apk add --no-cache \
+    build-base \
+    ca-certificates \
+    postgresql-dev \
+    python3 \
+    python3-dev \
+    libpq \
+    libxslt-dev \
+    'libxml2<2.9.4' \
+    'libxml2-dev<2.9.4' \
+    wget \
+  && apk add --no-cache \
+    --repository http://dl-3.alpinelinux.org/alpine/edge/testing/ \
+    --allow-untrusted \
+    geos \
+    geos-dev
+
+RUN adduser -D -u 1000 pycsw
+
+WORKDIR /tmp/pycsw
+
+COPY \
+  requirements-standalone.txt \
+  requirements-pg.txt \
+  requirements-dev.txt \
+  requirements.txt \
+  ./
+
+RUN pip3 install --upgrade pip setuptools \
+  && pip3 install --requirement requirements.txt \
+  && pip3 install --requirement requirements-standalone.txt \
+  && pip3 install --requirement requirements-pg.txt \
+  && pip3 install gunicorn
+
+COPY pycsw pycsw/
+COPY bin bin/
+COPY setup.py .
+COPY MANIFEST.in .
+COPY VERSION.txt .
+COPY README.rst .
+
+RUN pip3 install .
+
+COPY tests tests/
+COPY docker docker/
+
+ENV PYCSW_CONFIG=/etc/pycsw/pycsw.cfg
+
+RUN mkdir /etc/pycsw \
+  && mv docker/pycsw.cfg ${PYCSW_CONFIG} \
+  && mkdir /var/lib/pycsw \
+  && chown pycsw:pycsw /var/lib/pycsw \
+  && cp docker/entrypoint.py /usr/local/bin/entrypoint.py \
+  && chmod a+x /usr/local/bin/entrypoint.py \
+  && cp -r tests /home/pycsw \
+  && cp requirements.txt /home/pycsw \
+  && cp requirements-standalone.txt /home/pycsw \
+  && cp requirements-pg.txt /home/pycsw \
+  && cp requirements-dev.txt /home/pycsw \
+  && chown -R pycsw:pycsw /home/pycsw/* \
+  && rm -rf *
+
+WORKDIR /home/pycsw
+
+USER pycsw
+
+
+EXPOSE 8000
+
+ENTRYPOINT [\
+  "python3", \
+  "/usr/local/bin/entrypoint.py" \
+]
diff --git a/MANIFEST.in b/MANIFEST.in
index 39a2604..84e216a 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -1,2 +1,3 @@
 recursive-include pycsw *.xsd
 include *.txt
+include README.rst
diff --git a/README.rst b/README.rst
new file mode 100644
index 0000000..1a9bc91
--- /dev/null
+++ b/README.rst
@@ -0,0 +1,23 @@
+pycsw README
+============
+
+.. image:: https://travis-ci.org/geopython/pycsw.svg?branch=master
+    :target: https://travis-ci.org/geopython/pycsw
+
+pycsw is an OGC CSW server implementation written in Python.
+
+pycsw fully implements the OpenGIS Catalogue Service Implementation 
+Specification (Catalogue Service for the Web). Initial development started in 
+2010 (more formally announced in 2011). The project is certified OGC 
+Compliant, and is an OGC Reference Implementation.  Since 2015, pycsw is an 
+official OSGeo Project.
+
+pycsw allows for the publishing and discovery of geospatial metadata via 
+numerous APIs (CSW 2/CSW 3, OpenSearch, OAI-PMH, SRU). Existing repositories 
+of geospatial metadata can also be exposed, providing a standards-based 
+metadata and catalogue component of spatial data infrastructures.
+
+pycsw is Open Source, released under an MIT license, and runs on all major 
+platforms (Windows, Linux, Mac OS X).
+
+Please read the docs at http://pycsw.org/docs for more information.
diff --git a/README.txt b/README.txt
deleted file mode 100644
index 5d7fc70..0000000
--- a/README.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-pycsw README
-============
-
-pycsw is an OGC CSW server implementation written in Python.
-
-pycsw fully implements the OpenGIS Catalogue Service Implementation Specification (Catalogue Service for the Web). Initial development started in 2010 (more formally announced in 2011). The project is certified OGC Compliant, and is an OGC Reference Implementation.  Since 2015, pycsw is an official OSGeo Project.
-
-pycsw allows for the publishing and discovery of geospatial metadata via numerous APIs (CSW 2/CSW 3, OpenSearch, OAI-PMH, SRU). Existing repositories of geospatial metadata can also be exposed, providing a standards-based metadata and catalogue component of spatial data infrastructures.
-
-pycsw is Open Source, released under an MIT license, and runs on all major platforms (Windows, Linux, Mac OS X).
-
-Please read the docs at http://pycsw.org/docs for more information.
diff --git a/VERSION.txt b/VERSION.txt
index 50ffc5a..ccbccc3 100644
--- a/VERSION.txt
+++ b/VERSION.txt
@@ -1 +1 @@
-2.0.3
+2.2.0
diff --git a/bin/pycsw-admin.py b/bin/pycsw-admin.py
index 65481bd..5676525 100755
--- a/bin/pycsw-admin.py
+++ b/bin/pycsw-admin.py
@@ -33,13 +33,10 @@
 from six.moves import configparser
 from six.moves import input
 import getopt
-import logging
 import sys
 
 from pycsw.core import admin, config
 
-logging.basicConfig(format='%(message)s', level=logging.DEBUG)
-
 CONTEXT = config.StaticContext()
 
 
diff --git a/default-sample.cfg b/default-sample.cfg
index 0433477..3a832c2 100644
--- a/default-sample.cfg
+++ b/default-sample.cfg
@@ -39,7 +39,7 @@ maxrecords=10
 #ogc_schemas_base=http://foo
 #federatedcatalogues=http://catalog.data.gov/csw
 #pretty_print=true
-#gzip_compresslevel=8
+gzip_compresslevel=9
 #domainquerytype=range
 #domaincounts=true
 #spatial_ranking=true
@@ -68,7 +68,7 @@ contact_postalcode=Zip or Postal Code
 contact_country=Country
 contact_phone=+xx-xxx-xxx-xxxx
 contact_fax=+xx-xxx-xxx-xxxx
-contact_email=Email Address
+contact_email=you at example.org
 contact_url=Contact URL
 contact_hours=Hours of Service
 contact_instructions=During hours of service.  Off on weekends.
@@ -76,7 +76,7 @@ contact_role=pointOfContact
 
 [repository]
 # sqlite
-database=sqlite:////var/www/pycsw/tests/suites/cite/data/records.db
+database=sqlite:////var/www/pycsw/tests/functionaltests/suites/cite/data/cite.db
 # postgres
 #database=postgresql://username:password@localhost/pycsw
 # mysql
diff --git a/default-sample.cfg b/docker/docker-stack-pycsw.cfg
similarity index 91%
copy from default-sample.cfg
copy to docker/docker-stack-pycsw.cfg
index 0433477..fab76af 100644
--- a/default-sample.cfg
+++ b/docker/docker-stack-pycsw.cfg
@@ -1,8 +1,10 @@
 # =================================================================
 #
 # Authors: Tom Kralidis <tomkralidis at gmail.com>
+#          Ricardo Garcia Silva <ricardo.garcia.silva at gmail.com>
 #
 # Copyright (c) 2015 Tom Kralidis
+# Copyright (c) 2017 Ricardo Garcia Silva
 #
 # Permission is hereby granted, free of charge, to any person
 # obtaining a copy of this software and associated documentation
@@ -28,14 +30,14 @@
 # =================================================================
 
 [server]
-home=/var/www/pycsw
+home=/home/pycsw
 url=http://localhost/pycsw/csw.py
 mimetype=application/xml; charset=UTF-8
 encoding=UTF-8
 language=en-US
 maxrecords=10
-#loglevel=DEBUG
-#logfile=/tmp/pycsw.log
+loglevel=DEBUG
+logfile=
 #ogc_schemas_base=http://foo
 #federatedcatalogues=http://catalog.data.gov/csw
 #pretty_print=true
@@ -76,9 +78,9 @@ contact_role=pointOfContact
 
 [repository]
 # sqlite
-database=sqlite:////var/www/pycsw/tests/suites/cite/data/records.db
+#database=sqlite:////home/pycsw/tests/functionaltests/suites/cite/data/cite.db
 # postgres
-#database=postgresql://username:password@localhost/pycsw
+database=postgresql://postgres:mypass@db/pycsw
 # mysql
 #database=mysql://username:password@localhost/pycsw?charset=utf8
 #mappings=path/to/mappings.py
diff --git a/pycsw/core/formats/fmt_json.py b/docker/docker-stack.yml
similarity index 59%
copy from pycsw/core/formats/fmt_json.py
copy to docker/docker-stack.yml
index ded6ac6..ea316c2 100644
--- a/pycsw/core/formats/fmt_json.py
+++ b/docker/docker-stack.yml
@@ -1,9 +1,8 @@
-# -*- coding: utf-8 -*-
 # =================================================================
 #
-# Authors: Tom Kralidis <tomkralidis at gmail.com>
+# Authors: Ricardo Garcia Silva <ricardo.garcia.silva at gmail.com>
 #
-# Copyright (c) 2015 Tom Kralidis
+# Copyright (c) 2017 Ricardo Garcia Silva
 #
 # Permission is hereby granted, free of charge, to any person
 # obtaining a copy of this software and associated documentation
@@ -27,18 +26,38 @@
 # OTHER DEALINGS IN THE SOFTWARE.
 #
 # =================================================================
+#
+#
+# This docker-stack file demos how to use the pycsw docker image with a
+# postgis database
+#
+# Use it with docker-compose or in a docker swarm:
+#
+# docker-compose --file docker-stack.yml --project pycsw up
+#
+# PYCSW_DOCKER_IMAGE=2.1-dev docker stack deploy --compose-file docker-stack.yml pycsw
+#
 
-import json
-from pycsw.core.util import xml2dict
+version: "3"
 
+services:
 
-def xml2json(xml_string, namespaces, pretty_print=False):
-    """Convert an xml string to JSON"""
+  db:
+    image: mdillon/postgis:9.6-alpine
+    environment:
+      POSTGRES_PASSWORD: mypass
+      POSTGRES_DB: pycsw
+      PGDATA: /var/lib/postgresql/data/pgdata
+    volumes:
+      - db-data:/var/lib/postgresql/data/pgdata
 
-    separators = (',', ': ')
+  pycsw:
+    image: geopython/pycsw:${PYCSW_DOCKER_VERSION}
+    ports:
+      - "8000:8000"
+    volumes:
+      - ./docker-stack-pycsw.cfg:/etc/pycsw/pycsw.cfg
 
-    if pretty_print:
-        return json.dumps(xml2dict(xml_string, namespaces),
-                          indent=4, separators=separators)
 
-    return json.dumps(xml2dict(xml_string, namespaces), separators=separators)
+volumes:
+  db-data:
diff --git a/docker/entrypoint.py b/docker/entrypoint.py
new file mode 100644
index 0000000..edcf405
--- /dev/null
+++ b/docker/entrypoint.py
@@ -0,0 +1,178 @@
+#!/usr/bin/env python3
+# =================================================================
+#
+# Authors: Ricardo Garcia Silva <ricardo.garcia.silva at gmail.com>
+#
+# Copyright (c) 2017 Ricardo Garcia Silva
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation
+# files (the "Software"), to deal in the Software without
+# restriction, including without limitation the rights to use,
+# copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following
+# conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+#
+# =================================================================
+
+"""Entrypoint script for docker containers.
+
+This module serves as the entrypoint for docker containers. Its main
+purpose is to set up the pycsw database so that newly generated
+containers may be useful soon after being launched, without requiring
+additional input.
+
+"""
+
+
+import argparse
+import logging
+import os
+from six.moves.configparser import SafeConfigParser
+from six.moves.configparser import NoOptionError
+import sys
+from time import sleep
+
+from sqlalchemy import create_engine
+from sqlalchemy.exc import OperationalError
+from sqlalchemy.exc import ProgrammingError
+
+from pycsw.core import admin
+
+logger = logging.getLogger(__name__)
+
+
+def launch_pycsw(pycsw_config, workers=2, reload=False):
+    """Launch pycsw.
+
+    Main function of this entrypoint script. It will read pycsw's config file
+    and handle the specified repository backend, after which it will yield
+    control to the gunicorn wsgi server.
+
+    The ``os.execlp`` function is used to launch gunicorn. This causes it to
+    replace the current process - something analogous to bash's `exec`
+    command, which seems to be a common techinque when writing docker
+    entrypoint scripts. This means gunicorn will become PID 1 inside the
+    container and it somehow simplifies the process of interacting with it
+    (e.g. if the need arises to restart the worker processes). It also allows
+    for a clean exit. See
+
+    http://docs.gunicorn.org/en/latest/signals.html
+
+    for more information on how to control gunicorn by sending UNIX signals.
+    """
+
+    db_url = pycsw_config.get("repository", "database")
+    db = db_url.partition(":")[0].partition("+")[0]
+    db_handler = {
+        "sqlite": handle_sqlite_db,
+        "postgresql": handle_postgresql_db,
+    }.get(db)
+    logger.debug("Setting up pycsw's data repository...")
+    logger.debug("Repository URL: {}".format(db_url))
+    db_handler(
+        db_url,
+        pycsw_config.get("repository", "table"),
+        pycsw_config.get("server", "home")
+    )
+    sys.stdout.flush()
+    # we're using --reload-engine=poll because there is a bug with gunicorn
+    # that prevents using inotify together with python3. For more info:
+    #
+    # https://github.com/benoitc/gunicorn/issues/1477
+    #
+
+    args = ["--reload", "--reload-engine=poll"] if reload else []
+    execution_args = ["gunicorn"] + args + [
+        "--bind=0.0.0.0:8000",
+        "--access-logfile=-",
+        "--error-logfile=-",
+        "--workers={}".format(workers),
+        "pycsw.wsgi",
+
+    ]
+    logger.debug("Launching pycsw with {} ...".format(" ".join(execution_args)))
+    os.execlp(
+        "gunicorn",
+        *execution_args
+    )
+
+
+def handle_sqlite_db(database_url, table_name, pycsw_home):
+    db_path = database_url.rpartition(":///")[-1]
+    if not os.path.isfile(db_path):
+        try:
+            os.makedirs(os.path.dirname(db_path))
+        except OSError as exc:
+            if exc.args[0] == 17:  # directory already exists
+                pass
+        admin.setup_db(database=database_url, table=table_name,
+                       home=pycsw_home)
+
+
+def handle_postgresql_db(database_url, table_name, pycsw_home):
+    _wait_for_postgresql_db(database_url)
+    try:
+        admin.setup_db(database=database_url, table=table_name,
+                       home=pycsw_home)
+    except ProgrammingError:
+        pass  # database tables are already created
+
+
+def _wait_for_postgresql_db(database_url, max_tries=10, wait_seconds=3):
+    logger.debug("Waiting for {!r}...".format(database_url))
+    engine = create_engine(database_url)
+    current_try = 0
+    while current_try < max_tries:
+        try:
+            engine.execute("SELECT version();")
+            logger.debug("Database is already up!")
+            break
+        except OperationalError:
+            logger.debug("Database not responding yet ...")
+            current_try += 1
+            sleep(wait_seconds)
+    else:
+        raise RuntimeError(
+            "Database not responding at {} after {} tries. "
+            "Giving up".format(database_url, max_tries)
+        )
+
+
+if __name__ == "__main__":
+    parser = argparse.ArgumentParser()
+    parser.add_argument(
+        "--workers",
+        default=2,
+        help="Number of workers to use by the gunicorn server. Defaults to 2."
+    )
+    parser.add_argument(
+        "-r",
+        "--reload",
+        action="store_true",
+        help="Should the gunicorn server automatically restart workers when "
+             "code changes? This option is only useful for development. "
+             "Defaults to False."
+    )
+    args = parser.parse_args()
+    config = SafeConfigParser()
+    config.read(os.getenv("PYCSW_CONFIG"))
+    try:
+        level = config.get("server", "loglevel").upper()
+    except NoOptionError:
+        level = "WARNING"
+    logging.basicConfig(level=getattr(logging, level))
+    launch_pycsw(config, workers=args.workers, reload=args.reload)
diff --git a/default-sample.cfg b/docker/pycsw.cfg
similarity index 93%
copy from default-sample.cfg
copy to docker/pycsw.cfg
index 0433477..c303df7 100644
--- a/default-sample.cfg
+++ b/docker/pycsw.cfg
@@ -1,8 +1,10 @@
 # =================================================================
 #
 # Authors: Tom Kralidis <tomkralidis at gmail.com>
+#          Ricardo Garcia Silva <ricardo.garcia.silva at gmail.com>
 #
 # Copyright (c) 2015 Tom Kralidis
+# Copyright (c) 2017 Ricardo Garcia Silva
 #
 # Permission is hereby granted, free of charge, to any person
 # obtaining a copy of this software and associated documentation
@@ -28,14 +30,14 @@
 # =================================================================
 
 [server]
-home=/var/www/pycsw
+home=/home/pycsw
 url=http://localhost/pycsw/csw.py
 mimetype=application/xml; charset=UTF-8
 encoding=UTF-8
 language=en-US
 maxrecords=10
-#loglevel=DEBUG
-#logfile=/tmp/pycsw.log
+loglevel=DEBUG
+logfile=
 #ogc_schemas_base=http://foo
 #federatedcatalogues=http://catalog.data.gov/csw
 #pretty_print=true
@@ -76,7 +78,7 @@ contact_role=pointOfContact
 
 [repository]
 # sqlite
-database=sqlite:////var/www/pycsw/tests/suites/cite/data/records.db
+database=sqlite:////home/pycsw/tests/functionaltests/suites/cite/data/cite.db
 # postgres
 #database=postgresql://username:password@localhost/pycsw
 # mysql
diff --git a/docs/_templates/indexsidebar.html b/docs/_templates/indexsidebar.html
index d47247e..3e758d6 100644
--- a/docs/_templates/indexsidebar.html
+++ b/docs/_templates/indexsidebar.html
@@ -11,7 +11,7 @@
 </p>
 
 <p>
-    <img alt="OSGeo Project" src="http://svn.osgeo.org/osgeo/marketing/logo/png8/150/OSGeo_project.png" height="64"/>
+    <img alt="OSGeo Project" src="https://raw.githubusercontent.com/OSGeo/osgeo/master/incubation/project/OSGeo_project.png" height="64"/>
 </p>
 
 <p>
diff --git a/docs/administration.rst b/docs/administration.rst
index a5e0dc4..7efd92f 100644
--- a/docs/administration.rst
+++ b/docs/administration.rst
@@ -144,7 +144,16 @@ To override the default settings:
   ...
   mappings=path/to/mappings.py
 
-See the :ref:`geonode` and :ref:`odc` for further examples.
+Note you can also reference mappings as a Python object as a dotted path:
+
+.. code-block:: none
+
+  [repository]
+  ...
+  mappings='path.to.pycsw_mappings'
+
+
+See the :ref:`geonode`, :ref:`hhypermap`, and :ref:`odc` for further examples.
 
 Existing Repository Requirements
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/docs/conf.py b/docs/conf.py
index 2444d54..6d991a5 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -41,6 +41,11 @@
 
 import sys, os
 
+try:
+    from unittest.mock import MagicMock
+except ImportError:
+    from mock import Mock as MagicMock
+
 # If extensions (or modules to document with autodoc) are in another directory,
 # add these directories to sys.path here. If the directory is relative to the
 # documentation root, use os.path.abspath to make it absolute, like shown here.
@@ -48,6 +53,9 @@ import sys, os
 
 # -- General configuration -----------------------------------------------------
 
+# locale 
+locale_dirs = ['locale/']
+
 # If your documentation needs a minimal Sphinx version, state it here.
 #needs_sphinx = '1.0'
 
@@ -322,3 +330,14 @@ epub_copyright = copyright
 
 # Allow duplicate toc entries.
 #epub_tocdup = True
+
+# mock out imports with C extensions for building on readthedocs.io
+
+class Mock(MagicMock):
+    @classmethod
+    def __getattr__(cls, name):
+            return MagicMock()
+
+MOCK_MODULES = ['shapely']
+sys.modules.update((mod_name, Mock()) for mod_name in MOCK_MODULES)
+
diff --git a/docs/docker.rst b/docs/docker.rst
new file mode 100644
index 0000000..ff20cb4
--- /dev/null
+++ b/docs/docker.rst
@@ -0,0 +1,169 @@
+Docker
+======
+
+pycsw is available as a Docker image. The image is hosted on the `Docker Hub`_.
+
+Assuming you already have docker installed, you can get a pycsw instance up
+and running by issuing the following command::
+
+    docker run -p 8000:8000 geopython/pycsw
+
+Docker will retrieve the pycsw image from Docker Hub (if needed) and then
+start a new container listening on port 8000.
+
+The default configuration will run pycsw with an sqlite repository backend
+loaded with some test data from the CITE test suite. You can use this to take
+pycsw for a test drive.
+
+
+Inspect logs
+------------
+
+The default configuration for the docker image outputs logs to stdout. This is
+common practice with docker containers and enables the inspection of logs
+with the ``docker logs`` command::
+
+    # run a pycsw container in the background
+    docker run \
+        --name pycsw-test \
+        --publish 8000:8000 \
+        --detach \
+        geopython/pycsw
+
+    # inspect logs
+    docker logs pycsw-test
+
+.. note::
+
+   In order to have pycsw logs being sent to standard output you must set
+   ``server.logfile=`` in the pycsw configuration file.
+
+
+Using pycsw-admin
+-----------------
+
+``pycsw-admin`` can be executed on a running container by
+using ``docker exec``::
+
+    docker exec -ti <running-container-id> pycsw-admin.py -h
+
+
+Running custom pycsw containers
+-------------------------------
+
+pycsw configuration
+^^^^^^^^^^^^^^^^^^^
+
+It is possible to supply a custom configuration file for pycsw as a bind 
+mount or as a docker secret (in the case of docker swarm). The configuration 
+file is searched at the value of the ``PYCSW_CONFIG`` environmental variable,
+which defaults to ``/etc/pycsw/pycsw.cfg``. 
+
+Supplying the configuration file via bind mount::
+
+    docker run \
+        --name pycsw \
+        --detach \
+        --volume <path-to-local-pycsw.cfg>:/etc/pycsw/pycsw.cfg \
+        --publish 8000:8000 \
+        geopython/pycsw
+
+Supplying the configuration file via docker secrets::
+
+    # first create a docker secret with the pycsw config file
+    docker secret create pycsw-config <path-to-local-pycsw.cfg>
+    docker service create \
+        --name pycsw \
+        --secret src=pycsw-config,target=/etc/pycsw/pycsw.cfg \
+        --publish 8000:8000
+        geopython/pycsw
+
+
+sqlite repositories
+^^^^^^^^^^^^^^^^^^^
+
+The default database repository is the CITE database that is used for running 
+pycsw's test suites. Docker volumes may be used to specify a custom sqlite
+database path. It should be mounted under ``/var/lib/pycsw``::
+
+    # first create a docker volume for persisting the database when
+    # destroying containers
+    docker volume create pycsw-db-data
+    docker run \
+        --volume db-data:/var/lib/pycsw \
+        --detach \
+        --publish 8000:8000
+        geopython/pycsw
+
+
+PostgreSQL repositories
+^^^^^^^^^^^^^^^^^^^^^^^
+
+Specifying a PostgreSQL repository is just a matter of configuring a custom
+pycsw.cfg file with the correct specification.
+
+Check `pycsw's github repository`_ for an example of a docker-compose/stack
+file that spins up a postgis database together with a pycsw instance.
+
+
+Setting up a development environment with docker
+------------------------------------------------
+
+Working on pycsw's code using docker enables an isolated environment that
+helps ensuring reproducibility while at the same time keeping your base
+system free from pycsw related dependencies. This can be achieved by:
+
+* Cloning pycsw's repository locally;
+* Starting up a docker container with appropriately set up bind mounts. In
+  addition, the pycsw docker image supports a ``reload`` flag that turns on
+  automatic reloading of the gunicorn web server whenever the code changes;
+* Installing the development dependencies by using ``docker exec`` with the
+  root user;
+
+The following instructions set up a fully working development environment::
+
+    # clone pycsw's repo
+    git clone https://github.com/geopython/pycsw.git
+
+    # start a container for development
+    cd pycsw
+    docker run \
+        --name pycsw-dev \
+        --detach \
+        --volume ${PWD}/pycsw:/usr/lib/python3.5/site-packages/pycsw \
+        --volume ${PWD}/docs:/home/pycsw/docs \
+        --volume ${PWD}/VERSION.txt:/home/pycsw/VERSION.txt \
+        --volume ${PWD}/LICENSE.txt:/home/pycsw/LICENSE.txt \
+        --volume ${PWD}/COMMITTERS.txt:/home/pycsw/COMMITTERS.txt \
+        --volume ${PWD}/CONTRIBUTING.rst:/home/pycsw/CONTRIBUTING.rst \
+        --volume ${PWD}/pycsw/plugins:/home/pycsw/pycsw/plugins \
+        --publish 8000:8000 \
+        geopython/pycsw --reload
+
+    # install additional dependencies used in tests and docs
+    docker exec \
+        -ti \
+        --user root \
+        pycsw-dev pip3 install -r requirements-dev.txt
+
+    # run tests (for example unit tests)
+    docker exec -ti pycsw-dev py.test -m unit
+
+    # build docs
+    docker exec -ti pycsw-dev sh -c "cd docs && make html"
+
+.. note::
+
+   Please note that the pycsw image only uses python 3.5 and that it also does
+   not install pycsw in editable mode. As such it is not possible to
+   use ``tox``.
+
+Since the docs directory is bind mounted from your host machine into the
+container, after building the docs you may inspect their content visually, for
+example by running::
+
+    firefox docs/_build/html/index.html
+
+
+.. _Docker Hub: https://hub.docker.com/r/geopython/pycsw/
+.. _pycsw's github repository: https://github.com/geopython/pycsw/tree/master/docker
diff --git a/docs/geonode.rst b/docs/geonode.rst
index 55c6645..a8139b1 100644
--- a/docs/geonode.rst
+++ b/docs/geonode.rst
@@ -12,4 +12,6 @@ GeoNode Setup
 
 pycsw is enabled and configured by default in GeoNode, so there are no additional steps required once GeoNode is setup.  See the ``CATALOGUE`` and ``PYCSW`` `settings.py entries`_ at http://docs.geonode.org/en/latest/developers/reference/django-apps.html#id1 for customizing pycsw within GeoNode.
 
+The GeoNode plugin is managed outside of pycsw within the GeoNode project.
+
 .. _`settings.py entries`: http://docs.geonode.org/en/latest/developers/reference/django-apps.html#id1
diff --git a/docs/hhypermap.rst b/docs/hhypermap.rst
index 5b3d889..fa6dd04 100644
--- a/docs/hhypermap.rst
+++ b/docs/hhypermap.rst
@@ -3,7 +3,7 @@
 HHypermap Configuration
 =======================
 
-HHypermap (Harvard Hypermap) Supervisor (https://github.com/cga-harvard/HHypermap) is an application that manages OWS, Esri REST, and other types of map service harvesting, and maintains uptime statistics for services and layers. HHypermap Supervisor will publish to HHypermap Search (based on Lucene) which provides a fast search and visualization environment for spatio-temporal materials. 
+HHypermap (Harvard Hypermap) Registry (https://github.com/cga-harvard/HHypermap) is an application that manages OWS, Esri REST, and other types of map service harvesting, and maintains uptime statistics for services and layers. HHypermap Registry will publish to HHypermap Search (based on Lucene) which provides a fast search and visualization environment for spatio-temporal materials.
 
 HHypermap uses CSW as a cataloguing mechanism to ingest, query and present geospatial metadata.
 
@@ -12,6 +12,8 @@ pycsw supports binding to an existing HHypermap repository for metadata query.
 HHypermap Setup
 ---------------
 
-pycsw is enabled and configured by default in HHypermap, so there are no additional steps required once HHypermap is setup.  See the ``PYCSW`` `settings/default.py entries`_ for customizing pycsw within HHypermap.
+pycsw is enabled and configured by default in HHypermap, so there are no additional steps required once HHypermap is setup.  See the ``REGISTRY_PYCSW`` `hypermap/settings.py entries`_ for customizing pycsw within HHypermap.
 
-.. _`settings/default.py entries`: https://github.com/cga-harvard/HHypermap/blob/master/hypermap/settings/default.py#L197
+The HHypermap plugin is managed outside of pycsw within the HHypermap project.  HHypermap settings must ensure that ``REGISTRY_PYCSW['repository']['source']`` is set to``hypermap.search.pycsw_repository``.
+
+.. _`hypermap/settings.py entries`: https://github.com/cga-harvard/HHypermap/blob/master/hypermap/settings.py
diff --git a/docs/index.rst b/docs/index.rst
index fc00ac7..b330a2a 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -14,6 +14,7 @@ pycsw |release| Documentation
 
    introduction
    installation
+   docker
    configuration
    administration
    csw-support
@@ -27,6 +28,7 @@ pycsw |release| Documentation
    transactions
    repofilters
    profiles
+   repositories
    outputschemas
    geonode
    hhypermap
diff --git a/docs/installation.rst b/docs/installation.rst
index 875648d..8dec9cb 100644
--- a/docs/installation.rst
+++ b/docs/installation.rst
@@ -6,7 +6,7 @@ Installation
 System Requirements
 -------------------
 
-pycsw is written in `Python <http://python.org>`_, and works with (tested) version 2.6, 2.7 and 3.4
+pycsw is written in `Python <http://python.org>`_, and works with (tested) version 2.7, 3.4 and 3.5
 
 pycsw requires the following Python supporting libraries:
 
diff --git a/docs/locale/zh/LC_MESSAGES/administration.po b/docs/locale/zh/LC_MESSAGES/administration.po
new file mode 100644
index 0000000..11a3d32
--- /dev/null
+++ b/docs/locale/zh/LC_MESSAGES/administration.po
@@ -0,0 +1,383 @@
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: pycsw 2.0-dev\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2016-12-17 17:33+0800\n"
+"PO-Revision-Date: 2016-06-01 08:59+0800\n"
+"Last-Translator: \n"
+"Language-Team: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 2.3.4\n"
+
+#: ../../administration.rst:4
+msgid "Administration"
+msgstr "管理"
+
+#: ../../administration.rst:6
+msgid ""
+"pycsw administration is handled by the ``pycsw-admin.py`` utility.  "
+"``pycsw-admin.py`` is installed as part of the pycsw install process and "
+"should be available in your PATH."
+msgstr ""
+"pycsw 通过工具 ``pycsw-admin.py`` 进行管理。 ``pycsw-admin.py`` 需作为 pycsw "
+"安装的一部分安装到系统,可在你的路径中使用。"
+
+#: ../../administration.rst:11
+msgid ""
+"Run ``pycsw-admin.py -h`` to see all administration operations and "
+"parameters"
+msgstr "运行 ``pycsw-admin.py -h`` 来查看所有的管理操作与参数。 "
+
+#: ../../administration.rst:14
+msgid "Metadata Repository Setup"
+msgstr "元数据库创建设置"
+
+#: ../../administration.rst:16
+msgid "pycsw supports the following databases:"
+msgstr "pycsw支持以下数据库:"
+
+#: ../../administration.rst:18
+msgid "SQLite3"
+msgstr ""
+
+#: ../../administration.rst:19 ../../administration.rst:114
+msgid "PostgreSQL"
+msgstr ""
+
+#: ../../administration.rst:20
+msgid "PostgreSQL with PostGIS enabled"
+msgstr ""
+
+#: ../../administration.rst:21
+msgid "MySQL"
+msgstr ""
+
+#: ../../administration.rst:24
+msgid ""
+"The easiest and fastest way to deploy pycsw is to use SQLite3 as the "
+"backend."
+msgstr "最简单快速部署 pycws 的方式是使用 SQLite3 作为数据存储。"
+
+#: ../../administration.rst:27
+msgid "PostgreSQL support includes support for PostGIS functions if enabled"
+msgstr "PostgreSQL支持PostGIS功能"
+
+#: ../../administration.rst:30
+msgid ""
+"If PostGIS (1.x or 2.x) is activated before setting up the "
+"pycsw/PostgreSQL database, then native PostGIS geometries will be "
+"enabled."
+msgstr ""
+"如果PostGIS(1.×或2.x)可在建立pycsw / PostgreSQL数据库之前激活,那么本机的PostGIS "
+"geometries就可以使用。"
+
+#: ../../administration.rst:32
+msgid ""
+"To expose your geospatial metadata via pycsw, perform the following "
+"actions:"
+msgstr "可通过 pycsw 发布你的地理空间元数据,可执行以下操作:"
+
+#: ../../administration.rst:34
+msgid "setup the database"
+msgstr "创建数据库"
+
+#: ../../administration.rst:35
+msgid "import metadata"
+msgstr "导入元数据"
+
+#: ../../administration.rst:36
+msgid "publish the repository"
+msgstr "数据库发布"
+
+#: ../../administration.rst:39
+msgid "Supported Information Models"
+msgstr "支持的信息模型"
+
+#: ../../administration.rst:41
+msgid "By default, pycsw supports the ``csw:Record`` information model."
+msgstr "pycsw本身默认支持 ``csw:Record`` 信息模型。"
+
+#: ../../administration.rst:44
+msgid "See :ref:`profiles` for information on enabling profiles"
+msgstr "请参考 :ref:`profiles` 有关配置文件的信息"
+
+#: ../../administration.rst:47
+msgid "Setting up the Database"
+msgstr "创建数据库"
+
+#: ../../administration.rst:53
+msgid "This will create the necessary tables and values for the repository."
+msgstr "需创建数据库必要的表格与数值"
+
+#: ../../administration.rst:55
+msgid ""
+"The database created is an `OGC SFSQL`_ compliant database, and can be "
+"used with any implementing software.  For example, to use with `OGR`_:"
+msgstr "需创建一个标准的 `OGC SFSQL`_ 数据库,此数据库可应用于任何软件。例如, `OGR`_ "
+
+#: ../../administration.rst:67
+msgid ""
+"If PostGIS is detected, the pycsw-admin.py script does not create the "
+"SFSQL tables as they are already in the database."
+msgstr "如检测到PostGIS, pycsw-admin.py脚本就不会再创建 SFSQL 表,因为数据库中已经存在了。"
+
+#: ../../administration.rst:71
+msgid "Loading Records"
+msgstr "加载记录"
+
+#: ../../administration.rst:77
+msgid ""
+"This will import all ``*.xml`` records from ``/path/to/records`` into the"
+" database specified in ``default.cfg`` (``repository.database``).  "
+"Passing ``-r`` to the script will process ``/path/to/records`` "
+"recursively.  Passing ``-y`` to the script will force overwrite existing "
+"metadata with the same identifier.  Note that ``-p`` accepts either a "
+"directory path or single file."
+msgstr ""
+"这时所有的 ``*.xml`` 记录就会从 ``/path/to/records`` 中导入到指定的数据库 ``default.cfg`` "
+"(``repository.database``)。将 ``-r`` 复制到脚本中, 程序 ``/path/to/records`` "
+"就会层层递归。将 ``-y`` 复制到脚本中, 程序 ``/path/to/records`` 将强制替换现有的相同元数据标识符。请注意, "
+"``-p`` 只能接受一个目录路径或单个文件。"
+
+#: ../../administration.rst:80
+msgid "Records can also be imported using CSW-T (see :ref:`transactions`)."
+msgstr "记录也可以使用 CSW-T导入 (请查看  :ref:`transactions` )"
+
+#: ../../administration.rst:83
+msgid "Exporting the Repository"
+msgstr "导出数据库"
+
+#: ../../administration.rst:89
+msgid ""
+"This will write each record in the database specified in ``default.cfg`` "
+"(``repository.database``) to an XML document on disk, in directory "
+"``/path/to/output_dir``."
+msgstr ""
+" ``default.cfg`` (``repository.database``) 会将数据库的每项记录都录入在磁盘XML文件的目录下 "
+"``/path/to/output_dir`` "
+
+#: ../../administration.rst:92
+msgid "Optimizing the Database"
+msgstr "优化数据库"
+
+#: ../../administration.rst:99
+msgid "This feature is relevant only for PostgreSQL and MySQL"
+msgstr "此功能只关联 PostgreSQL和MySQL"
+
+#: ../../administration.rst:102
+msgid "Deleting Records from the Repository"
+msgstr "从数据库中删除记录"
+
+#: ../../administration.rst:108
+msgid "This will empty the repository of all records."
+msgstr "数据库中的所有记录都会被清空"
+
+#: ../../administration.rst:111
+msgid "Database Specific Notes"
+msgstr "数据库特别需要注意的是"
+
+#: ../../administration.rst:116
+msgid ""
+"if PostGIS is not enabled, pycsw makes uses of PL/Python functions.  To "
+"enable PostgreSQL support, the database user must be able to create "
+"functions within the database. In case of recent PostgreSQL versions "
+"(9.x), the PL/Python extension must be enabled prior to pycsw setup"
+msgstr ""
+"若 PostGIS不可用,pycsw会启用 "
+"PL/Python功能。在PostgreSQL支持下,用户必须在数据库中创建这些功能。如果是最新版本PostgreSQL (9.x),PL/ "
+"Python扩展必须在pycsw安装之前可运行"
+
+#: ../../administration.rst:117
+msgid ""
+"`PostgreSQL Full Text Search`_ is supported for ``csw:AnyText`` based "
+"queries.  pycsw creates a tsvector column based on the text from anytext "
+"column. Then pycsw creates a GIN index against the anytext_tsvector "
+"column.  This is created automatically in ``pycsw.admin.setup_db``.  Any "
+"query against `csw:AnyText` or `apiso:AnyText` will process using "
+"PostgreSQL FTS handling"
+msgstr ""
+" `PostgreSQL Full Text Search`_ (全文搜索)是 ``csw:AnyText`` "
+"查询功能支撑的。pycsw创建的tsvector栏是基于文本anytext栏。然而pycsw创建的GIN索引却不是基于文本anytext栏。这在 "
+"``pycsw.admin.setup_db`` 是自动生成的。任何针对 `csw:AnyText` or `apiso:AnyText` "
+"的查询都是使用PostgreSQL FTS处理的。"
+
+#: ../../administration.rst:120
+msgid "PostGIS"
+msgstr ""
+
+#: ../../administration.rst:122
+msgid ""
+"pycsw makes use of PostGIS spatial functions and native geometry data "
+"type."
+msgstr "pycsw使用的是PostGIS空间功能和本地geometry数据类型"
+
+#: ../../administration.rst:123
+msgid ""
+"It is advised to install the PostGIS extension before setting up the "
+"pycsw database"
+msgstr "建议在创建pycsw数据库前先安装PostGIS扩展信息"
+
+#: ../../administration.rst:124
+msgid ""
+"If PostGIS is detected, the pycsw-admin.py script will create both a "
+"native geometry column and a WKT column, as well as a trigger to keep "
+"both synchronized."
+msgstr "一旦PostGIS被监测到,脚本pycsw-admin.py既会在本地 geometry栏创建,也会在WKT栏创建,就像是触发器一样,会保持同步 "
+
+#: ../../administration.rst:125
+msgid ""
+"In case PostGIS gets disabled, pycsw will continue to work with the "
+"`WKT`_ column"
+msgstr "一旦PostGIS被禁用,这时 `WKT`_ 栏中的pycsw会运行"
+
+#: ../../administration.rst:126
+msgid ""
+"In case of migration from plain PostgreSQL database to PostGIS, the "
+"spatial functions of PostGIS will be used automatically"
+msgstr "如果plain PostgreSQL数据库移入PostGIS中,PostGIS的空间功能将自行启动"
+
+#: ../../administration.rst:127
+msgid ""
+"When migrating from plain PostgreSQL database to PostGIS, in order to "
+"enable native geometry support, a \"GEOMETRY\" column named "
+"\"wkb_geometry\" needs to be created manually (along with the update "
+"trigger in ``pycsw.admin.setup_db``). Also the native geometries must be "
+"filled manually from the `WKT`_ field. Next versions of pycsw will "
+"automate this process"
+msgstr ""
+"如果plain PostgreSQL数据库移入PostGIS中, 一个名为 \"wkb_geometry\" 的 \"GEOMETRY\" "
+"栏就需要被手动创建出来(随着 ``pycsw.admin.setup_db`` 一起更新)。本地geometries也必须在 `WKT`_ "
+"中手动创建。pycsw的下一个版本就会将此过程自动化运行 "
+
+#: ../../administration.rst:132
+msgid "Mapping to an Existing Repository"
+msgstr "映射到现有的存储库"
+
+#: ../../administration.rst:134
+msgid ""
+"pycsw supports publishing metadata from an existing repository.  To "
+"enable this functionality, the default database mappings must be modified"
+" to represent the existing database columns mapping to the abstract core "
+"model (the default mappings are in ``pycsw/config.py:MD_CORE_MODEL``)."
+msgstr ""
+"pycsw支持在现在的存储库中发布元数据。为实现此功能,默认的数据库映射功能就必须替换掉原有的数据库栏,此数据库栏是映射到abstract "
+"core model 中的(默认的眏射方式在 ``pycsw/config.py:MD_CORE_MODEL`` 中)"
+
+#: ../../administration.rst:136
+msgid "To override the default settings:"
+msgstr "覆盖默认的安装设置:"
+
+#: ../../administration.rst:138
+msgid "define a custom database mapping based on ``etc/mappings.py``"
+msgstr "基于``etc/mappings.py``映射的自定义数据库"
+
+#: ../../administration.rst:139
+msgid ""
+"in ``default.cfg``, set ``repository.mappings`` to the location of the "
+"mappings.py file:"
+msgstr "在 ``default.cfg``中, 将 ``repository.mappings`` 配置到mappings.py 文件中:"
+
+#: ../../administration.rst:147
+msgid "Note you can also reference mappings as a Python object as a dotted path:"
+msgstr ""
+
+#: ../../administration.rst:156
+#, fuzzy
+msgid ""
+"See the :ref:`geonode`, :ref:`hhypermap`, and :ref:`odc` for further "
+"examples."
+msgstr "请参照 :ref:`geonode` 和 :ref:`odc` 查看更多例子."
+
+#: ../../administration.rst:159
+msgid "Existing Repository Requirements"
+msgstr "现有的存储需求"
+
+#: ../../administration.rst:161
+msgid ""
+"pycsw requires certain repository attributes and semantics to exist in "
+"any repository to operate as follows:"
+msgstr "pycsw需要特定的存储属性,也需要语义来操作如下程序:"
+
+#: ../../administration.rst:163
+msgid "``pycsw:Identifier``: unique identifier"
+msgstr "``pycsw:Identifier``:唯一的标识符"
+
+#: ../../administration.rst:164
+msgid ""
+"``pycsw:Typename``: typename for the metadata; typically the value of the"
+" root element tag (e.g. ``csw:Record``, ``gmd:MD_Metadata``)"
+msgstr "``pycsw:Typename``: 元数据的类型名;典型的根标签值(例如``csw:Record``, ``gmd:MD_Metadata``)"
+
+#: ../../administration.rst:165
+msgid ""
+"``pycsw:Schema``: schema for the metadata; typically the target namespace"
+" (e.g. ``http://www.opengis.net/cat/csw/2.0.2``, "
+"``http://www.isotc211.org/2005/gmd``)"
+msgstr ""
+"``pycsw:Schema``: "
+"元数据图表;典型的目标名称空间(例如``http://www.opengis.net/cat/csw/2.0.2``, "
+"``http://www.isotc211.org/2005/gmd``)"
+
+#: ../../administration.rst:166
+msgid "``pycsw:InsertDate``: date of insertion"
+msgstr "``pycsw:InsertDate``: 插入日期"
+
+#: ../../administration.rst:167
+msgid "``pycsw:XML``: full XML representation"
+msgstr "``pycsw:XML``:完整的XML表示形式"
+
+#: ../../administration.rst:168
+msgid ""
+"``pycsw:AnyText``: bag of XML element text values, used for full text "
+"search.  Realized with the following design pattern:"
+msgstr "``pycsw:AnyText``: XML元素文件值包,用于完整的文本搜索。实现了以下设计功能:"
+
+#: ../../administration.rst:170
+msgid "capture all XML element and attribute values"
+msgstr "获取所有的XML元素与属性值"
+
+#: ../../administration.rst:171
+msgid "store in repository"
+msgstr "存储数据库"
+
+#: ../../administration.rst:172
+msgid "``pycsw:BoundingBox``: string of `WKT`_ or `EWKT`_ geometry"
+msgstr "``pycsw:BoundingBox``: `WKT`_ or `EWKT`_ geometry字符串"
+
+#: ../../administration.rst:174
+msgid "The following repository semantics exist if the attributes are specified:"
+msgstr "一旦被指定了属性,以下的语义库就会自动存在 ︰"
+
+#: ../../administration.rst:176
+msgid "``pycsw:Keywords``: comma delimited list of keywords"
+msgstr "' pycsw:Keywords ': 以逗号分隔的关键字列表"
+
+#: ../../administration.rst:177
+msgid ""
+"``pycsw:Links``: structure of links in the format "
+"\"name,description,protocol,url[^,,,[^,,,]]\""
+msgstr "' pycsw:Links ': 链接的格式结构\"名称、 描述、 协议、 网页地址 [^,[^...]]\""
+
+#: ../../administration.rst:179
+msgid "Values of mappings can be derived from the following mechanisms:"
+msgstr "映射值由以下的结构获得:"
+
+#: ../../administration.rst:181
+msgid "text fields"
+msgstr "文本域"
+
+#: ../../administration.rst:182
+msgid "Python datetime.datetime or datetime.date objects"
+msgstr "Python ``datetime.datetime`` 或 ``datetime.date`` 对象"
+
+#: ../../administration.rst:183
+msgid "Python functions"
+msgstr "Python函数"
+
+#: ../../administration.rst:185
+msgid "Further information is provided in ``pycsw/config.py:MD_CORE_MODEL``."
+msgstr "在 'pycsw/config.py:MD_CORE_MODEL ' 中获得更多资料"
+
diff --git a/docs/locale/zh/LC_MESSAGES/api.po b/docs/locale/zh/LC_MESSAGES/api.po
new file mode 100644
index 0000000..0cccc6e
--- /dev/null
+++ b/docs/locale/zh/LC_MESSAGES/api.po
@@ -0,0 +1,57 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) 2010-2015, Tom Kralidis This work is licensed under a
+# Creative Commons Attribution 4.0 International License
+# This file is distributed under the same license as the pycsw package.
+# FIRST AUTHOR <EMAIL at ADDRESS>, 2016.
+#
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: pycsw 2.1-dev\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2016-07-21 21:02+0800\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL at ADDRESS>\n"
+"Language-Team: LANGUAGE <LL at li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 2.3.4\n"
+
+#: ../../api.rst:4
+msgid "API"
+msgstr ""
+
+#: ../../api.rst:6
+msgid ""
+"Python applications can integrate pycsw into their custom workflows.  "
+"This allows for seamless integate within frameworks like Flask and Django"
+msgstr "Python应用可以在自己的工作流中集成 pycsw 。"
+"这样就允许在 Flask与 Django 这样的框架中无缝集成"
+
+#: ../../api.rst:9
+msgid ""
+"Below are examples of where using the API (as opposed to the default "
+"WSGI/CGI services could be used:"
+msgstr "下面是一些使用API的示例(与缺省的可用的 WSGI/CGI 服务不同:)"
+
+#: ../../api.rst:12
+msgid "configuration based on a Python dict, or stored in a database"
+msgstr "基于Python字典 进行配置,或存储在数据库中 "
+
+#: ../../api.rst:13
+msgid "downstream request environment / framework (Flask, Django)"
+msgstr "下游请求环境/框架(Flask,Django)"
+
+#: ../../api.rst:14
+msgid "authentication or authorization logic"
+msgstr "认证或授权逻辑"
+
+#: ../../api.rst:15
+msgid "forcing CSW version 2.0.2 as default"
+msgstr "强制使用 CSW 版本2.0.2作为缺省情况"
+
+#: ../../api.rst:19
+msgid "Simple Flask Example"
+msgstr "简单的 Flask 示例"
+
diff --git a/docs/locale/zh/LC_MESSAGES/ckan.po b/docs/locale/zh/LC_MESSAGES/ckan.po
new file mode 100644
index 0000000..3e0ded1
--- /dev/null
+++ b/docs/locale/zh/LC_MESSAGES/ckan.po
@@ -0,0 +1,57 @@
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: pycsw 2.0-dev\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2015-11-23 21:42+0800\n"
+"PO-Revision-Date: 2016-06-01 09:14+0800\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+"Last-Translator: \n"
+"Language-Team: \n"
+"Language: zh_CN\n"
+"X-Generator: Poedit 1.8.7\n"
+
+#: ../../ckan.rst:4
+msgid "CKAN Configuration"
+msgstr "CKAN配置"
+
+#: ../../ckan.rst:6
+msgid ""
+"CKAN (http://ckan.org) is a powerful data management system that makes data "
+"accessible – by providing tools to streamline publishing, sharing, finding "
+"and using data. CKAN is aimed at data publishers (national and regional "
+"governments, companies and organizations) wanting to make their data open "
+"and available."
+msgstr ""
+"CKAN (http://ckan.org)是一个功能强大的数据管理系统,该系统提高了数据可访问"
+"性,通过提供工具来无缝地发布、共享、发现和使用数据。CKAN的目的在于使他们变成"
+"数据开放并可用的数据发布者(国家和地方政府、公司和组织)。"
+
+#: ../../ckan.rst:8
+msgid ""
+"`ckanext-spatial`_ is CKAN's geospatial extension.  The extension adds a "
+"spatial field to the default CKAN dataset schema, using PostGIS as the "
+"backend. This allows to perform spatial queries and display the dataset "
+"extent on the frontend. It also provides harvesters to import geospatial "
+"metadata into CKAN from other sources, as well as commands to support the "
+"CSW standard. Finally, it also includes plugins to preview spatial formats "
+"such as GeoJSON."
+msgstr ""
+" `ckanext 空间`_ 是 CKAN 的地理空间扩展。此功能扩展将空间的字段添加到默认的 "
+"CKAN 数据集架构中,使用 PostGIS 作为后端。可实现空间位置查询,还可显示前端数"
+"据集的扩展信息。它还有收集信息的功能,从其他来源处将地理空间的元数据导入到"
+"CKAN中,就如同CKAN也支持csw标准命令一样。最后,它还有可预览空间信息的插件,"
+"例如 GeoJSON。"
+
+#: ../../ckan.rst:11
+msgid "CKAN Setup"
+msgstr "CKAN设置"
+
+#: ../../ckan.rst:13
+msgid ""
+"Installation and configuration Instructions are provided as part of the "
+"ckanext-spatial `documentation`_."
+msgstr "安装和配置说明在ckanext-spatial的 `documentation`_ 部分"
diff --git a/docs/locale/zh/LC_MESSAGES/committers.po b/docs/locale/zh/LC_MESSAGES/committers.po
new file mode 100644
index 0000000..d2e4092
--- /dev/null
+++ b/docs/locale/zh/LC_MESSAGES/committers.po
@@ -0,0 +1,96 @@
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: pycsw 2.0-dev\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2016-05-28 11:27+0800\n"
+"PO-Revision-Date: 2016-06-01 09:24+0800\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 2.3.4\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+"Last-Translator: \n"
+"Language-Team: \n"
+"Language: zh_CN\n"
+"X-Generator: Poedit 1.8.7\n"
+
+#: ../../committers.rst:4
+msgid "Committers"
+msgstr "提交者,执行者,管理员"
+
+#: ../../../COMMITTERS.txt:2
+msgid "Login(s)"
+msgstr "登录"
+
+#: ../../../COMMITTERS.txt:2
+msgid "Name"
+msgstr "名字"
+
+#: ../../../COMMITTERS.txt:2
+msgid "Email / Contact"
+msgstr "联系方式/邮件"
+
+#: ../../../COMMITTERS.txt:2
+msgid "Area(s)"
+msgstr "领域"
+
+#: ../../../COMMITTERS.txt:4
+msgid "tomkralidis"
+msgstr "tomkralidis"
+
+#: ../../../COMMITTERS.txt:4
+msgid "Tom Kralidis"
+msgstr "Tom Kralidis"
+
+#: ../../../COMMITTERS.txt:4
+msgid "tomkralidis at gmail.com"
+msgstr "tomkralidis at gmail.com"
+
+#: ../../../COMMITTERS.txt:4 ../../../COMMITTERS.txt:7
+msgid "Overall"
+msgstr "总计"
+
+#: ../../../COMMITTERS.txt:5
+msgid "kalxas"
+msgstr "kalxas"
+
+#: ../../../COMMITTERS.txt:5
+msgid "Angelos Tzotsos"
+msgstr "Angelos Tzotsos"
+
+#: ../../../COMMITTERS.txt:5
+msgid "tzotsos at gmail.com"
+msgstr "tzotsos at gmail.com"
+
+#: ../../../COMMITTERS.txt:5
+msgid "INSPIRE, APISO profiles, Packaging"
+msgstr "INSPIRE, APISO profiles, Packaging"
+
+#: ../../../COMMITTERS.txt:6
+msgid "adamhinz"
+msgstr "adamhinz"
+
+#: ../../../COMMITTERS.txt:6
+msgid "Adam Hinz"
+msgstr "Adam Hinz"
+
+#: ../../../COMMITTERS.txt:6
+msgid "hinz dot adam at gmail.com"
+msgstr "hinz dot adam at gmail.com"
+
+#: ../../../COMMITTERS.txt:6
+msgid "WSGI/Server Deployment"
+msgstr "WSGI/服务器部署"
+
+#: ../../../COMMITTERS.txt:7
+msgid "ricardogsilva"
+msgstr "ricardogsilva"
+
+#: ../../../COMMITTERS.txt:7
+msgid "Ricardo Garcia Silva"
+msgstr "Ricardo Garcia Silva"
+
+#: ../../../COMMITTERS.txt:7
+msgid "ricardo.garcia.silva at gmail.com"
+msgstr "ricardo.garcia.silva at gmail.com"
diff --git a/docs/locale/zh/LC_MESSAGES/configuration.po b/docs/locale/zh/LC_MESSAGES/configuration.po
new file mode 100644
index 0000000..4703c7e
--- /dev/null
+++ b/docs/locale/zh/LC_MESSAGES/configuration.po
@@ -0,0 +1,482 @@
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: pycsw 2.0-dev\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2015-11-23 21:42+0800\n"
+"PO-Revision-Date: 2016-06-02 11:30+0800\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+"Last-Translator: \n"
+"Language-Team: \n"
+"Language: zh_CN\n"
+"X-Generator: Poedit 1.8.7\n"
+
+#: ../../configuration.rst:4
+msgid "Configuration"
+msgstr "配置"
+
+#: ../../configuration.rst:6
+msgid ""
+"pycsw's runtime configuration is defined by ``default.cfg``.  pycsw ships "
+"with a sample configuration (``default-sample.cfg``).  Copy the file to "
+"``default.cfg`` and edit the following:"
+msgstr ""
+"pycsw 的运行配置写为此格式 ``default.cfg`` 。 pycsw 还有一个示例配置 ("
+" ``default-sample.cfg`` )。 将文件复制到 ``default.cfg`` 并编辑以下内容 ︰"
+
+#: ../../configuration.rst:8
+msgid "**[server]**"
+msgstr "**[server]**"
+
+#: ../../configuration.rst:10
+msgid "**home**: the full filesystem path to pycsw"
+msgstr "**home**: pycsw 的完整文件系统路径"
+
+#: ../../configuration.rst:11
+msgid "**url**: the URL of the resulting service"
+msgstr "**url**: 生成服务器的网址"
+
+#: ../../configuration.rst:12
+msgid "**mimetype**: the MIME type when returning HTTP responses"
+msgstr "**mimetype**: 当HTTP响应时的MIME型"
+
+#: ../../configuration.rst:13
+msgid ""
+"**language**: the ISO 639-1 language and ISO 3166-1 alpha2 country code of "
+"the service (e.g. ``en-CA``, ``fr-CA``, ``en-US``)"
+msgstr ""
+"**language**: ISO 639-1 语言和 ISO 3166-1 α2服务器上的国家/地区代码 (例如 ``en-CA`` "
+"、``fr-CA``、 ``EN-US`` )"
+
+#: ../../configuration.rst:14
+msgid ""
+"**encoding**: the content type encoding (e.g. ``ISO-8859-1``, see https://"
+"docs.python.org/2/library/codecs.html#standard-encodings).  Default value "
+"is 'UTF-8'"
+msgstr ""
+"**encoding**: 编码的内容类别 (例如 ``ISO-8859-1``,见 https://docs.python.org/2/library/codecs.html#standard-encodings) 。"
+" 默认值是 'UTF-8'"
+
+#: ../../configuration.rst:15
+msgid ""
+"**maxrecords**: the maximum number of records to return by default.  This "
+"value is enforced if a CSW's client's ``maxRecords`` parameter is greater "
+"than ``server.maxrecords`` to limit capacity.  See :ref:`maxrecords-"
+"handling` for more information"
+msgstr ""
+"**maxrecords**: 默认情况下再次浏览记录的最大数目。如果CSW客户端的 ``maxRecords`` "
+"参数大于 ``server.maxrecords`` ,此值就会被强制性限制。 请参见 :ref:`maxrecords-handling` 的详细信息"
+
+#: ../../configuration.rst:16
+msgid ""
+"**loglevel**: the logging level (see http://docs.python.org/library/logging."
+"html#logging-levels)"
+msgstr ""
+"**loglevel**: 日志记录级别 (见 http://docs.python.org/library/logging."
+"html#logging-levels)"
+
+#: ../../configuration.rst:17
+msgid "**logfile**: the full file path to the logfile"
+msgstr "**logfile**:日志文件的完整文件系统路径"
+
+#: ../../configuration.rst:18
+msgid ""
+"**ogc_schemas_base**: base URL of OGC XML schemas tree file structure "
+"(default is http://schemas.opengis.net)"
+msgstr ""
+"**ogc_schemas_base**: OGC XML 模型文件结构树的网址库 (默认 http://schemas.opengis.net)"
+
+#: ../../configuration.rst:19
+msgid ""
+"**federatedcatalogues**: comma delimited list of CSW endpoints to be used "
+"for distributed searching, if requested by the client (see :ref:"
+"`distributedsearching`)"
+msgstr ""
+"**federatedcatalogues**: 如果客户端有用户请求加入时, CSW端以逗号分隔的列表就会用于分布式搜"
+"索 (请参阅 :ref:`distributedsearching` )"
+
+#: ../../configuration.rst:20
+msgid ""
+"**pretty_print**: whether to pretty print the output (``true`` or "
+"``false``).  Default is ``false``"
+msgstr "**pretty_print**: 输出的(''是'或'否')来确认是否要优质打印。 默认值为否"
+
+#: ../../configuration.rst:21
+msgid ""
+"**gzip_compresslevel**: gzip compression level, lowest is ``1``, highest is "
+"``9``.  Default is off"
+msgstr "**gzip_compresslevel**: 压缩级别,最低是 '1 ',最高是' 9 '。 默认值是不压缩"
+
+#: ../../configuration.rst:22
+msgid ""
+"**domainquerytype**: for GetDomain operations, how to output domain "
+"values.  Accepted values are ``list`` and ``range`` (min/max). Default is "
+"``list``"
+msgstr ""
+"**domainquerytype**: 在GetDomain中应当如何输出域值呢。 目前的域值有'列表'和'range' (最"
+"小/最大)。默认值是列表。"
+
+#: ../../configuration.rst:23
+msgid ""
+"**domaincounts**: for GetDomain operations, whether to provide frequency "
+"counts for values.  Accepted values are ``true`` and ``False``. Default is "
+"``false``"
+msgstr ""
+"**domaincounts**:在GetDomain中,是否要提供频率计数值的操作。 目前的值"
+"有'是'和'否' 。默认值为否"
+
+#: ../../configuration.rst:24
+msgid ""
+"**profiles**: comma delimited list of profiles to load at runtime (default "
+"is none).  See :ref:`profiles`"
+msgstr ""
+"**profiles**: 是否在运行时加载以逗号分隔的配置文件列表(默认为无)。 请参见 :ref:`profiles` 。"
+
+#: ../../configuration.rst:25
+msgid ""
+"**smtp_host**: SMTP host for processing ``csw:ResponseHandler`` parameter "
+"via outgoing email requests (default is ``localhost``)"
+msgstr ""
+"**smtp_host**: SMTP 主机(默认为' 本地主机 ')通过发送电子邮件请求的方式处理 "
+" ``csw:ResponseHandler`` 参数"
+
+#: ../../configuration.rst:26
+msgid ""
+"**spatial_ranking**: parameter that enables (``true`` or ``false``) ranking "
+"of spatial query results as per `K.J. Lanfear 2006 - A Spatial Overlay "
+"Ranking Method for a Geospatial Search of Text Objects  <http://pubs.usgs."
+"gov/of/2006/1279/2006-1279.pdf>`_."
+msgstr ""
+"**spatial_ranking**: 是否在对空间搜索的结果进行排名的一项参数(' 是' 或' 否' ),此排名"
+"参数在每“K.J. Lanfear 2006” - 文本对象空间搜索的一个空间覆盖排名方法,“K.J. "
+"Lanfear 2006”网址:<http: pubs.usgs.gov/of/2006/1279/2006-1279.pdf>_."
+
+#: ../../configuration.rst:28
+msgid "**[manager]**"
+msgstr ""
+
+#: ../../configuration.rst:30
+msgid ""
+"**transactions**: whether to enable transactions (``true`` or ``false``).  "
+"Default is ``false`` (see :ref:`transactions`)"
+msgstr "**transactions**: 是否可以交易 ( ``true`` 或 ``false`` )。 默认值为否 (请参阅 :ref:`transactions` )"
+
+#: ../../configuration.rst:31
+msgid ""
+"**allowed_ips**: comma delimited list of IP addresses (e.g. 192.168.0.103), "
+"wildcards (e.g. 192.168.0.*) or CIDR notations (e.g. 192.168.100.0/24) "
+"allowed to perform transactions (see :ref:`transactions`)"
+msgstr ""
+"**allowed_ips**: IP 地址 (如 192.168.0.103)、 通配符 (如 192.168.0.*) 或 CIDR "
+"表示法 (例如 192.168.100.0/24) 以逗号分隔的列表允许执行交易 (请 :ref:`transactions` ) "
+
+#: ../../configuration.rst:32
+msgid ""
+"**csw_harvest_pagesize**: when harvesting other CSW servers, the number of "
+"records per request to page by (default is 10)"
+msgstr ""
+"**csw_harvest_pagesize**: 当收集其它CSW服务器时,每项请求的记录数都会显示在各页"
+"中 (每页默认的数量为 10)"
+
+#: ../../configuration.rst:34
+msgid "**[metadata:main]**"
+msgstr ""
+
+#: ../../configuration.rst:36
+msgid "**identification_title**: the title of the service"
+msgstr "**identification_title**: 服务项目标题"
+
+#: ../../configuration.rst:37
+msgid "**identification_abstract**: some descriptive text about the service"
+msgstr "**identification_abstract**: 一些有关该服务的描述性文本"
+
+#: ../../configuration.rst:38
+msgid ""
+"**identification_keywords**: comma delimited list of keywords about the "
+"service"
+msgstr "**identification_keywords**: 以逗号分隔的服务器有关的关键字列表"
+
+#: ../../configuration.rst:39
+msgid ""
+"**identification_keywords_type**: keyword type as per the `ISO 19115 "
+"MD_KeywordTypeCode codelist <http://www.isotc211.org/2005/resources/"
+"Codelist/gmxCodelists.xml#MD_KeywordTypeCode>`_).  Accepted values are "
+"``discipline``, ``temporal``, ``place``, ``theme``, ``stratum``"
+msgstr ""
+"**identification_keywords_type**: 每 'ISO 19115 MD_KeywordTypeCode 代码列表"
+"<http: www.isotc211.org/2005/resources/codelist/gmxcodelists."
+"xml#md_keywordtypecode=\"\">' _)的关键字类型。 接受的值是"
+"``discipline``, ``temporal``, ``place``, ``theme``, ``stratum``"
+
+#: ../../configuration.rst:40
+msgid "**identification_fees**: fees associated with the service"
+msgstr "**identification_fees**: 与服务有关的费用"
+
+#: ../../configuration.rst:41
+msgid ""
+"**identification_accessconstraints**: access constraints associated with "
+"the service"
+msgstr "**identification_accessconstraints**: 访问与该服务相关的限制条目"
+
+#: ../../configuration.rst:42
+msgid "**provider_name**: the name of the service provider"
+msgstr "**provider_name**: 服务提供者的名字"
+
+#: ../../configuration.rst:43
+msgid "**provider_url**: the URL of the service provider"
+msgstr "**provider_url**: 服务提供者的网址"
+
+#: ../../configuration.rst:44
+msgid "**contact_name**: the name of the provider contact"
+msgstr "**provider_name**: 服务提供者联系人"
+
+#: ../../configuration.rst:45
+msgid "**contact_position**: the position title of the provider contact"
+msgstr "**contact_position**:提供者联系人的职位名称"
+
+#: ../../configuration.rst:46
+msgid "**contact_address**: the address of the provider contact"
+msgstr "**contact_address**: 提供者联系人的地址"
+
+#: ../../configuration.rst:47
+msgid "**contact_city**: the city of the provider contact"
+msgstr "**contact_city**:提供者联系人所在城市"
+
+#: ../../configuration.rst:48
+msgid ""
+"**contact_stateorprovince**: the province or territory of the provider "
+"contact"
+msgstr "**contact_stateorprovince**: 提供者联系人所在省份或更详细地址"
+
+#: ../../configuration.rst:49
+msgid "**contact_postalcode**: the postal code of the provider contact"
+msgstr "**contact_postalcode**: 提供者联系人所在地区的邮政编码"
+
+#: ../../configuration.rst:50
+msgid "**contact_country**: the country of the provider contact"
+msgstr "**contact_country**: 提供者联系人所在国籍"
+
+#: ../../configuration.rst:51
+msgid "**contact_phone**: the phone number of the provider contact"
+msgstr "**contact_phone**: 提供者联系人的电话号码"
+
+#: ../../configuration.rst:52
+msgid "**contact_fax**: the facsimile number of the provider contact"
+msgstr "**contact_fax**: 提供者联系人的传真号码"
+
+#: ../../configuration.rst:53
+msgid "**contact_email**: the email address of the provider contact"
+msgstr "**contact_email**: 提供者联系人的电子邮件地址"
+
+#: ../../configuration.rst:54
+msgid ""
+"**contact_url**: the URL to more information about the provider contact"
+msgstr "**contact_url**: 提供者联系人的详细URL"
+
+#: ../../configuration.rst:55
+msgid "**contact_hours**: the hours of service to contact the provider"
+msgstr "**contact_hours**: 提供者联系人的服务时数"
+
+#: ../../configuration.rst:56
+msgid "**contact_instructions**: the how to contact the provider contact"
+msgstr "**contact_instructions**: 如何与提供者取得联系"
+
+#: ../../configuration.rst:57
+msgid ""
+"**contact_role**: the role of the provider contact as per the `ISO 19115 "
+"CI_RoleCode codelist <http://www.isotc211.org/2005/resources/Codelist/"
+"gmxCodelists.xml#CI_RoleCode>`_).  Accepted values are ``author``, "
+"``processor``, ``publisher``, ``custodian``, ``pointOfContact``, "
+"``distributor``, ``user``, ``resourceProvider``, ``originator``, ``owner``, "
+"``principalInvestigator``"
+msgstr ""
+"**contact_role**: 在 'ISO 19115 CI_RoleCode 代码列表中:<http: www.isotc211."
+"org/2005/resources/codelist/gmxcodelists.xml#ci_rolecode=\"\">' _)有每位提供"
+"商联系人的职务。可接受的值包括  ``author``, "
+"``processor``, ``publisher``, ``custodian``, ``pointOfContact``, "
+"``distributor``, ``user``, ``resourceProvider``, ``originator``, ``owner``, "
+"``principalInvestigator``"
+
+#: ../../configuration.rst:59
+msgid "**[repository]**"
+msgstr "**[repository]**"
+
+#: ../../configuration.rst:61
+msgid ""
+"**database**: the full file path to the metadata database, in database URL "
+"format (see http://docs.sqlalchemy.org/en/latest/core/engines.html#database-"
+"urls)"
+msgstr ""
+"**database**:元数据库中完整的文件路径,数据库URL格式(见 http://docs.sqlalchemy.org/en/latest/core/engines.html#database-urls)"
+
+#: ../../configuration.rst:62
+msgid ""
+"**table**: the table name for metadata records (default is ``records``).  "
+"If you are using PostgreSQL with a DB schema other than ``public``, qualify "
+"the table like ``myschema.table``"
+msgstr ""
+"**table**:元数据记录的表名(默认为 ``records``)。如果您在使用除了``public``以外"
+"的DB模式PostgreSQL,表格就会被限定,像 ``myschema.table`` "
+
+#: ../../configuration.rst:63
+msgid ""
+"**mappings**: custom repository mappings (see :ref:`custom_repository`)"
+msgstr "**mappings**:自定义的映射库(请参见 :ref:`custom_repository` )"
+
+#: ../../configuration.rst:64
+msgid ""
+"**source**: the source of this repository only if not local (e.g. :ref:"
+"`geonode`, :ref:`odc`).  Supported values are ``geonode``, ``odc``"
+msgstr ""
+"**source**:不在本地的数据库源(例如:请参考 :ref:`geonode` ,  :ref:`odc` )。现有值为"
+"`geonode`,`odc`"
+
+#: ../../configuration.rst:65
+msgid ""
+"**filter**: server side database filter to apply as mask to all CSW "
+"requests (see :ref:`repofilters`)"
+msgstr ""
+"**filter**:服务器端的数据库过滤器,适用所有CSW请求掩码(请参阅: :ref:`repofilters`)"
+
+#: ../../configuration.rst:69
+msgid ""
+"See :ref:`administration` for connecting your metadata repository and "
+"supported information models."
+msgstr "请参阅: :ref:`administration` ,用于连接您的元数据信息库和支持信息模型。"
+
+#: ../../configuration.rst:74
+msgid "MaxRecords Handling"
+msgstr "最大记录处理"
+
+#: ../../configuration.rst:76
+msgid ""
+"The The following describes how ``maxRecords`` is handled by the "
+"configuration when handling ``GetRecords`` requests:"
+msgstr "下面介绍的是 ``maxRecords`` 怎样处理 ``GetRecords`` 请求时的配置"
+
+#: ../../configuration.rst:1
+msgid "server.maxrecords"
+msgstr ""
+
+#: ../../configuration.rst:1
+msgid "GetRecords.maxRecords"
+msgstr "
+
+#: ../../configuration.rst:1
+msgid "Result"
+msgstr "结果"
+
+#: ../../configuration.rst:1
+msgid "none set"
+msgstr "未设定"
+
+#: ../../configuration.rst:1
+msgid "none passed"
+msgstr "未通过"
+
+#: ../../configuration.rst:1
+msgid "10 (CSW default)"
+msgstr "10 (CSW 默认值)"
+
+#: ../../configuration.rst:1
+msgid "20"
+msgstr "20"
+
+#: ../../configuration.rst:1
+msgid "14"
+msgstr "14"
+
+#: ../../configuration.rst:1
+msgid "100"
+msgstr "100"
+
+#: ../../configuration.rst:1
+msgid "200"
+msgstr "200"
+
+#: ../../configuration.rst:90
+msgid "Alternate Configurations"
+msgstr "备用配置"
+
+#: ../../configuration.rst:92
+msgid ""
+"By default, pycsw loads ``default.cfg`` at runtime.  To load an alternate "
+"configuration, modify ``csw.py`` to point to the desired configuration.  "
+"Alternatively, pycsw supports explicitly specifiying a configuration by "
+"appending ``config=/path/to/default.cfg`` to the base URL of the service (e."
+"g. ``http://localhost/pycsw/csw.py?config=tests/suites/default/default."
+"cfg&service=CSW&version=2.0.2&request=GetCapabilities``).  When the "
+"``config`` parameter is passed by a CSW client, pycsw will override the "
+"default configuration location and subsequent settings with those of the "
+"specified configuration."
+msgstr ""
+"默认情况下,pycsw在运行时加载的是 ``default.cfg`` 。加载一个配置,修改``csw.py``来指定所需配置。"
+"另外,pycsw还可以通过附加 ``config=/path/to/default.cfg``到服务器的基础URL来显式定义一个配置,"
+"例如 ``http://localhost/pycsw/csw.py?config=tests/suites/default/default.cfg&service=CSW&version=2.0.2&request=GetCapabilities`` 。"
+"当 ``config`` 参数通过CSW客户端时,pycsw就会覆盖默认的配置所在地址,并且用这些指定的配置来完成接"
+"下来的一系列设置。"
+
+#: ../../configuration.rst:94
+msgid ""
+"This also provides the functionality to deploy numerous CSW servers with a "
+"single pycsw installation."
+msgstr "使用单个pycsw配置就可以部署大量的功能性CSW。"
+
+#: ../../configuration.rst:97
+msgid "Hiding the Location"
+msgstr "隐藏的位置"
+
+#: ../../configuration.rst:99
+msgid ""
+"Some deployments with alternate configurations prefer not to advertise the "
+"base URL with the ``config=`` approach.  In this case, there are many "
+"options to advertise the base URL."
+msgstr ""
+"在做基URL时,一些备用配置的部署不用 ``config=`` 方式做声明。通常状态下,会有"
+"很多别的方式来做声明。"
+
+#: ../../configuration.rst:102
+msgid "Environment Variables"
+msgstr "环境变量"
+
+#: ../../configuration.rst:104
+msgid ""
+"One option is using Apache's ``Alias`` and ``SetEnvIf`` directives.  For "
+"example, given the base URL ``http://localhost/pycsw/csw.py?config=foo."
+"cfg``, set the following in Apache's ``httpd.conf``:"
+msgstr ""
+"有一种选择是使用 Apache 的``Alias`` 和 ``SetEnvIf`` 指令。 例如,可以指定基 "
+"URL 'http://localhost/pycsw/csw.py?config=foo.cfg ',在 Apache 的 'httpd."
+"conf' 下配置以下指令 ︰"
+
+#: ../../configuration.rst:113
+msgid "Apache must be restarted after changes to ``httpd.conf``"
+msgstr "在更改 ``Httpd.conf``  后必须重新启动 Apache"
+
+#: ../../configuration.rst:115
+msgid ""
+"pycsw will use the configuration as set in the ``PYCSW_CONFIG`` environment "
+"variable in the same manner as if it was specified in the base URL.  Note "
+"that the configuration value ``server.url`` value must match the "
+"``Request_URI`` value so as to advertise correctly in pycsw's Capabilities "
+"XML."
+msgstr ""
+"pycsw 将以同样的方式配置设置 ``PYCSW_CONFIG`` 的环境变量,就如同它在基 URL 中"
+"指定了一样。 请注意,配置值 ``server.url`` 值必须匹配 ``Request_URI`` 值,这样"
+"在 pycsw 的功能 XML 中就可以做正确声明了。"
+
+#: ../../configuration.rst:118
+msgid "Wrapper Script"
+msgstr "包装器脚本"
+
+#: ../../configuration.rst:120
+msgid ""
+"Another option is to write a simple wrapper (e.g. ``csw-foo.sh``), which "
+"provides the same functionality and can be deployed without restarting "
+"Apache:"
+msgstr ""
+"另一个选择是编写一个简单的包装器 (如``csw-foo.sh``),也会有相同的功能,而且"
+"无需重新启动 Apache 也可以部署 ︰"
diff --git a/docs/locale/zh/LC_MESSAGES/contributing.po b/docs/locale/zh/LC_MESSAGES/contributing.po
new file mode 100644
index 0000000..9b614f5
--- /dev/null
+++ b/docs/locale/zh/LC_MESSAGES/contributing.po
@@ -0,0 +1,354 @@
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: pycsw 2.0-dev\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2015-11-23 21:42+0800\n"
+"PO-Revision-Date: 2016-06-03 15:38+0800\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+"Last-Translator: \n"
+"Language-Team: \n"
+"Language: zh_CN\n"
+"X-Generator: Poedit 1.8.7\n"
+
+#: ../../../CONTRIBUTING.rst:2
+msgid "Contributing to pycsw"
+msgstr "pycsw的贡献"
+
+#: ../../../CONTRIBUTING.rst:4
+msgid ""
+"The pycsw project openly welcomes contributions (bug reports, bug fixes, "
+"code enhancements/features, etc.).  This document will outline some "
+"guidelines on contributing to pycsw.  As well, the pycsw `community </"
+"community.html>`_ is a great place to get an idea of how to connect and "
+"participate in pycsw community and development."
+msgstr ""
+"Pycsw 项目是开源的 (bug 报告、 bug 修复、 代码增强功能等)。 此篇文章将概述"
+"pycsw 的一些作用。 pycsw'社区' </community.html> _ ,就是提供一些建议,应该"
+"如何连接和参与 pycsw 社区,并如何更好地发展。"
+
+#: ../../../CONTRIBUTING.rst:9
+msgid "pycsw has the following modes of contribution:"
+msgstr "以下是几项pycsw做出的贡献 ︰"
+
+#: ../../../CONTRIBUTING.rst:11 ../../../CONTRIBUTING.rst:25
+msgid "GitHub Commit Access"
+msgstr "GitHub 提交修改的权限"
+
+#: ../../../CONTRIBUTING.rst:12 ../../../CONTRIBUTING.rst:33
+msgid "GitHub Pull Requests"
+msgstr "GitHub 的请求"
+
+#: ../../../CONTRIBUTING.rst:15
+msgid "Code of Conduct"
+msgstr "行为准则"
+
+#: ../../../CONTRIBUTING.rst:17
+msgid ""
+"Contributors to this project are expected to act respectfully toward others "
+"in accordance with the `OSGeo Code of Conduct <http://www.osgeo.org/"
+"code_of_conduct>`_."
+msgstr ""
+"此项目的贡献者是遵守 'OSGeo 行为守则<http: www.osgeo.org/code_of_conduct>' _"
+
+#: ../../../CONTRIBUTING.rst:20
+msgid "Contributions and Licensing"
+msgstr "贡献和许可"
+
+#: ../../../CONTRIBUTING.rst:22
+msgid ""
+"Contributors are asked to confirm that they comply with project `license "
+"<https://github.com/geopython/pycsw/blob/master/LICENSE.txt>`_ guidelines."
+msgstr ""
+"贡献者应当符合 '许可证<https: github.com/geopython/pycsw/blob/master/"
+"license.txt>' _ 准则。"
+
+#: ../../../CONTRIBUTING.rst:27
+msgid ""
+"proposals to provide developers with GitHub commit access shall be emailed "
+"to the pycsw-devel `mailing list`_.  Proposals shall be approved by the "
+"pycsw development team.  Committers shall be added by the project admin"
+msgstr ""
+"建议开发人员提供 GitHub 的提交访问权限,此权限应通过电子邮件发送到pycsw-"
+"devel `mailing list`_。 希望 pycsw 开发团队可以允许。 应由项目管理员处添加访"
+"问者"
+
+#: ../../../CONTRIBUTING.rst:28
+msgid "removal of commit access shall be handled in the same manner"
+msgstr "应以同样的方式解除提交访问权限"
+
+#: ../../../CONTRIBUTING.rst:29
+msgid ""
+"each committer must send an email to the pycsw mailing list agreeing to the "
+"license guidelines (see `Contributions and Licensing Agreement Template "
+"<#contributions-and-licensing-agreement-template>`_).  **This is only "
+"required once**"
+msgstr ""
+"每个提交的用户必须发送电子邮件到 pycsw 邮件列表中,前得是同意许可证准则 "
+"(见 '贡献和许可协议模板 <#contributions-and-licensing-agreement-template>' "
+"_)。只需一次即可。"
+
+#: ../../../CONTRIBUTING.rst:30
+msgid ""
+"each committer shall be listed in https://github.com/geopython/pycsw/blob/"
+"master/COMMITTERS.txt"
+msgstr ""
+"每个提交的用户会显示在https://github.com/geopython/pycsw/blob/master/"
+"COMMITTERS.txt列表中"
+
+#: ../../../CONTRIBUTING.rst:35
+msgid ""
+"pull requests can provide agreement to license guidelines as text in the "
+"pull request or via email to the pycsw `mailing list`_  (see `Contributions "
+"and Licensing Agreement Template <#contributions-and-licensing-agreement-"
+"template>`_).  **This is only required for a contributor's first pull "
+"request.  Subsequent pull requests do not require this step**"
+msgstr ""
+"pull 请求可以提供协议许可准则,在pull请求时可作为文本,也可以电邮至 pycsw 邮"
+"件列表 (见 `贡献和许可协议模板<#contributions-and-licensing-agreement-template>`_ )。 这只需要在第一次Pull请求时使用。 后续的请求不需要此步骤"
+
+#: ../../../CONTRIBUTING.rst:36
+msgid ""
+"pull requests may include copyright in the source code header by the "
+"contributor if the contribution is significant or the contributor wants to "
+"claim copyright on their contribution"
+msgstr "如果有重大贡献或贡献者想要申请版权专利,pull请求可以将源代码设置权限"
+
+#: ../../../CONTRIBUTING.rst:37
+msgid ""
+"all contributors shall be listed at https://github.com/geopython/pycsw/"
+"graphs/contributors"
+msgstr ""
+"所有贡献者均在 https://github.com/geopython/pycsw/graphs/contributors 列表中"
+
+#: ../../../CONTRIBUTING.rst:38
+msgid ""
+"unclaimed copyright, by default, is assigned to the main copyright holders "
+"as specified in https://github.com/geopython/pycsw/blob/master/LICENSE.txt"
+msgstr ""
+"若无人声明版权所属,在默认情况下,会指定分配给主要的版权持有人,在https://"
+"github.com/geopython/pycsw/blob/master/LICENSE.txt中强调指出"
+
+#: ../../../CONTRIBUTING.rst:41
+msgid "Contributions and Licensing Agreement Template"
+msgstr "贡献和许可协议模板"
+
+#: ../../../CONTRIBUTING.rst:43
+msgid ""
+"``Hi all, I'd like to contribute <feature X|bugfix Y|docs|something else> "
+"to pycsw. I confirm that my contributions to pycsw will be compatible with "
+"the pycsw license guidelines at the time of contribution.``"
+msgstr ""
+"``大家好,我愿意在pycsw贡献 <feature X|bugfix Y|docs|something else>。我证"
+"明,我对pycsw的贡献将与pycsw许可指南兼容。``"
+
+#: ../../../CONTRIBUTING.rst:49
+msgid "GitHub"
+msgstr "GitHub"
+
+#: ../../../CONTRIBUTING.rst:51
+msgid ""
+"Code, tests, documentation, wiki and issue tracking are all managed on "
+"GitHub. Make sure you have a `GitHub account <https://github.com/signup/"
+"free>`_."
+msgstr ""
+"代码,测试,文档,wiki和问题都在GitHub上进行追踪管理,以确保每个人均有一个自"
+"己的 GitHub的账户<https://github.com/signup/free> 。 "
+
+#: ../../../CONTRIBUTING.rst:55
+msgid "Code Overview"
+msgstr "代码概览"
+
+#: ../../../CONTRIBUTING.rst:57
+msgid ""
+"the pycsw `wiki <https://github.com/geopython/pycsw/wiki/Code-"
+"Architecture>`_ documents an overview of the codebase"
+msgstr ""
+"在pycsw `维基 <https://github.com/geopython/pycsw/wiki/Code-Architecture>`_ 有"
+"详细的代码库概述"
+
+#: ../../../CONTRIBUTING.rst:60
+msgid "Documentation"
+msgstr "说明文件"
+
+#: ../../../CONTRIBUTING.rst:62
+msgid "documentation is managed in ``docs/``, in reStructuredText format"
+msgstr "文档在 ``docs/`` 中管理,以reStructuredText格式"
+
+#: ../../../CONTRIBUTING.rst:63
+msgid "`Sphinx`_ is used to generate the documentation"
+msgstr "`Sphinx`_ 作用是生成文档"
+
+#: ../../../CONTRIBUTING.rst:64
+msgid ""
+"See the `reStructuredText Primer <http://sphinx-doc.org/rest.html>`_ on rST "
+"markup and syntax."
+msgstr ""
+"在RST上的标记和语法中见 reStructuredText Primer<http://sphinx-doc.org/rest.html> 。"
+
+#: ../../../CONTRIBUTING.rst:67
+msgid "Bugs"
+msgstr "错误"
+
+#: ../../../CONTRIBUTING.rst:69
+msgid ""
+"pycsw's `issue tracker <https://github.com/geopython/pycsw/issues>`_ is the "
+"place to report bugs or request enhancements. To submit a bug be sure to "
+"specify the pycsw version you are using, the appropriate component, a "
+"description of how to reproduce the bug, as well as what version of Python "
+"and platform. For convenience, you can run ``pycsw-admin.py -c "
+"get_sysprof`` and copy/paste the output into your issue."
+msgstr ""
+"<https://github.com/geopython/pycsw/issues> `_是pycsw问题跟踪器,是报告错误"
+"或要求改进的地方。当您提交出现的错误时,一定要指定您正在使用的pycsw版本,相"
+"应的组件,如何操作显示的错误信息,以及Python和平台的版本。为方便起见,你可以"
+"运行``pycsw-admin.py -c get_sysprof``,并将输出信息复制、粘贴到您的问题中。"
+
+#: ../../../CONTRIBUTING.rst:72
+msgid "Forking pycsw"
+msgstr "分叉pycsw"
+
+#: ../../../CONTRIBUTING.rst:74
+msgid ""
+"Contributions are most easily managed via GitHub pull requests.  `Fork "
+"<https://github.com/geopython/pycsw/fork>`_ pycsw into your own GitHub "
+"repository to be able to commit your work and submit pull requests."
+msgstr ""
+"通过 GitHub pull 请求后,贡献是最容易管理的。 '叉<https: github.com/"
+"geopython/pycsw/fork>' _ pycsw 放到你自己 GitHub 存储库中,这样可以轻松地提"
+"交你的工作,并提交pull请求。"
+
+#: ../../../CONTRIBUTING.rst:78
+msgid "Development"
+msgstr "开发"
+
+#: ../../../CONTRIBUTING.rst:81
+msgid "GitHub Commit Guidelines"
+msgstr "GitHub 提交指南"
+
+#: ../../../CONTRIBUTING.rst:83
+msgid "enhancements and bug fixes should be identified with a GitHub issue"
+msgstr "增强和 bug 修复应该等同于 GitHub 问题"
+
+#: ../../../CONTRIBUTING.rst:84
+msgid ""
+"commits should be granular enough for other developers to understand the "
+"nature / implications of the change(s)"
+msgstr "提交时粒数应该足够量,为方便其他开发人员了解自然/变化的影响(S)"
+
+#: ../../../CONTRIBUTING.rst:85
+msgid ""
+"for trivial commits that do not need `Travis CI <https://travis-ci.org/"
+"geopython/pycsw>`_ to run, include ``[ci skip]`` as part of the commit "
+"message"
+msgstr ""
+"如果是一些琐碎的提交,就像是 ``[ci skip]`` 也是做为提交消息的一部分,则不需"
+"要运行`Travis CI <https://travis-ci.org/geopython/pycsw>`_,"
+
+#: ../../../CONTRIBUTING.rst:86
+msgid ""
+"non-trivial Git commits shall be associated with a GitHub issue.  As "
+"documentation can always be improved, tickets need not be opened for "
+"improving the docs"
+msgstr ""
+"若是重大事件的 Git 提交应与 GitHub 问题部门取得联系。 以文档格式是可以修改"
+"的,但修改文档的tickets则是不必公开的"
+
+#: ../../../CONTRIBUTING.rst:87
+msgid "Git commits shall include a description of changes"
+msgstr "Git 提交应包括更改说明"
+
+#: ../../../CONTRIBUTING.rst:88
+msgid ""
+"Git commits shall include the GitHub issue number (i.e. ``#1234``) in the "
+"Git commit log message"
+msgstr "Git 提交应在Git 提交日志中写入 GitHub 问题编号 (例如 ' #1234 ')"
+
+#: ../../../CONTRIBUTING.rst:89
+msgid ""
+"all enhancements or bug fixes must successfully pass all :ref:`ogc-cite` "
+"tests before they are committed"
+msgstr "在提交之前,所有应改进的或错误修改的必须通过所有 :ref:`ogc-cite` 测试"
+
+#: ../../../CONTRIBUTING.rst:90
+msgid ""
+"all enhancements or bug fixes must successfully pass all :ref:`tests` tests "
+"before they are committed"
+msgstr "在提交之前,所有应改进的或错误修改的必须通过所有 :ref:`tests` 测试"
+
+#: ../../../CONTRIBUTING.rst:91
+msgid ""
+"enhancements which can be demonstrated from the pycsw :ref:`tests` should "
+"be accompanied by example CSW request XML"
+msgstr "pycsw加强的部分请参考 :ref:`tests` ,应附有像CSW的 请求 XML"
+
+#: ../../../CONTRIBUTING.rst:94
+msgid "Coding Guidelines"
+msgstr "编码准则"
+
+#: ../../../CONTRIBUTING.rst:96
+msgid "pycsw instead of PyCSW, pyCSW, Pycsw"
+msgstr "写法应是pycsw,而不是 PyCSW,pyCSW,Pycsw"
+
+#: ../../../CONTRIBUTING.rst:97
+msgid "always code with `PEP 8`_ conventions"
+msgstr "应是 `PEP 8`_ 公约代码"
+
+#: ../../../CONTRIBUTING.rst:98
+msgid ""
+"always run source code through ``pep8`` and `pylint`_, using all pylint "
+"defaults except for ``C0111``.  ``sbin/pycsw-pylint.sh`` is included for "
+"convenience"
+msgstr ""
+"应使用所有 pylint 默认设置的 ``pep8`` 与 `pylint`_,运行除了 ``C0111`` 的源代"
+"码。 ``sbin/pycsw-pylint.sh`` 是为了方便起见"
+
+#: ../../../CONTRIBUTING.rst:99
+msgid ""
+"for exceptions which make their way to OGC ``ExceptionReport`` XML, always "
+"specify the appropriate ``locator`` and ``code`` parameters"
+msgstr ""
+"除了OGC  'ExceptionReport' XML运行方式为个别例外,通常会指定合适的 '定位器 "
+"'和' 代码 ' 参数"
+
+#: ../../../CONTRIBUTING.rst:100
+msgid ""
+"the pycsw wiki documents `developer tasks`_ for things like releasing "
+"documentation, testing, etc."
+msgstr "pycsw wiki 文档的 `developer tasks`_ 类似于发布文档,测试等。"
+
+#: ../../../CONTRIBUTING.rst:103
+msgid "Submitting a Pull Request"
+msgstr "提交pull请求"
+
+#: ../../../CONTRIBUTING.rst:105
+msgid ""
+"This section will guide you through steps of working on pycsw.  This "
+"section assumes you have forked pycsw into your own GitHub repository."
+msgstr ""
+"这一节将指导您操作pycsw的步骤。 本节假定在您自己GitHub资料库中,有分叉的 "
+"pycsw。"
+
+#: ../../../CONTRIBUTING.rst:129
+msgid ""
+"Your changes are now visible on your pycsw repository on GitHub.  You are "
+"now ready to create a pull request. A member of the pycsw team will review "
+"the pull request and provide feedback / suggestions if required.  If "
+"changes are required, make them against the same branch and push as per "
+"above (all changes to the branch in the pull request apply)."
+msgstr ""
+"您的更改在 GitHub自己的 pycsw 存储库为可见状态。 现在你要创建pull请求。Pycsw"
+"的团队成员将审查你的pull请求,若您有需要,团队成员会提供给您反馈建议。 如果"
+"需要改动,要另立分支,并push以上步骤 (pull请求中所有更改的分支)。"
+
+#: ../../../CONTRIBUTING.rst:133
+msgid ""
+"The pull request will then be merged by the pycsw team.  You can then "
+"delete your local branch (on GitHub), and then update your own repository "
+"to ensure your pycsw repository is up to date with pycsw master:"
+msgstr ""
+"然后pycsw 团队将合并pull请求。 你可以删除掉你本地的分支(在 GitHub),更新您"
+"自己的库,以确保您的 pycsw 存储库与pycsw总站是同步的 ︰"
diff --git a/docs/locale/zh/LC_MESSAGES/csw-support.po b/docs/locale/zh/LC_MESSAGES/csw-support.po
new file mode 100644
index 0000000..c73c521
--- /dev/null
+++ b/docs/locale/zh/LC_MESSAGES/csw-support.po
@@ -0,0 +1,65 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) 2010-2015, Tom Kralidis This work is licensed under a
+# Creative Commons Attribution 4.0 International License
+# This file is distributed under the same license as the pycsw package.
+# FIRST AUTHOR <EMAIL at ADDRESS>, 2016.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: pycsw 2.1-dev\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2016-07-21 21:02+0800\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL at ADDRESS>\n"
+"Language-Team: LANGUAGE <LL at li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 2.3.4\n"
+
+#: ../../csw-support.rst:4
+msgid "CSW Support"
+msgstr ""
+
+#: ../../csw-support.rst:7
+msgid "Versions"
+msgstr ""
+
+#: ../../csw-support.rst:9
+msgid ""
+"pycsw supports both CSW 2.0.2 and 3.0.0 versions by default.  In "
+"alignment with the CSW specifications, the default version returned is "
+"the latest supported version.  That is, pycsw will always behave like a "
+"3.0.0 CSW unless the client explicitly requests a 2.0.2 CSW."
+msgstr ""
+
+#: ../../csw-support.rst:14
+msgid ""
+"The sample URLs below provide examples of how requests behaves against "
+"various/missing/default version parameters."
+msgstr ""
+
+#: ../../csw-support.rst:25
+msgid "Request Examples"
+msgstr ""
+
+#: ../../csw-support.rst:27
+msgid ""
+"The best place to look for sample requests is within the `tests/` "
+"directory, which provides numerous examples of all supported APIs and "
+"requests."
+msgstr ""
+
+#: ../../csw-support.rst:30
+msgid "Additional examples:"
+msgstr ""
+
+#: ../../csw-support.rst:32
+msgid "`Data.gov CSW HowTo v2.0`_"
+msgstr ""
+
+#: ../../csw-support.rst:33
+msgid "`pycsw Quickstart on OSGeoLive`_"
+msgstr ""
+
diff --git a/docs/locale/zh/LC_MESSAGES/distributedsearching.po b/docs/locale/zh/LC_MESSAGES/distributedsearching.po
new file mode 100644
index 0000000..ff74a48
--- /dev/null
+++ b/docs/locale/zh/LC_MESSAGES/distributedsearching.po
@@ -0,0 +1,156 @@
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: pycsw 2.0-dev\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2015-11-23 21:42+0800\n"
+"PO-Revision-Date: 2016-06-06 15:05+0800\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+"Last-Translator: \n"
+"Language-Team: \n"
+"Language: zh_CN\n"
+"X-Generator: Poedit 1.8.7\n"
+
+#: ../../distributedsearching.rst:4
+msgid "Distributed Searching"
+msgstr "分布式搜索"
+
+#: ../../distributedsearching.rst:8
+msgid ""
+"Your server must be able to make outgoing HTTP requests for this "
+"functionality."
+msgstr "此功能的作用就是可以使你的服务器传出HTTP请求。"
+
+#: ../../distributedsearching.rst:10
+msgid ""
+"pycsw has the ability to perform distributed searching against other CSW "
+"servers.  Distributed searching is disabled by default; to enable, ``server."
+"federatedcatalogues`` must be set.  A CSW client must issue a GetRecords "
+"request with ``csw:DistributedSearch`` specified, along with an optional "
+"``hopCount`` attribute (see subclause 10.8.4.13 of the CSW specification).  "
+"When enabled, pycsw will search all specified catalogues and return a "
+"unified set of search results to the client.  Due to the distributed nature "
+"of this functionality, requests will take extra time to process compared to "
+"queries against the local repository."
+msgstr ""
+"pycsw与其它CSW服务器不同的是,它有能力自己实现分布式搜索。此分布式搜索默认为"
+"禁用;若想启用,必须设置 ``server.federatedcatalogues`` 。CSW客户端会发出一个"
+"Getrecords指定性请求 ``csw:DistributedSearch`` ,以及一个可选的 ``hopCount`` "
+"属性(见CSW规范中第10.8.4.13 )。当启用时,pycsw会搜索所有指定的目录并会将一"
+"组统一的搜索结果返回给客户端。由于此功能的分布式性质,若要查询本地存储库,请"
+"求可能会需要更多的时间来处理。"
+
+#: ../../distributedsearching.rst:13
+msgid "Scenario: Federated Search"
+msgstr "场景:联合搜索"
+
+#: ../../distributedsearching.rst:15
+msgid ""
+"pycsw deployment with 3 configurations (CSW-1, CSW-2, CSW-3), subsequently "
+"providing three (3) endpoints.  Each endpoint is based on an opaque "
+"metadata repository (based on theme/place/discipline, etc.).  Goal is to "
+"perform a single search against all endpoints."
+msgstr ""
+"pycsw部署共有3项配置(CSW-1,CSW-2,CSW-3),同时也会提供3个端点。每个端点是"
+"基于一个不透明的元数据信息库(基于主题/地点/学科等)。目标是执行对所有端点一"
+"对一的搜索。"
+
+#: ../../distributedsearching.rst:17
+msgid ""
+"pycsw realizes this functionality by supporting :ref:`alternate "
+"configurations <alternate-configurations>`, and exposes the additional CSW "
+"endpoint(s) with the following design pattern:"
+msgstr ""
+"pycsw的本功能是靠 :ref:`交替配置<alternate-configurations>` 支持的,并是按"
+"以下设计模式来公开其他CSW端点的︰"
+
+#: ../../distributedsearching.rst:19
+msgid "CSW-1: ``http://localhost/pycsw/csw.py?config=CSW-1.cfg``"
+msgstr "CSW-1: ``http://localhost/pycsw/csw.py?config=CSW-1.cfg``"
+
+#: ../../distributedsearching.rst:21
+msgid "CSW-2: ``http://localhost/pycsw/csw.py?config=CSW-2.cfg``"
+msgstr "CSW-2: ``http://localhost/pycsw/csw.py?config=CSW-2.cfg``"
+
+#: ../../distributedsearching.rst:23
+msgid "CSW-3: ``http://localhost/pycsw/csw.py?config=CSW-3.cfg``"
+msgstr "CSW-3: ``http://localhost/pycsw/csw.py?config=CSW-3.cfg``"
+
+#: ../../distributedsearching.rst:25
+msgid ""
+"...where the ``*.cfg`` configuration files are configured for each "
+"respective metadata repository.  The above CSW endpoints can be interacted "
+"with as usual."
+msgstr ""
+"只要有 ``*.cfg``  这个配置文件,它就可以为每个元数据存储库进行配置。 以上的CSW"
+"端点也可以像往常一样进行交互。"
+
+#: ../../distributedsearching.rst:27
+msgid ""
+"To federate the discovery of the three (3) portals into a unified search, "
+"pycsw realizes this functionality by deploying an additional configuration "
+"which acts as the superset of CSW-1, CSW-2, CSW-3:"
+msgstr ""
+"将这3个门户联合成统一的搜索,pycsw就可以通过部署超集的CSW-1、 CSW-2、 CSW-3 "
+"这些附加配置来实现此功能:"
+
+#: ../../distributedsearching.rst:29
+msgid "CSW-all: ``http://localhost/pycsw/csw.py?config=CSW-all.cfg``"
+msgstr "所有的CSW: ``http://localhost/pycsw/csw.py?config=CSW-all.cfg``"
+
+#: ../../distributedsearching.rst:31
+msgid ""
+"This allows the client to invoke one (1) CSW GetRecords request, in which "
+"the CSW endpoint spawns the same GetRecords request to 1..n distributed CSW "
+"endpoints.  Distributed CSW endpoints are advertised in CSW Capabilities "
+"XML via ``ows:Constraint``:"
+msgstr ""
+"这允许客户端调用 1 CSW GetRecords 请求,其中CSW端点就会生成相同的GetRecords"
+"请求,从1到n分布各个CSW 终结点。分布式CSW端点通过 'ows:Constraint' 在CSW功"
+"能 XML上发布广告︰"
+
+#: ../../distributedsearching.rst:45
+msgid ""
+"...which advertises which CSW endpoint(s) the CSW server will spawn if a "
+"distributed search is requested by the client."
+msgstr "如果在客户端请求分布式搜索的话,CSW服务器将spawn。"
+
+#: ../../distributedsearching.rst:47
+msgid "in the CSW-all configuration:"
+msgstr "CSW-all 配置"
+
+#: ../../distributedsearching.rst:55
+msgid ""
+"At which point a CSW client request to CSW-all with "
+"``distributedsearch=TRUE``, while specifying an optional ``hopCount``.  "
+"Query network topology:"
+msgstr ""
+"当指定选项``hopCount``时,CSW客户端就会用 ' distributedsearch = TRUE '请求所"
+"有的CSW。 查询网络拓扑 ︰"
+
+#: ../../distributedsearching.rst:73
+msgid ""
+"As a result, a pycsw deployment in this scenario may be approached on a per "
+"'theme' basis, or at an aggregate level."
+msgstr ""
+"因此,在这个场景中,pycsw 部署就会深入每个 '主题' 的基础部分或总体水平。"
+
+#: ../../distributedsearching.rst:75
+msgid ""
+"All interaction in this scenario is local to the pycsw installation, so "
+"network performance would not be problematic."
+msgstr ""
+"在这个场景中的所有交互都是在本地pycsw 安装的,所以网络性能的好与坏是不会产生"
+"影响的。"
+
+#: ../../distributedsearching.rst:77
+msgid ""
+"A very important facet of distributed search is as per Annex B of OGC:CSW "
+"2.0.2.  Given that all the CSW endpoints are managed locally, duplicates "
+"and infinite looping are not deemed to present an issue."
+msgstr ""
+"分布式搜索的一个非常重要的方面是OGC的附件B问题:CSW 2.0.2。鉴于所有的CSW端点"
+"都是本地管理,因此复制和无限循环不会存在问题。"
diff --git a/docs/locale/zh/LC_MESSAGES/geonode.po b/docs/locale/zh/LC_MESSAGES/geonode.po
new file mode 100644
index 0000000..9731bde
--- /dev/null
+++ b/docs/locale/zh/LC_MESSAGES/geonode.po
@@ -0,0 +1,61 @@
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: pycsw 2.0-dev\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2016-12-17 17:33+0800\n"
+"PO-Revision-Date: 2016-06-07 15:54+0800\n"
+"Last-Translator: \n"
+"Language-Team: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 2.3.4\n"
+
+#: ../../geonode.rst:4
+msgid "GeoNode Configuration"
+msgstr "GeoNode配置"
+
+#: ../../geonode.rst:6
+msgid ""
+"GeoNode (http://geonode.org/) is a platform for the management and "
+"publication of geospatial data. It brings together mature and stable "
+"open-source software projects under a consistent and easy-to-use "
+"interface allowing users, with little training, to quickly and easily "
+"share data and create interactive maps. GeoNode provides a cost-effective"
+" and scalable tool for developing information management systems.  "
+"GeoNode uses CSW as a cataloguing mechanism to query and present "
+"geospatial metadata."
+msgstr ""
+"GeoNode(http://geonode.org/)是地理空间数据管理和发布的平台。它是成熟且稳定的开源软件项目,具有一致性和易掌握性,只要稍加指导,就可以快速且轻松地分享数据,并能创建交互式地图。"
+" "
+"GeoNode是一种工具,为开发信息管理系统提供了节约成本且可伸缩等功能。GeoNode使用的是CSW,此CSW可查询编目,还可以显示当前的地理空间元数据。"
+" "
+
+#: ../../geonode.rst:8
+msgid ""
+"pycsw supports binding to an existing GeoNode repository for metadata "
+"query.  The binding is read-only (transactions are not in scope, as "
+"GeoNode manages repository metadata changes in the application proper)."
+msgstr "pycsw绑定到现有GeoNode库,此库用于元数据查询。此绑定是只读文件(交易不在范围内,GeoNode在适当的应用程序中管理库元数据)。"
+
+#: ../../geonode.rst:11
+msgid "GeoNode Setup"
+msgstr "GeoNode设置"
+
+#: ../../geonode.rst:13
+msgid ""
+"pycsw is enabled and configured by default in GeoNode, so there are no "
+"additional steps required once GeoNode is setup.  See the ``CATALOGUE`` "
+"and ``PYCSW`` `settings.py entries`_ at "
+"http://docs.geonode.org/en/latest/developers/reference/django-"
+"apps.html#id1 for customizing pycsw within GeoNode."
+msgstr ""
+"在GeoNode中,pycsw 的启用和配置都是默认的,所以GeoNode的安装程序不需要额外步骤的。若想定制GeoNode-"
+"pycsw,请参见http://docs.geonode.org/en/latest/developers/reference/django-"
+"apps.html#id1中``CATALOGUE``和```PYCSW``  `settings.py entries`_ 。"
+
+#: ../../geonode.rst:15
+msgid "The GeoNode plugin is managed outside of pycsw within the GeoNode project."
+msgstr "GeoNode插件不是由 GeoNode 项目中的 pycsw 管理。"
+
diff --git a/docs/locale/zh/LC_MESSAGES/hhypermap.po b/docs/locale/zh/LC_MESSAGES/hhypermap.po
new file mode 100644
index 0000000..1924dc9
--- /dev/null
+++ b/docs/locale/zh/LC_MESSAGES/hhypermap.po
@@ -0,0 +1,72 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) 2010-2015, Tom Kralidis This work is licensed under a
+# Creative Commons Attribution 4.0 International License
+# This file is distributed under the same license as the pycsw package.
+# FIRST AUTHOR <EMAIL at ADDRESS>, 2016.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: pycsw 2.0-dev\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2016-12-17 17:33+0800\n"
+"PO-Revision-Date: 2016-06-06 16:04+0800\n"
+"Last-Translator: \n"
+"Language-Team: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 2.3.4\n"
+
+#: ../../hhypermap.rst:4
+msgid "HHypermap Configuration"
+msgstr "HHypermap配置"
+
+#: ../../hhypermap.rst:6
+#, fuzzy
+msgid ""
+"HHypermap (Harvard Hypermap) Registry (https://github.com/cga-"
+"harvard/HHypermap) is an application that manages OWS, Esri REST, and "
+"other types of map service harvesting, and maintains uptime statistics "
+"for services and layers. HHypermap Registry will publish to HHypermap "
+"Search (based on Lucene) which provides a fast search and visualization "
+"environment for spatio-temporal materials."
+msgstr ""
+"HHypermap (Harvard Hypermap) Supervisor(https://github.com/cga-"
+"harvard/HHypermap)是管理OWS、ESRI "
+"REST、其他类型的地图服务、维护服务和图层正常运行统计的一款应用程序。HHypermap "
+"Supervisor会发布到HHypermap搜索中(基于Lucene),它可实现空间数据的快速搜索和可视化环境。"
+
+#: ../../hhypermap.rst:8
+msgid ""
+"HHypermap uses CSW as a cataloguing mechanism to ingest, query and "
+"present geospatial metadata."
+msgstr "HHypermap使用CSW作为摄取、查询、地理空间元数据显示的编目。"
+
+#: ../../hhypermap.rst:10
+msgid ""
+"pycsw supports binding to an existing HHypermap repository for metadata "
+"query."
+msgstr "为元数据查询,将pycsw绑定到已有的HHypermap存储库。"
+
+#: ../../hhypermap.rst:13
+msgid "HHypermap Setup"
+msgstr "HHypermap设置"
+
+#: ../../hhypermap.rst:15
+msgid ""
+"pycsw is enabled and configured by default in HHypermap, so there are no "
+"additional steps required once HHypermap is setup.  See the "
+"``REGISTRY_PYCSW`` `hypermap/settings.py entries`_ for customizing pycsw "
+"within HHypermap."
+msgstr ""
+"在HHypermap中,pycsw的启用与配置是默认设置的,所以HHypermap的安装程序是不需要额外步骤的。"
+"想定制HHypermap-pycsw,请参见 "
+"``REGISTRY_PYCSW`` `hypermap/settings.py entries`_ "。
+
+#: ../../hhypermap.rst:17
+msgid ""
+"The HHypermap plugin is managed outside of pycsw within the HHypermap "
+"project.  HHypermap settings must ensure that "
+"``REGISTRY_PYCSW['repository']['source']`` is set "
+"to``hypermap.search.pycsw_repository``."
+msgstr ""
diff --git a/docs/locale/zh/LC_MESSAGES/index.po b/docs/locale/zh/LC_MESSAGES/index.po
new file mode 100644
index 0000000..218f14f
--- /dev/null
+++ b/docs/locale/zh/LC_MESSAGES/index.po
@@ -0,0 +1,35 @@
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: pycsw 2.0-dev\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2015-11-23 21:42+0800\n"
+"PO-Revision-Date: 2016-06-06 16:09+0800\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+"Last-Translator: \n"
+"Language-Team: \n"
+"Language: zh_CN\n"
+"X-Generator: Poedit 1.8.7\n"
+
+#: ../../index.rst:5
+msgid "pycsw |release| Documentation"
+msgstr "pycsw 发布 文档"
+
+#: ../../index.rst:7
+msgid "Tom Kralidis"
+msgstr "Tom Kralidis"
+
+#: ../../index.rst:8
+msgid "tomkralidis at gmail.com"
+msgstr "tomkralidis at gmail.com"
+
+#: ../../index.rst:9
+msgid "|release|"
+msgstr "发布"
+
+#: ../../index.rst:10
+msgid "|today|"
+msgstr "今天"
diff --git a/docs/locale/zh/LC_MESSAGES/installation.po b/docs/locale/zh/LC_MESSAGES/installation.po
new file mode 100644
index 0000000..8a4c4f9
--- /dev/null
+++ b/docs/locale/zh/LC_MESSAGES/installation.po
@@ -0,0 +1,270 @@
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: pycsw 2.0-dev\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2016-07-21 21:02+0800\n"
+"PO-Revision-Date: 2016-06-07 10:58+0800\n"
+"Last-Translator: \n"
+"Language-Team: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 2.3.4\n"
+
+#: ../../installation.rst:4
+msgid "Installation"
+msgstr "安装"
+
+#: ../../installation.rst:7
+msgid "System Requirements"
+msgstr "系统要求"
+
+#: ../../installation.rst:9
+msgid ""
+"pycsw is written in `Python <http://python.org>`_, and works with "
+"(tested) version 2.7, 3.4 and 3.5"
+msgstr "pycsw 编写语言是 `Python <http://python.org>`_ ,版本(测试通过)为 2.7, 3.4 及3.5"
+
+#: ../../installation.rst:11
+msgid "pycsw requires the following Python supporting libraries:"
+msgstr "pycsw 是由以下Python库支撑的︰"
+
+#: ../../installation.rst:13
+msgid "`lxml`_ for XML support"
+msgstr "`lxml`_  用于XML 支撑"
+
+#: ../../installation.rst:14
+msgid "`SQLAlchemy`_ for database bindings"
+msgstr "`SQLAlchemy`_ 用于数据库绑定"
+
+#: ../../installation.rst:15
+msgid "`pyproj`_ for coordinate transformations"
+msgstr "`pyproj`_ 用于变换坐标"
+
+#: ../../installation.rst:16
+msgid "`Shapely`_ for spatial query / geometry support"
+msgstr "`Shapely`_ 用于空间查询/ 几何支持"
+
+#: ../../installation.rst:17
+msgid "`OWSLib`_ for CSW client and metadata parser"
+msgstr "`OWSLib`_ 用于CSW客户端和元数据分析"
+
+#: ../../installation.rst:18
+msgid "`six`_ for Python 2/3 compatibility"
+msgstr "`six`_  用于处理 Python 2/3 兼容性"
+
+#: ../../installation.rst:19
+msgid "`xmltodict`_ for working with XML similar to working with JSON"
+msgstr "`xmltodict`_ ,来像使用 JSON 一样使用 XML"
+
+#: ../../installation.rst:20
+msgid "`geolinks`_ for dealing with geospatial links"
+msgstr "`geolinks`_ 处理 地理空间链接"
+
+#: ../../installation.rst:24
+msgid "You can install these dependencies via `easy_install`_ or `pip`_"
+msgstr "通过 `easy_install`_ or `pip`_ 可以安装一些与之相关的程序"
+
+#: ../../installation.rst:28
+msgid ""
+"For :ref:`GeoNode <geonode>` or :ref:`Open Data Catalog <odc>` or "
+":ref:`HHypermap <hhypermap>` deployments, SQLAlchemy is not required"
+msgstr "对于 :ref:`GeoNode <geonode>` 或 :ref:`Open Data Catalog <odc>` ,或 :ref:`HHypermap <hhypermap>` 部署,SQLAlchemy 不是必需的"
+
+#: ../../installation.rst:31
+msgid "Installing from Source"
+msgstr "从源代码安装"
+
+#: ../../installation.rst:33
+msgid ""
+"`Download <http://pycsw.org/download>`_ the latest stable version or "
+"fetch from Git."
+msgstr " `下载<http: pycsw.org/download>`_ 最新稳定版本,或从 Git 获取。"
+
+#: ../../installation.rst:36
+msgid "For Developers and the Truly Impatient"
+msgstr "为开发人员和真正Impatient"
+
+#: ../../installation.rst:38
+msgid "The 4 minute install:"
+msgstr "安装需要4分钟"
+
+#: ../../installation.rst:56
+msgid "The Quick and Dirty Way"
+msgstr "快速但并非完善的方式"
+
+#: ../../installation.rst:62
+msgid ""
+"Ensure that CGI is enabled for the install directory.  For example, on "
+"Apache, if pycsw is installed in ``/srv/www/htdocs/pycsw`` (where the URL"
+" will be ``http://host/pycsw/csw.py``), add the following to "
+"``httpd.conf``:"
+msgstr ""
+"确保在安装目录中 CGI已启用。 例如,对 Apache,如果 pycsw 安装在 ``/srv/www/htdocs/pycsw`` "
+"(这时,URL 就会在 ``http://host/pycsw/csw.py`` ),将以下信息添加至 ``httpd.conf`` :"
+
+#: ../../installation.rst:73
+msgid ""
+"If pycsw is installed in ``cgi-bin``, this should work as expected.  In "
+"this case, the :ref:`tests <tests>` application must be moved to a "
+"different location to serve static HTML documents."
+msgstr ""
+"如果 pycsw安装在 ``cgi-bin`` 下,工作就能预期进行。在这种情况下,  :ref:`tests<tests>` "
+"应用程序就必须转移到其它位置,成为静态的 HTML 文件。"
+
+#: ../../installation.rst:75
+msgid ""
+"Make sure, you have all the dependencies from ``requirements.txt and "
+"requirements-standalone.txt``"
+msgstr ""
+"请确保你已经从 ``requirements.txt and requirements-standalone.txt`` "
+"获得所有dependencies"
+
+#: ../../installation.rst:78
+msgid "The Clean and Proper Way"
+msgstr "适当的方式"
+
+#: ../../installation.rst:86
+msgid ""
+"At this point, pycsw is installed as a library and requires a CGI "
+"``csw.py`` or WSGI ``pycsw/wsgi.py`` script to be served into your web "
+"server environment (see below for WSGI configuration/deployment)."
+msgstr ""
+"在这一点上,pycsw 安装库将 CGI 'csw.py '或 WSGI' pycsw/wsgi.py ' 脚本发送到您的 web 服务器环境 "
+"(参见下文 WSGI 配置/部署)。"
+
+#: ../../installation.rst:93
+msgid "Installing from the Python Package Index (PyPi)"
+msgstr "从 Python Package 指数 (PyPi) 安装"
+
+#: ../../installation.rst:105
+msgid "Installing from OpenSUSE Build Service"
+msgstr "从 OpenSUSE 生成服务安装"
+
+#: ../../installation.rst:107
+msgid ""
+"In order to install the pycsw package in openSUSE Leap (stable "
+"distribution), one can run the following commands as user ``root``:"
+msgstr "若要在 openSUSE  Leap (稳定版本) 安装 pycsw 包,就可以以用户 ``root`` 身份运行以下命令 ︰"
+
+#: ../../installation.rst:116
+msgid ""
+"In order to install the pycsw package in openSUSE Tumbleweed (rolling "
+"distribution), one can run the following commands as user ``root``:"
+msgstr "若要在 openSUSE  Tumbleweed (滚动版本) 安装 pycsw 包,就可以以用户 ``root`` 身份运行以下命令 ︰"
+
+
+#: ../../installation.rst:124
+msgid ""
+"An alternative method is to use the `One-Click Installer "
+"<https://software.opensuse.org/package/python-pycsw>`_."
+msgstr ""
+"另一种方法是使用一键式安装程序"
+"<https://software.opensuse.org/package/python-pycsw>`_."
+
+#: ../../installation.rst:129
+msgid "Installing on Ubuntu/Mint"
+msgstr "在 Ubuntu/Mint系统上安装"
+
+#: ../../installation.rst:131
+msgid ""
+"In order to install the most recent pycsw release to an Ubuntu-based "
+"distribution, one can use the UbuntuGIS Unstable repository by running "
+"the following commands:"
+msgstr "为了在基于 Ubuntu 的发行版安装最新的 pycsw,可以运行以下命令来使用 UbuntuGIS 非稳定版本 ︰"
+
+#: ../../installation.rst:139
+msgid ""
+"Alternatively, one can use the UbuntuGIS Stable repository which includes"
+" older but very well tested versions:"
+msgstr ""
+
+#: ../../installation.rst:141
+msgid ""
+"# sudo add-apt-repository ppa:ubuntugis/ppa # sudo apt-get update # sudo "
+"apt-get install python-pycsw pycsw-cgi"
+msgstr ""
+
+#: ../../installation.rst:146
+msgid ""
+"Since Ubuntu 16.04 LTS Xenial release, pycsw is included by default in "
+"the official Multiverse repository."
+msgstr ""
+
+#: ../../installation.rst:149
+msgid "Running on Windows"
+msgstr "在 Windows 上运行"
+
+#: ../../installation.rst:151
+msgid "For Windows installs, change the first line of ``csw.py`` to:"
+msgstr "对于Windows 安装,更改 'csw.py ' 的第一行 ︰"
+
+#: ../../installation.rst:158
+msgid ""
+"The use of ``-u`` is required to properly output gzip-compressed "
+"responses."
+msgstr "使用 ``-u`` 需要正确输出 gzip 压缩响应。"
+
+#: ../../installation.rst:161
+msgid "Security"
+msgstr "安全性"
+
+#: ../../installation.rst:163
+msgid ""
+"By default, ``default.cfg`` is at the root of the pycsw install.  If "
+"pycsw is setup outside an HTTP server's ``cgi-bin`` area, this file could"
+" be read.  The following options protect the configuration:"
+msgstr ""
+"默认情况下,' default.cfg ' 是 pycsw 安装的根目录。 如果 pycsw 设置在 HTTP 服务器 'cgi-bin' "
+"区域以外,此文件就可以被读取。 以下是几项保护配置的选项 ︰"
+
+#: ../../installation.rst:165
+msgid ""
+"move ``default.cfg`` to a non HTTP accessible area, and modify ``csw.py``"
+" to point to the updated location"
+msgstr "将 'default.cfg' 移动到非 HTTP 可访问的区域,并修改 'csw.py' 以指向更新的位置"
+
+#: ../../installation.rst:166
+msgid ""
+"configure web server to deny access to the configuration.  For example, "
+"in Apache, add the following to ``httpd.conf``:"
+msgstr "配置 web 服务器,拒绝对配置的访问。 例如,在 Apache 中,在 'httpd.conf '下添加以下内容:"
+
+#: ../../installation.rst:177
+msgid "Running on WSGI"
+msgstr "在 WSGI 上运行"
+
+#: ../../installation.rst:179
+msgid ""
+"pycsw supports the `Web Server Gateway Interface`_ (WSGI).  To run pycsw "
+"in WSGI mode, use ``pycsw/wsgi.py`` in your WSGI server environment."
+msgstr ""
+"pycsw 支持 `Web 服务器网关接口`_ (WSGI)。 在 WSGI 模式下运行 pycsw,在 WSGI 服务器环境中使用 "
+"``pycsw/wsgi.py`` 。"
+
+#: ../../installation.rst:184
+msgid ""
+"``mod_wsgi`` supports only the version of python it was compiled with. If"
+" the target server already supports WSGI applications, pycsw will need to"
+" use the same python version. `WSGIDaemonProcess`_ provides a ``python-"
+"path`` directive that may allow a virtualenv created from the python "
+"version ``mod_wsgi`` uses."
+msgstr ""
+"``mod_wsgi`` 只支持已编译的python版本。如果目标服务器支持 WSGI 应用,pycsw也是相同的 python "
+"版本。`WSGIDaemonProcess`_ 提供一个  ``python-path``  指令,其允许从 python 版本 "
+"``mod_wsgi`` 进行virtualenv 的创建。"
+
+#: ../../installation.rst:188
+msgid "Below is an example of configuring with Apache:"
+msgstr "下面是Apache 配置的示例 ︰"
+
+#: ../../installation.rst:201
+msgid "or use the `WSGI reference implementation`_:"
+msgstr "或者使用 `WSGI 参考实例`_ :"
+
+#: ../../installation.rst:208
+msgid "which will publish pycsw to ``http://localhost:8000/``"
+msgstr " 将pycsw发布到 ``http://localhost:8000/`` "
+
+
diff --git a/docs/locale/zh/LC_MESSAGES/introduction.po b/docs/locale/zh/LC_MESSAGES/introduction.po
new file mode 100644
index 0000000..61b8d8c
--- /dev/null
+++ b/docs/locale/zh/LC_MESSAGES/introduction.po
@@ -0,0 +1,558 @@
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: pycsw 2.0-dev\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2016-07-21 21:52+0800\n"
+"PO-Revision-Date: 2016-06-08 11:02+0800\n"
+"Last-Translator: \n"
+"Language-Team: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 2.3.4\n"
+
+#: ../../introduction.rst:4
+msgid "Introduction"
+msgstr "引言"
+
+#: ../../introduction.rst:6
+msgid "pycsw is an OGC CSW server implementation written in Python."
+msgstr "pycsw是使用 Python 语言实现的 OGC CSW 服务。"
+
+#: ../../introduction.rst:9
+msgid "Features"
+msgstr "特性"
+
+#: ../../introduction.rst:11
+msgid ""
+"certified OGC `Compliant`_ and OGC Reference Implementation for both CSW "
+"2.0.2 and CSW 3.0.0"
+msgstr "认证 OGC `Compliant`_ 与 OGC 参考实现"
+
+#: ../../introduction.rst:12
+msgid "harvesting support for WMS, WFS, WCS, WPS, WAF, CSW, SOS"
+msgstr "WMS、WFS、WCS、WPS、WAF、CSW、SOS得到支持"
+
+#: ../../introduction.rst:13
+msgid "implements `INSPIRE Discovery Services 3.0`_"
+msgstr "实现了 `INSPIRE Discovery Services 3.0`_"
+
+#: ../../introduction.rst:14
+msgid "implements `ISO Metadata Application Profile 1.0.0`_"
+msgstr "实现了 `ISO Metadata Application Profile 1.0.0`_"
+
+#: ../../introduction.rst:15
+msgid "implements `FGDC CSDGM Application Profile for CSW 2.0`_"
+msgstr "实现了 `FGDC CSDGM Application Profile for CSW 2.0`_"
+
+#: ../../introduction.rst:16
+msgid "implements the Search/Retrieval via URL (`SRU`_) search protocol"
+msgstr "实现了通过URL (`SRU`_) 查找接口进行查找或抓取"
+
+#: ../../introduction.rst:17
+msgid "implements Full Text Search capabilities"
+msgstr "实现了全文检索的功能"
+
+#: ../../introduction.rst:18
+msgid "implements OGC OpenSearch Geo and Time Extensions"
+msgstr "实现了 OGC 开放搜索与时空扩展"
+
+#: ../../introduction.rst:19
+msgid "implements Open Archives Initiative Protocol for Metadata Harvesting"
+msgstr "支持元数据主动文档开放协议"
+
+#: ../../introduction.rst:20
+msgid "supports ISO, Dublin Core, DIF, FGDC, Atom and GM03 metadata models"
+msgstr "支持 ISO、Dublin Core、DIF、FGDC,Atom与 GM03 元数据模型"
+
+#: ../../introduction.rst:21
+msgid "CGI or WSGI deployment"
+msgstr "CGI或WSCI部署"
+
+#: ../../introduction.rst:22
+msgid "Python 2 and 3 compatible"
+msgstr ""
+
+#: ../../introduction.rst:23
+msgid "simple configuration"
+msgstr "简单配置"
+
+#: ../../introduction.rst:24
+msgid "transactional capabilities (CSW-T)"
+msgstr "事务功能(CSW-T))"
+
+#: ../../introduction.rst:25
+msgid "flexible repository configuration"
+msgstr "灵活的存储配置"
+
+#: ../../introduction.rst:26
+msgid "`GeoNode`_ connectivity"
+msgstr "连接 `GeoNode`_ "
+
+#: ../../introduction.rst:27
+msgid "`HHypermap`_ connectivity"
+msgstr "连接 `HHypermap`_  "
+
+#: ../../introduction.rst:28
+msgid "`Open Data Catalog`_ connectivity"
+msgstr "连接 `开放数据目录`_"
+
+#: ../../introduction.rst:29
+msgid "`CKAN`_ connectivity"
+msgstr "连接 `CKAN`_  "
+
+#: ../../introduction.rst:30
+msgid "federated catalogue distributed searching"
+msgstr "联合目录分布式搜索"
+
+#: ../../introduction.rst:31
+msgid "realtime XML Schema validation"
+msgstr "实时XML Schema验证"
+
+#: ../../introduction.rst:32
+msgid "extensible profile plugin architecture"
+msgstr "可扩展的配置文件插件架构"
+
+#: ../../introduction.rst:35
+msgid "Standards Support"
+msgstr "支持的标准"
+
+#: ../../introduction.rst:38
+msgid "Standard"
+msgstr "标准"
+
+#: ../../introduction.rst:38
+msgid "Version(s)"
+msgstr "版本"
+
+#: ../../introduction.rst:40
+msgid "`OGC CSW`_"
+msgstr "`OGC CSW`_"
+
+#: ../../introduction.rst:40
+msgid "2.0.2, 3.0.0"
+msgstr ""
+
+#: ../../introduction.rst:42
+msgid "`OGC Filter`_"
+msgstr "`OGC Filte`_"
+
+#: ../../introduction.rst:42
+msgid "1.1.0, 2.0.0"
+msgstr ""
+
+#: ../../introduction.rst:44
+msgid "`OGC OWS Common`_"
+msgstr ""
+
+#: ../../introduction.rst:44
+msgid "1.0.0, 2.0.0"
+msgstr ""
+
+#: ../../introduction.rst:46
+msgid "`OGC GML`_"
+msgstr "`OGC GML`_"
+
+#: ../../introduction.rst:46
+msgid "3.1.1"
+msgstr "3.1.1"
+
+#: ../../introduction.rst:48
+msgid "`OGC SFSQL`_"
+msgstr "`OGC SFSQL`_"
+
+#: ../../introduction.rst:48
+msgid "1.2.1"
+msgstr "1.2.1"
+
+#: ../../introduction.rst:50
+msgid "`Dublin Core`_"
+msgstr "`Dublin Core`_"
+
+#: ../../introduction.rst:50 ../../introduction.rst:66
+msgid "1.1"
+msgstr "1.1"
+
+#: ../../introduction.rst:52
+msgid "`SOAP`_"
+msgstr "`SOAP`_"
+
+#: ../../introduction.rst:52
+msgid "1.2"
+msgstr "1.2"
+
+#: ../../introduction.rst:54
+msgid "`ISO 19115`_"
+msgstr "`ISO 19115`_"
+
+#: ../../introduction.rst:54
+msgid "2003"
+msgstr "2003"
+
+#: ../../introduction.rst:56
+msgid "`ISO 19139`_"
+msgstr "`ISO 19139`_"
+
+#: ../../introduction.rst:56
+msgid "2007"
+msgstr "2007"
+
+#: ../../introduction.rst:58
+msgid "`ISO 19119`_"
+msgstr "`ISO 19119`_"
+
+#: ../../introduction.rst:58
+msgid "2005"
+msgstr "2005"
+
+#: ../../introduction.rst:60
+msgid "`NASA DIF`_"
+msgstr "`NASA DIF`_"
+
+#: ../../introduction.rst:60
+msgid "9.7"
+msgstr "9.7"
+
+#: ../../introduction.rst:62
+msgid "`FGDC CSDGM`_"
+msgstr "`FGDC CSDGM`_"
+
+#: ../../introduction.rst:62
+msgid "1998"
+msgstr "1998"
+
+#: ../../introduction.rst:64
+msgid "`GM03`_"
+msgstr "`GM03`_"
+
+#: ../../introduction.rst:64
+msgid "2.1"
+msgstr "2.1"
+
+#: ../../introduction.rst:66
+msgid "`SRU`_"
+msgstr "`SRU`_"
+
+#: ../../introduction.rst:68
+msgid "`OGC OpenSearch`_"
+msgstr "`OGC OpenSearch`_"
+
+#: ../../introduction.rst:68
+msgid "1.0"
+msgstr "1.0"
+
+#: ../../introduction.rst:70
+msgid "`OAI-PMH`_"
+msgstr ""
+
+#: ../../introduction.rst:70
+msgid "2.0"
+msgstr "2.0"
+
+#: ../../introduction.rst:74
+msgid "Supported Operations"
+msgstr "支持的操作"
+
+#: ../../introduction.rst:1
+msgid "Request"
+msgstr "请求"
+
+#: ../../introduction.rst:1
+msgid "Optionality"
+msgstr "可选性"
+
+#: ../../introduction.rst:1
+msgid "Supported"
+msgstr "支持"
+
+#: ../../introduction.rst:1
+msgid "HTTP method binding(s)"
+msgstr "HTTP方法绑定"
+
+#: ../../introduction.rst:1
+msgid "GetCapabilities"
+msgstr "功能"
+
+#: ../../introduction.rst:1
+msgid "mandatory"
+msgstr "必填"
+
+#: ../../introduction.rst:1
+msgid "yes"
+msgstr "是"
+
+#: ../../introduction.rst:1
+msgid "GET (KVP) / POST (XML) / SOAP"
+msgstr "GET (KVP) / POST (XML) / SOAP"
+
+#: ../../introduction.rst:1
+msgid "DescribeRecord"
+msgstr "记录详述"
+
+#: ../../introduction.rst:1
+msgid "GetRecords"
+msgstr "获取记录"
+
+#: ../../introduction.rst:1
+msgid "GetRecordById"
+msgstr "GetRecordById"
+
+#: ../../introduction.rst:1
+msgid "optional"
+msgstr "选项"
+
+#: ../../introduction.rst:1
+msgid "GetRepositoryItem"
+msgstr "项目库获取"
+
+#: ../../introduction.rst:1
+msgid "GET (KVP)"
+msgstr "KVP获取"
+
+#: ../../introduction.rst:1
+msgid "GetDomain"
+msgstr "GetDomain"
+
+#: ../../introduction.rst:1
+msgid "Harvest"
+msgstr "获取"
+
+#: ../../introduction.rst:1
+msgid "UnHarvest"
+msgstr ""
+
+#: ../../introduction.rst:1
+msgid "no"
+msgstr ""
+
+#: ../../introduction.rst:1
+msgid "Transaction"
+msgstr "订单"
+
+#: ../../introduction.rst:1
+msgid "POST (XML) / SOAP"
+msgstr "POST (XML) / SOAP"
+
+#: ../../introduction.rst:91
+msgid ""
+"Asynchronous processing supported for GetRecords and Harvest requests "
+"(via ``csw:ResponseHandler``)"
+msgstr "异步处理支持 GetRecords 和获取请求 (通过 ' csw:ResponseHandler ')"
+
+#: ../../introduction.rst:95
+msgid "Supported Harvest Resource Types are listed in :ref:`transactions`"
+msgstr "获取资源类型请参考: :ref:`transactions` 中列表"
+
+#: ../../introduction.rst:98
+msgid "Supported Output Formats"
+msgstr "支持的输出格式"
+
+#: ../../introduction.rst:100
+msgid "XML (default)"
+msgstr "XML (默认值)"
+
+#: ../../introduction.rst:101
+msgid "JSON"
+msgstr "JSON代码"
+
+#: ../../introduction.rst:104
+msgid "Supported Output Schemas"
+msgstr "支持的输出模式"
+
+#: ../../introduction.rst:106
+msgid "Dublin Core"
+msgstr "Dublin Core"
+
+#: ../../introduction.rst:107
+msgid "ISO 19139"
+msgstr "ISO 19139"
+
+#: ../../introduction.rst:108
+msgid "FGDC CSDGM"
+msgstr "FGDC CSDGM"
+
+#: ../../introduction.rst:109
+msgid "NASA DIF"
+msgstr "NASA DIF"
+
+#: ../../introduction.rst:110
+msgid "Atom"
+msgstr "Atom"
+
+#: ../../introduction.rst:111
+msgid "GM03"
+msgstr "GM03"
+
+#: ../../introduction.rst:114
+msgid "Supported Sorting Functionality"
+msgstr "支持排序功能 "
+
+#: ../../introduction.rst:116
+msgid "ogc:SortBy"
+msgstr "ogc:SortBy"
+
+#: ../../introduction.rst:117
+msgid "ascending or descending"
+msgstr "升序或降序"
+
+#: ../../introduction.rst:118
+msgid "aspatial (queryable properties)"
+msgstr "非空间 (可查询属性)"
+
+#: ../../introduction.rst:119
+msgid "spatial (geometric area)"
+msgstr "空间 (几何区域)"
+
+#: ../../introduction.rst:122
+msgid "Supported Filters"
+msgstr "筛选条件"
+
+#: ../../introduction.rst:125
+msgid "Full Text Search"
+msgstr ""
+
+#: ../../introduction.rst:127
+msgid "csw:AnyText"
+msgstr "csw:任意文章"
+
+#: ../../introduction.rst:130
+msgid "Geometry Operands"
+msgstr "几何操作"
+
+#: ../../introduction.rst:132
+msgid "gml:Point"
+msgstr "gml:点"
+
+#: ../../introduction.rst:133
+msgid "gml:LineString"
+msgstr "gml:线"
+
+#: ../../introduction.rst:134
+msgid "gml:Polygon"
+msgstr "gml:面"
+
+#: ../../introduction.rst:135
+msgid "gml:Envelope"
+msgstr "gml:外框"
+
+#: ../../introduction.rst:139
+msgid "Coordinate transformations are supported"
+msgstr "坐标变换"
+
+#: ../../introduction.rst:142
+msgid "Spatial Operators"
+msgstr "空间操作"
+
+#: ../../introduction.rst:144
+msgid "BBOX"
+msgstr "BBOX"
+
+#: ../../introduction.rst:145
+msgid "Beyond"
+msgstr "以外"
+
+#: ../../introduction.rst:146
+msgid "Contains"
+msgstr "包括"
+
+#: ../../introduction.rst:147
+msgid "Crosses"
+msgstr "交叉"
+
+#: ../../introduction.rst:148
+msgid "Disjoint"
+msgstr "不相交"
+
+#: ../../introduction.rst:149
+msgid "DWithin"
+msgstr "DWithin"
+
+#: ../../introduction.rst:150
+msgid "Equals"
+msgstr "等于"
+
+#: ../../introduction.rst:151
+msgid "Intersects"
+msgstr "相交"
+
+#: ../../introduction.rst:152
+msgid "Overlaps"
+msgstr "重叠"
+
+#: ../../introduction.rst:153
+msgid "Touches"
+msgstr "触动"
+
+#: ../../introduction.rst:154
+msgid "Within"
+msgstr "内"
+
+#: ../../introduction.rst:157
+msgid "Logical Operators"
+msgstr "逻辑运算符"
+
+#: ../../introduction.rst:159
+msgid "Between"
+msgstr "两者之间"
+
+#: ../../introduction.rst:160
+msgid "EqualTo"
+msgstr "等于"
+
+#: ../../introduction.rst:161
+msgid "LessThanEqualTo"
+msgstr "小于等于"
+
+#: ../../introduction.rst:162
+msgid "GreaterThan"
+msgstr "大于"
+
+#: ../../introduction.rst:163
+msgid "Like"
+msgstr "似"
+
+#: ../../introduction.rst:164
+msgid "LessThan"
+msgstr "小于"
+
+#: ../../introduction.rst:165
+msgid "GreaterThanEqualTo"
+msgstr "大于等于"
+
+#: ../../introduction.rst:166
+msgid "NotEqualTo"
+msgstr "不等于"
+
+#: ../../introduction.rst:167
+msgid "NullCheck"
+msgstr "零检验"
+
+#: ../../introduction.rst:170
+msgid "Functions"
+msgstr "功能"
+
+#: ../../introduction.rst:171
+msgid "length"
+msgstr "长度"
+
+#: ../../introduction.rst:172
+msgid "lower"
+msgstr "低于"
+
+#: ../../introduction.rst:173
+msgid "ltrim"
+msgstr "函数:除去字符串开始的空格"
+
+#: ../../introduction.rst:174
+msgid "rtrim"
+msgstr "函数:除去字符串尾部空格"
+
+#: ../../introduction.rst:175
+msgid "trim"
+msgstr "函数:除去字符串开始和尾部空格"
+
+#: ../../introduction.rst:176
+msgid "upper"
+msgstr "转成大写"
+
diff --git a/docs/locale/zh/LC_MESSAGES/json.po b/docs/locale/zh/LC_MESSAGES/json.po
new file mode 100644
index 0000000..cfd82c4
--- /dev/null
+++ b/docs/locale/zh/LC_MESSAGES/json.po
@@ -0,0 +1,35 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) 2010-2015, Tom Kralidis This work is licensed under a
+# Creative Commons Attribution 4.0 International License
+# This file is distributed under the same license as the pycsw package.
+# FIRST AUTHOR <EMAIL at ADDRESS>, 2016.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: pycsw 2.0-dev\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2016-05-28 11:06+0800\n"
+"PO-Revision-Date: 2016-06-07 10:59+0800\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 2.3.4\n"
+"Last-Translator: \n"
+"Language-Team: \n"
+"X-Generator: Poedit 1.8.7\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+"Language: zh_TW\n"
+
+#: ../../json.rst:4
+msgid "JSON Support"
+msgstr "对JSON的支持"
+
+#: ../../json.rst:6
+msgid ""
+"pycsw supports JSON support for ``DescribeRecord``, ``GetRecords`` and "
+"``GetRecordById`` requests.  Adding ``outputFormat=application/json`` to "
+"your CSW request will return the response as a JSON representation."
+msgstr ""
+"pycsw 对JSON 的支持包括 ``DescribeRecord``, ``GetRecords`` 和 "
+"``GetRecordById`` 的请求。  在你的CSW请示中添加 "
+"``outputFormat=application/json`` 会返回JSON格式表达的响应。"
diff --git a/docs/locale/zh/LC_MESSAGES/license.po b/docs/locale/zh/LC_MESSAGES/license.po
new file mode 100644
index 0000000..d45f6c4
--- /dev/null
+++ b/docs/locale/zh/LC_MESSAGES/license.po
@@ -0,0 +1,78 @@
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: pycsw 2.0-dev\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2016-05-28 11:27+0800\n"
+"PO-Revision-Date: 2016-06-07 15:12+0800\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 2.3.4\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+"Last-Translator: \n"
+"Language-Team: \n"
+"Language: zh_CN\n"
+"X-Generator: Poedit 1.8.7\n"
+
+#: ../../license.rst:4
+msgid "License"
+msgstr "授权"
+
+#: ../../../LICENSE.txt:1
+msgid "The MIT License (MIT)"
+msgstr "MIT 许可证 (MIT)"
+
+#: ../../../LICENSE.txt:3
+msgid ""
+"Copyright (c) 2010-2015 Tom Kralidis Copyright (c) 2011-2015 Angelos "
+"Tzotsos Copyright (c) 2012-2015 Adam Hinz Copyright (c) 2015      "
+"Ricardo Garcia Silva"
+msgstr ""
+"版权所有 (c) 2010年-2015年Tom Kralidis 版权所有 (c) 2011年-2015年"
+"Angelos Tzotsos 版权所有 (c) 2012年-2015年Adam Hinz Copyright版权所有 "
+"(c) 2015年Ricardo Garcia Silva"
+
+#: ../../../LICENSE.txt:8
+msgid ""
+"Permission is hereby granted, free of charge, to any person obtaining a "
+"copy of this software and associated documentation files (the \"Software"
+"\"), to deal in the Software without restriction, including without "
+"limitation the rights to use, copy, modify, merge, publish, distribute, "
+"sublicense, and/or sell copies of the Software, and to permit persons to "
+"whom the Software is furnished to do so, subject to the following "
+"conditions:"
+msgstr ""
+"特此授予权限,此软件是免费的,任何人都可获得本软件副本及相关文档文件 "
+"(\"软件\"),处理软件也不受限制,包括使用、 复制、 修改、 合并、 发布、 "
+"分发、 二次许可,或复印件转卖。给予授权的人应符合以下条件︰"
+
+#: ../../../LICENSE.txt:15
+msgid ""
+"The above copyright notice and this permission notice shall be included "
+"in all copies or substantial portions of the Software."
+msgstr "上面的版权声明和许可声明应列入所有副本或软件的重要部分。"
+
+#: ../../../LICENSE.txt:18
+msgid ""
+"THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, "
+"EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF "
+"MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. "
+"IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY "
+"CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, "
+"TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE "
+"SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE."
+msgstr ""
+"该软件为“原版”,不做任何担保(明文或暗文的担保),包括对适销性、特定用途"
+"和非侵权性的保证。在任何情况下,不论是合同,侵权或其他,软件使用或其他交"
+"易。作者或版权持有者是法律责任的任何索赔、损害赔偿或其他责任。"
+
+#: ../../license.rst:9
+msgid "Documentation"
+msgstr "说明文件"
+
+#: ../../license.rst:11
+msgid ""
+"The documentation is released under the `Creative Commons Attribution "
+"4.0 International (CC BY 4.0)`_ license."
+msgstr "该文档是 `知识共享署名4.0国际发布(CC BY 4.0)`_ 许可证下发的。"
diff --git a/docs/locale/zh/LC_MESSAGES/migration-guide.po b/docs/locale/zh/LC_MESSAGES/migration-guide.po
new file mode 100644
index 0000000..45933e7
--- /dev/null
+++ b/docs/locale/zh/LC_MESSAGES/migration-guide.po
@@ -0,0 +1,57 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) 2010-2015, Tom Kralidis This work is licensed under a
+# Creative Commons Attribution 4.0 International License
+# This file is distributed under the same license as the pycsw package.
+# FIRST AUTHOR <EMAIL at ADDRESS>, 2016.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: pycsw 2.1-dev\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2016-07-21 21:02+0800\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL at ADDRESS>\n"
+"Language-Team: LANGUAGE <LL at li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 2.3.4\n"
+
+#: ../../migration-guide.rst:4
+msgid "pycsw Migration Guide"
+msgstr "pycsw迁移向导"
+
+#: ../../migration-guide.rst:6
+msgid ""
+"This page provides migration support across pycsw versions over time to "
+"help with pycsw change management."
+msgstr "这个页面提供了pycsw跨版本管理的支持"
+
+#: ../../migration-guide.rst:10
+msgid "pycsw 1.x to 2.0 Migration"
+msgstr "pycsw 1.x到2.0的迁移"
+
+#: ../../migration-guide.rst:12
+msgid ""
+"the default CSW version is now 3.0.0.  CSW clients need to explicitly "
+"specify ``version=2.0.2`` for CSW 2 behaviour.  Also, pycsw "
+"administrators can use a WSGI wrapper to the pycsw API to force "
+"``version=2.0.2`` on init of ``pycsw.server.Csw`` from the server.  See "
+":ref:`csw-support` for more information."
+msgstr "缺省的CSW版本是 3.0.0。 CSW 客户端需要显式地声明 ```version=2.0.2`` 来使用 CSW 2的行为。"
+"另外,pycsw管理器可能通过在服务器端通过 ``pycsw.server.Csw`` 初始化来使用强制的 pycsw ``version=2.0.2``。 "
+"查看 :ref:`csw-support` 来获取更多的信息。 "
+
+#: ../../migration-guide.rst:17
+msgid ""
+"``pycsw.server.Csw.dispatch_wsgi()`` previously returned the response "
+"content as a string.  2.0.0 introduces a compatability break to "
+"additionally return the HTTP status code along with the response as a "
+"list"
+msgstr ""
+
+#: ../../migration-guide.rst:42
+msgid "See :ref:`api` for more information."
+msgstr "查看 :ref:`api` 来获取更多的信息。"
+
diff --git a/docs/locale/zh/LC_MESSAGES/oaipmh.po b/docs/locale/zh/LC_MESSAGES/oaipmh.po
new file mode 100644
index 0000000..6d6b366
--- /dev/null
+++ b/docs/locale/zh/LC_MESSAGES/oaipmh.po
@@ -0,0 +1,41 @@
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: pycsw 2.0-dev\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2015-11-23 21:42+0800\n"
+"PO-Revision-Date: 2016-06-07 15:16+0800\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+"Last-Translator: \n"
+"Language-Team: \n"
+"Language: zh_CN\n"
+"X-Generator: Poedit 1.8.7\n"
+
+#: ../../oaipmh.rst:4
+msgid "OAI-PMH Support"
+msgstr "OAI-PMH支持"
+
+#: ../../oaipmh.rst:6
+msgid ""
+"pycsw supports the `The Open Archives Initiative Protocol for Metadata "
+"Harvesting`_ (OAI-PMH) standard."
+msgstr "pycsw支持 `元数据获取的开放式档案协议`_ (OAI-PMH)标准"
+
+#: ../../oaipmh.rst:8
+msgid ""
+"OAI-PMH OpenSearch support is enabled by default.  HTTP requests must be "
+"specified with ``mode=oaipmh`` in the base URL for OAI-PMH requests, e.g.:"
+msgstr ""
+"默认情况下是启用OAI-PMH OpenSearch的。 HTTP请求必须在 OAI-PMH要求的基准URL"
+"中指定``mode= oaipmh``,例如:"
+
+#: ../../oaipmh.rst:14
+msgid ""
+"See http://www.openarchives.org/OAI/openarchivesprotocol.html for more "
+"information on OAI-PMH as well as request / reponse examples."
+msgstr ""
+"见 http://www.openarchives.org/OAI/openarchivesprotocol.html,是关于OAI-PMH"
+"以及更多信息请求及回应的例子。"
diff --git a/docs/locale/zh/LC_MESSAGES/odc.po b/docs/locale/zh/LC_MESSAGES/odc.po
new file mode 100644
index 0000000..0982d5d
--- /dev/null
+++ b/docs/locale/zh/LC_MESSAGES/odc.po
@@ -0,0 +1,70 @@
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: pycsw 2.0-dev\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2016-12-17 17:33+0800\n"
+"PO-Revision-Date: 2016-06-07 16:00+0800\n"
+"Last-Translator: \n"
+"Language-Team: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 2.3.4\n"
+
+#: ../../odc.rst:4
+msgid "Open Data Catalog Configuration"
+msgstr "开放性数据目录配置"
+
+#: ../../odc.rst:6
+msgid ""
+"Open Data Catalog (https://github.com/azavea/Open-Data-Catalog/) is an "
+"open data catalog based on Django, Python and PostgreSQL. It was "
+"originally developed for OpenDataPhilly.org, a portal that provides "
+"access to open data sets, applications, and APIs related to the "
+"Philadelphia region. The Open Data Catalog is a generalized version of "
+"the original source code with a simple skin. It is intended to display "
+"information and links to publicly available data in an easily searchable "
+"format. The code also includes options for data owners to submit data for"
+" consideration and for registered public users to nominate a type of data"
+" they would like to see openly available to the public."
+msgstr ""
+"开放数据目录(https://github.com/azavea/open-data-"
+"catalog/)是一种基于Django,Python和PostgreSQL的。它最初为opendataphilly.org(一个门户网站)提供开放的数据集,应用程序,并其API与费城地区相关。开放数据目录是一个通用的原始版本的源代码,其皮肤也很简易。它以显示信息为主,以检索便宜为主。该代码还包括数据所有者提交的数据代码,会指定一种数据类型供注册的公共用户参考,他们很乐意为公众公开信息。"
+
+#: ../../odc.rst:8
+msgid ""
+"pycsw supports binding to an existing Open Data Catalog repository for "
+"metadata query.  The binding is read-only (transactions are not in scope,"
+" as Open Data Catalog manages repository metadata changes in the "
+"application proper)."
+msgstr ""
+"pycsw绑定到用于元数据查询的现有公开数据目录库。此绑定是只读文件(交易不在范围内,Open Data "
+"Catalog在适当的应用程序中管理元数据库)"
+
+#: ../../odc.rst:11
+msgid "Open Data Catalog Setup"
+msgstr "开放数据目录设置"
+
+#: ../../odc.rst:13
+msgid ""
+"Open Data Catalog provides CSW functionality using pycsw out of the box "
+"(installing ODC will also install pycsw).  Settings are defined in "
+"https://github.com/azavea/Open-Data-"
+"Catalog/blob/master/OpenDataCatalog/settings.py#L165."
+msgstr ""
+"开放数据目录提供了CSW功能,pycsw无需设置,开箱即用(安装ODC需安装pycsw)。设置在https://github.com/azavea"
+"/Open-Data-Catalog/blob/master/OpenDataCatalog/settings.py#L165中。"
+
+#: ../../odc.rst:15
+msgid ""
+"ODC settings must ensure that ``REGISTRY_PYCSW['repository']['source']`` "
+"is set to``hypermap.search.pycsw_repository``."
+msgstr ""
+
+#: ../../odc.rst:17
+msgid ""
+"At this point, pycsw is able to read from the Open Data Catalog "
+"repository using the Django ORM."
+msgstr "在这一点上,pycsw可以用Django的ORM从数据目录库中读取。"
+
diff --git a/docs/locale/zh/LC_MESSAGES/opensearch.po b/docs/locale/zh/LC_MESSAGES/opensearch.po
new file mode 100644
index 0000000..73f52d1
--- /dev/null
+++ b/docs/locale/zh/LC_MESSAGES/opensearch.po
@@ -0,0 +1,56 @@
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: pycsw 2.0-dev\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2016-05-28 11:27+0800\n"
+"PO-Revision-Date: 2016-06-08 11:03+0800\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 2.3.4\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+"Last-Translator: \n"
+"Language-Team: \n"
+"Language: zh_CN\n"
+"X-Generator: Poedit 1.8.7\n"
+
+#: ../../opensearch.rst:4
+msgid "OpenSearch Support"
+msgstr "OpenSearch支撑"
+
+#: ../../opensearch.rst:6
+msgid ""
+"pycsw supports the `OGC OpenSearch Geo and Time Extensions 1.0`_ "
+"standard via the following conformance classes:"
+msgstr ""
+"pycsw通过以下分类支持 `OGC OpenSearch地理和时间扩展1.0`_ 标准:"
+
+#: ../../opensearch.rst:8
+msgid ""
+"Core (GeoSpatial Service) ``{searchTerms}``, ``{geo:box}``, "
+"``{startIndex}``, ``{count}``"
+msgstr ""
+"核心(地理空间服务)``{searchTerms}`,``{geo:box}``,"
+"``{startIndex}``,``{count}``"
+
+#: ../../opensearch.rst:9
+msgid "Temporal Search core ``{time:start}``, ``{time:end}``"
+msgstr "时间搜索核心``{时间:开始}``,``{时间:结束}``"
+
+#: ../../opensearch.rst:11
+msgid ""
+"OpenSearch support is enabled by default.  HTTP requests must be "
+"specified with ``mode=opensearch`` in the base URL for OpenSearch "
+"requests, e.g.:"
+msgstr ""
+"OpenSearch启动是默认的。 HTTP请求必须在OpenSearch要求的基准URL中指"
+"定``mode=opensearch``,例如:"
+
+#: ../../opensearch.rst:17
+msgid ""
+"This will return the Description document which can then be "
+"`autodiscovered <http://www.opensearch.org/Specifications/"
+"OpenSearch/1.1#Autodiscovery>`_."
+msgstr ""
+"将返回描述文档,此文档可以 `autodiscovered <http://www.opensearch.org/Specifications/OpenSearch/1.1#Autodiscovery>`_ 。"
diff --git a/docs/locale/zh/LC_MESSAGES/outputschemas.po b/docs/locale/zh/LC_MESSAGES/outputschemas.po
new file mode 100644
index 0000000..f84e072
--- /dev/null
+++ b/docs/locale/zh/LC_MESSAGES/outputschemas.po
@@ -0,0 +1,96 @@
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: pycsw 2.0-dev\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2016-05-28 11:27+0800\n"
+"PO-Revision-Date: 2016-06-08 13:51+0800\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 2.3.4\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+"Last-Translator: \n"
+"Language-Team: \n"
+"Language: zh_CN\n"
+"X-Generator: Poedit 1.8.7\n"
+
+#: ../../outputschemas.rst:4
+msgid "Output Schema Plugins"
+msgstr "输出模式插件"
+
+#: ../../outputschemas.rst:7
+msgid "Overview"
+msgstr "视图"
+
+#: ../../outputschemas.rst:9
+msgid ""
+"pycsw allows for extending the implementation of output schemas to the "
+"core standard.  outputschemas allow for a client to request metadata in "
+"a specific format (ISO, Dublin Core, FGDC, NASA DIF Atom and GM03 are "
+"default)."
+msgstr ""
+"pycsw 使输出架构达到核心标准。输出架构允许客户端请求特定格式的元数据 "
+"(ISO, Dublin Core, FGDC, NASA DIF Atom、GM03是默认设置)。"
+
+#: ../../outputschemas.rst:11
+msgid ""
+"All outputschemas must be placed in the ``pycsw/plugins/outputschemas`` "
+"directory."
+msgstr ""
+"所有输出架构必须都放在 ' pycsw/插件/输出架构(`pycsw/plugins/"
+"outputschemas`) 目录中。"
+
+#: ../../outputschemas.rst:14
+msgid "Requirements"
+msgstr "要求"
+
+#: ../../outputschemas.rst:29
+msgid "Implementing a new outputschema"
+msgstr "实施新的输出架构"
+
+#: ../../outputschemas.rst:31
+msgid ""
+"Create a file in ``pycsw/plugins/outputschemas``, which defines the "
+"following:"
+msgstr "创建文件 ' pycsw/插件/输出架构 ',其中定义了以下内容 ︰"
+
+#: ../../outputschemas.rst:33
+msgid ""
+"``NAMESPACE``: the default namespace of the outputschema which will be "
+"advertised"
+msgstr "命名空间: 输出架构的默认命名空间"
+
+#: ../../outputschemas.rst:34
+msgid "``NAMESPACE``: dict of all applicable namespaces to outputschema"
+msgstr "命名空间: 所有适用的命名空间在输出架构中以目录显示"
+
+#: ../../outputschemas.rst:35
+msgid ""
+"``XPATH_MAPPINGS``: dict of pycsw core queryables mapped to the "
+"equivalent XPath of the outputschema"
+msgstr "' XPATH_MAPPINGS ': pycsw 核心查询目录映射到输出空间的等效XPath"
+
+#: ../../outputschemas.rst:36
+msgid ""
+"``write_record``: function which returns a record as an ``lxml.etree."
+"Element`` object"
+msgstr "'write_record ': 返回记录为' lxml.etree.Element ' 对象记录的功能"
+
+#: ../../outputschemas.rst:38
+msgid ""
+"Add the name of the file to ``__init__.py:__all__``.  The new "
+"outputschema is now supported in pycsw."
+msgstr "将文件名添加到 '__init__.py:__all__ '。 新的输出架构就在 pycsw中。"
+
+#: ../../outputschemas.rst:41
+msgid "Testing"
+msgstr "测试"
+
+#: ../../outputschemas.rst:43
+msgid ""
+"New outputschemas must add examples to the :ref:`tests` interface, which "
+"must provide example requests specific to the profile."
+msgstr ""
+"新的输出架构必须添加到示例: :ref:`tests` 接口,此 '测试' 接口须提供特定于该配置"
+"文件的示例请求。"
diff --git a/docs/locale/zh/LC_MESSAGES/profiles.po b/docs/locale/zh/LC_MESSAGES/profiles.po
new file mode 100644
index 0000000..af2eeb3
--- /dev/null
+++ b/docs/locale/zh/LC_MESSAGES/profiles.po
@@ -0,0 +1,277 @@
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: pycsw 2.0-dev\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2015-11-23 21:42+0800\n"
+"PO-Revision-Date: 2016-06-08 14:52+0800\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+"Last-Translator: \n"
+"Language-Team: \n"
+"Language: zh_CN\n"
+"X-Generator: Poedit 1.8.7\n"
+
+#: ../../profiles.rst:4
+msgid "Profile Plugins"
+msgstr "配置文件的插件"
+
+#: ../../profiles.rst:7 ../../../pycsw/plugins/profiles/apiso/docs/apiso.rst:7
+#: ../../../pycsw/plugins/profiles/apiso/docs/apiso.rst:35
+#: ../../../pycsw/plugins/profiles/ebrim/docs/ebrim.rst:7
+msgid "Overview"
+msgstr "视图"
+
+#: ../../profiles.rst:9
+msgid ""
+"pycsw allows for the implementation of profiles to the core standard. "
+"Profiles allow specification of additional metadata format types (i.e. ISO "
+"19139:2007, NASA DIF, INSPIRE, etc.) to the repository, which can be "
+"queried and presented to the client.  pycsw supports a plugin architecture "
+"which allows for runtime loading of Python code."
+msgstr ""
+"pycsw 使配置文件达到核心标准。配置文件允许其余元数据格式类型 (例如ISO "
+"19139:2007, NASA DIF, INSPIRE等) 特定到存储库,此配置文件可以查询,也可以提"
+"交给客户端。 pycsw 支持插件体系结构,也支持运行时加载的 Python 代码。"
+
+#: ../../profiles.rst:11
+msgid ""
+"All profiles must be placed in the ``pycsw/plugins/profiles`` directory."
+msgstr "所有的配置文件必须放在 ' pycsw/插件/配置文件 '目录中。"
+
+#: ../../profiles.rst:14
+msgid "Requirements"
+msgstr "要求"
+
+#: ../../profiles.rst:30
+msgid "Abstract Base Class Definition"
+msgstr "抽象基类定义"
+
+#: ../../profiles.rst:32
+msgid ""
+"All profile code must be instantiated as a subclass of ``profile."
+"Profile``.  Below is an example to add a ``Foo`` profile:"
+msgstr ""
+"配置文件的所有代码须实例化为 ``profile.Profile`` 。下面是一个添加配置文件 ``Foo`` 的示例︰"
+
+#: ../../profiles.rst:53
+msgid ""
+"Your profile plugin class (``FooProfile``) must implement all methods as "
+"per ``profile.Profile``.  Profile methods must always return ``lxml.etree."
+"Element`` types, or ``None``."
+msgstr ""
+"您的配置插件类 (FooProfile) 必须按照``profile.Profile``完成所有的配置工作。 "
+"配置文件方法须保持 ``lxml.etree.Element`` 类型或 ``None``"
+
+#: ../../profiles.rst:56
+msgid "Enabling Profiles"
+msgstr "启用配置文件"
+
+#: ../../profiles.rst:58
+msgid ""
+"All profiles are disabled by default.  To specify profiles at runtime, set "
+"the ``server.profiles`` value in the :ref:`configuration` to the name of "
+"the package (in the ``pycsw/plugins/profiles`` directory).  To enable "
+"multiple profiles, specify as a comma separated value (see :ref:"
+"`configuration`)."
+msgstr ""
+"所有配置文件默认是不可用的。 若要指定在运行时的配置文件,在参考文件"
+" :ref:`configuration` 中设置 ``server.profiles`` 值(在 ``pycsw/plugins/profiles`` 目录"
+"中)。 若要启用多个配置文件,请指定值(以逗号分隔) (请参见: :ref:`configuration` )。"
+
+#: ../../profiles.rst:61
+#: ../../../pycsw/plugins/profiles/apiso/docs/apiso.rst:27
+#: ../../../pycsw/plugins/profiles/ebrim/docs/ebrim.rst:27
+msgid "Testing"
+msgstr "测试"
+
+#: ../../profiles.rst:63
+msgid ""
+"Profiles must add examples to the :ref:`tests` interface, which must "
+"provide example requests specific to the profile."
+msgstr ""
+"配置文件必须添加到 :ref:`tests` 接口,此接口须提供特定于该配置文件的示例请求。"
+
+#: ../../profiles.rst:66
+msgid "Supported Profiles"
+msgstr "支持的配置文件"
+
+#: ../../../pycsw/plugins/profiles/apiso/docs/apiso.rst:4
+msgid "ISO Metadata Application Profile (1.0.0)"
+msgstr "ISO 元数据应用程序配置文件 (1.0.0)"
+
+#: ../../../pycsw/plugins/profiles/apiso/docs/apiso.rst:8
+msgid ""
+"The ISO Metadata Application Profile (APISO) is a profile of CSW 2.0.2 "
+"which enables discovery of geospatial metadata following ISO 19139:2007 and "
+"ISO 19119:2005/PDAM 1."
+msgstr ""
+"ISO 元数据应用程序配置文件 (APISO) 是CSW 2.0.2的配置文件,是继地理空间元数"
+"据 ISO 19139:2007 和 ISO 19119:2005 之后开发的文件。"
+
+#: ../../../pycsw/plugins/profiles/apiso/docs/apiso.rst:11
+#: ../../../pycsw/plugins/profiles/apiso/docs/apiso.rst:40
+#: ../../../pycsw/plugins/profiles/ebrim/docs/ebrim.rst:11
+msgid "Configuration"
+msgstr "配置"
+
+#: ../../../pycsw/plugins/profiles/apiso/docs/apiso.rst:13
+#: ../../../pycsw/plugins/profiles/ebrim/docs/ebrim.rst:13
+msgid "No extra configuration is required."
+msgstr "不需要其余配置。"
+
+#: ../../../pycsw/plugins/profiles/apiso/docs/apiso.rst:16
+#: ../../../pycsw/plugins/profiles/ebrim/docs/ebrim.rst:16
+msgid "Querying"
+msgstr "查询"
+
+#: ../../../pycsw/plugins/profiles/apiso/docs/apiso.rst:18
+msgid "**typename**: ``gmd:MD_Metadata``"
+msgstr "类型名称:``gmd:MD_元数据``"
+
+#: ../../../pycsw/plugins/profiles/apiso/docs/apiso.rst:19
+msgid "**outputschema**: ``http://www.isotc211.org/2005/gmd``"
+msgstr "输出模式: ``http://www.isotc211.org/2005/gmd``"
+
+#: ../../../pycsw/plugins/profiles/apiso/docs/apiso.rst:22
+msgid "Enabling APISO Support"
+msgstr "启用 APISO 支持"
+
+#: ../../../pycsw/plugins/profiles/apiso/docs/apiso.rst:24
+msgid ""
+"To enable APISO support, add ``apiso`` to ``server.profiles`` as specified "
+"in :ref:`configuration`."
+msgstr ""
+"若要启用 APISO 支持,作为指定 :ref:`configuration` 信息,将 `apiso` 添加到 ``server.profiles`` "
+
+#: ../../../pycsw/plugins/profiles/apiso/docs/apiso.rst:29
+msgid ""
+"A testing interface is available in ``tests/index.html`` which contains "
+"tests specific to APISO to demonstrate functionality.  See :ref:`tests` for "
+"more information."
+msgstr ""
+"测试接口在 ``tests/index.html`` 可用,其包含特定于 APISO 演示功能的测试。请参"
+"见: :ref:`tests` 及其它更多信息。"
+
+#: ../../../pycsw/plugins/profiles/apiso/docs/apiso.rst:32
+msgid "INSPIRE Extension"
+msgstr "激发扩展"
+
+#: ../../../pycsw/plugins/profiles/apiso/docs/apiso.rst:37
+msgid ""
+"APISO includes an extension for enabling `INSPIRE Discovery Services 3.0`_ "
+"support.  To enable the INSPIRE extension to APISO, create a ``[metadata:"
+"inspire]`` section in the main configuration with ``enabled`` set to "
+"``true``."
+msgstr ""
+"APISO 包括启用 `INSPIRE Discovery Services 3.0`_ 的扩展。 若要启用 INSPIRE扩展到 APISO,需"
+"要用 ``enabled`` set to ``true``在主要的配置中创建 ``[metadata:inspire]`` 部分"
+
+#: ../../../pycsw/plugins/profiles/apiso/docs/apiso.rst:42
+msgid "**[metadata:inspire]**"
+msgstr "元数据:inspire"
+
+#: ../../../pycsw/plugins/profiles/apiso/docs/apiso.rst:44
+msgid ""
+"**enabled**: whether to enable the INSPIRE extension (``true`` or ``false``)"
+msgstr "启用: 是否启用INSPIRE扩展 ('是 '或'否')"
+
+#: ../../../pycsw/plugins/profiles/apiso/docs/apiso.rst:45
+msgid ""
+"**languages_supported**: supported languages (see http://inspire.ec.europa."
+"eu/schemas/common/1.0/enums/enum_eng.xsd, simpleType ``euLanguageISO6392B``)"
+msgstr ""
+"支持的语言: (见 http://inspire.ec.europa.eu/schemas/common/1.0/enums/"
+"enum_eng.xsd,simpleType ' euLanguageISO6392B ')"
+
+#: ../../../pycsw/plugins/profiles/apiso/docs/apiso.rst:46
+msgid ""
+"**default_language**: the default language (see http://inspire.ec.europa.eu/"
+"schemas/common/1.0/enums/enum_eng.xsd, simpleType ``euLanguageISO6392B``)"
+msgstr ""
+"默认语言 (见 http://inspire.ec.europa.eu/schemas/common/1.0/enums/enum_eng."
+"xsd,simpleType ' euLanguageISO6392B ')"
+
+#: ../../../pycsw/plugins/profiles/apiso/docs/apiso.rst:47
+msgid "**date**: date of INSPIRE metadata offering (in `ISO 8601`_ format)"
+msgstr "**date**: INSPIRE元数据的日期 (在 `ISO 8601`_ 格式中) "
+
+#: ../../../pycsw/plugins/profiles/apiso/docs/apiso.rst:48
+msgid ""
+"**gemet_keywords**: a comma-seperated keyword list of `GEMET INSPIRE theme "
+"keywords`_ about the service (see http://inspire.ec.europa.eu/schemas/"
+"common/1.0/enums/enum_eng.xsd, complexType ``inspireTheme_eng``)"
+msgstr ""
+"**gemet_keywords**: 关于服务的,以逗号分隔的关键字列表 `GEMET INSPIRE 主题关键词`_ "
+" (见 http://inspire.ec.europa.eu/schemas/common/1.0/enums/enum_eng.xsd,"
+"complexType ``inspireTheme_eng`` )"
+
+#: ../../../pycsw/plugins/profiles/apiso/docs/apiso.rst:49
+msgid ""
+"**conformity_service**: the level of INSPIRE conformance for spatial data "
+"sets and services (``conformant``, ``notConformant``, ``notEvaluated``)"
+msgstr ""
+"conformity_service: 以空间数据集和服务 (``conformant``, ``notConformant``, "
+"``notEvaluated``)为目标的INSPIRE级别"
+
+#: ../../../pycsw/plugins/profiles/apiso/docs/apiso.rst:50
+msgid ""
+"**contact_organization**: the organization name responsible for the INSPIRE "
+"metadata"
+msgstr "contact_organization: 负责 INSPIRE元数据的组织名称"
+
+#: ../../../pycsw/plugins/profiles/apiso/docs/apiso.rst:51
+msgid ""
+"**contact_email**: the email address of entity responsible for the INSPIRE "
+"metadata"
+msgstr "contact_email: 负责 INSPIRE元数据实体的电子邮件地址"
+
+#: ../../../pycsw/plugins/profiles/apiso/docs/apiso.rst:52
+msgid ""
+"**temp_extent**: temporal extent of the service (in `ISO 8601`_ format).  "
+"Either a single date (i.e. ``yyyy-mm-dd``), or an extent (i.e. ``yyyy-mm-dd/"
+"yyyy-mm-dd``)"
+msgstr ""
+"**temp_extent**: ( `ISO 8601`_ 格式)服务时间。 单个日期 ( ``yyyy-mm-dd`` ) 或多"
+"数以 ( ``yyyy-mm-dd/yyyy-mm-dd`` )"
+
+#: ../../../pycsw/plugins/profiles/ebrim/docs/ebrim.rst:4
+msgid "CSW-ebRIM Registry Service - Part 1: ebRIM profile of CSW"
+msgstr "CSW-ebRIM注册服务-第一部分: CSW的ebRIM 配置文件"
+
+#: ../../../pycsw/plugins/profiles/ebrim/docs/ebrim.rst:8
+msgid ""
+"The CSW-ebRIM Registry Service is a profile of CSW 2.0.2 which enables "
+"discovery of geospatial metadata following the ebXML information model."
+msgstr ""
+"CSW-ebRIM注册服务是CSW 2.0.2的配置文件,是继ebXML 信息模型之后的地理空间元数"
+"据配置文件。"
+
+#: ../../../pycsw/plugins/profiles/ebrim/docs/ebrim.rst:18
+msgid "**typename**: ``rim:RegistryObject``"
+msgstr "类型名称: ' rim: RegistryObject '"
+
+#: ../../../pycsw/plugins/profiles/ebrim/docs/ebrim.rst:19
+msgid "**outputschema**: ``urn:oasis:names:tc:ebxml-regrep:xsd:rim:3.0``"
+msgstr "输出模式: ' urn:oasis:names:tc:ebxml-regrep:xsd:rim:3.0' "
+
+#: ../../../pycsw/plugins/profiles/ebrim/docs/ebrim.rst:22
+msgid "Enabling ebRIM Support"
+msgstr "启用 ebRIM 支持"
+
+#: ../../../pycsw/plugins/profiles/ebrim/docs/ebrim.rst:24
+msgid ""
+"To enable ebRIM support, add ``ebrim`` to ``server.profiles`` as specified "
+"in :ref:`configuration`."
+msgstr ""
+"若要启用 ebRIM 支持,需添加 ``ebrim`` 到 ``server.profiles`` ,以 作为指定的   :ref:`configuration`。 "
+
+#: ../../../pycsw/plugins/profiles/ebrim/docs/ebrim.rst:29
+msgid ""
+"A testing interface is available in ``tests/index.html`` which contains "
+"tests specific to ebRIM to demonstrate functionality.  See :ref:`tests` for "
+"more information."
+msgstr ""
+"测试接口在 ``tests/index.html``  可用,其包含特定于ebRIM演示功能的测试。请参见: :ref:`tests` 及其它更多信息。"
diff --git a/docs/locale/zh/LC_MESSAGES/repofilters.po b/docs/locale/zh/LC_MESSAGES/repofilters.po
new file mode 100644
index 0000000..0e6c701
--- /dev/null
+++ b/docs/locale/zh/LC_MESSAGES/repofilters.po
@@ -0,0 +1,179 @@
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: pycsw 2.0-dev\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2015-11-23 21:42+0800\n"
+"PO-Revision-Date: 2016-06-08 15:16+0800\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+"Last-Translator: \n"
+"Language-Team: \n"
+"Language: zh_CN\n"
+"X-Generator: Poedit 1.8.7\n"
+
+#: ../../repofilters.rst:4
+msgid "Repository Filters"
+msgstr "存储库中的筛选器"
+
+#: ../../repofilters.rst:6
+msgid ""
+"pycsw has the ability to perform server side repository / database filters "
+"as a means to mask all CSW requests to query against a specific subset of "
+"the metadata repository, thus providing the ability to deploy multiple "
+"pycsw instances pointing to the same database in different ways via the "
+"``repository.filter`` configuration option."
+msgstr ""
+"pycsw 有能力执行服务器端存储库或数据库筛选功能,以覆盖所有的CSW请求,目的是"
+"查询元数据存储库中的一个特定子集,从而需部署多个 pycsw 实例,通过 "
+"'repository.filter' 配置选项,以不同的方式指向同一个数据库。"
+
+#: ../../repofilters.rst:8
+msgid ""
+"Repository filters are a convenient way to subset your repository at the "
+"server level without the hassle of creating proper database views.  For "
+"large repositories, it may be better to subset at the database level for "
+"performance."
+msgstr ""
+"存储库中的筛选器是一种便捷方式,是为了创建子数据库,以免去创建适当数据库视图"
+"的服务器级别的步骤。 对于大型数据库而言,它可能比创建数据库级别的子集要更好"
+"一些。"
+
+#: ../../repofilters.rst:11
+msgid "Scenario: One Database, Many Views"
+msgstr "场景 ︰ 一个数据库,很多种视角"
+
+#: ../../repofilters.rst:13
+msgid "Imagine a sample database table of records (subset below for brevity):"
+msgstr "想象一下,现在要记录数据库示例表(下面以子集做为简称):"
+
+#: ../../repofilters.rst:1
+msgid "identifier"
+msgstr "标识"
+
+#: ../../repofilters.rst:1
+msgid "parentidentifier"
+msgstr "母标识符"
+
+#: ../../repofilters.rst:1
+msgid "title"
+msgstr "标题"
+
+#: ../../repofilters.rst:1
+msgid "abstract"
+msgstr "摘要"
+
+#: ../../repofilters.rst:1
+msgid "1"
+msgstr "1"
+
+#: ../../repofilters.rst:1
+msgid "33"
+msgstr "33"
+
+#: ../../repofilters.rst:1
+msgid "foo1"
+msgstr "第一页"
+
+#: ../../repofilters.rst:1
+msgid "bar1"
+msgstr "第1条"
+
+#: ../../repofilters.rst:1
+msgid "2"
+msgstr "2"
+
+#: ../../repofilters.rst:1
+msgid "foo2"
+msgstr "第二页"
+
+#: ../../repofilters.rst:1
+msgid "bar2"
+msgstr "第2条"
+
+#: ../../repofilters.rst:1
+msgid "3"
+msgstr "3"
+
+#: ../../repofilters.rst:1
+msgid "55"
+msgstr "55"
+
+#: ../../repofilters.rst:1
+msgid "foo3"
+msgstr "第三页"
+
+#: ../../repofilters.rst:1
+msgid "bar3"
+msgstr "第3条"
+
+#: ../../repofilters.rst:1
+msgid "4"
+msgstr "4"
+
+#: ../../repofilters.rst:1
+msgid "5"
+msgstr "5"
+
+#: ../../repofilters.rst:1
+msgid "21"
+msgstr "21"
+
+#: ../../repofilters.rst:1
+msgid "foo5"
+msgstr "第五页"
+
+#: ../../repofilters.rst:1
+msgid "bar5"
+msgstr "第5条"
+
+#: ../../repofilters.rst:1
+msgid "foo6"
+msgstr "第六页"
+
+#: ../../repofilters.rst:1
+msgid "bar6"
+msgstr "第6条"
+
+#: ../../repofilters.rst:25
+msgid ""
+"A default pycsw instance (with no ``repository.filters`` option) will "
+"always process CSW requests against the entire table.  So a CSW "
+"`GetRecords` filter like:"
+msgstr ""
+"若没有``repository.filters``选项,pycsw默认是始终处理整个表的CSW请求。"
+"CSW`GetRecords`过滤如:"
+
+#: ../../repofilters.rst:36
+msgid "...will return:"
+msgstr "...将返回:"
+
+#: ../../repofilters.rst:44
+msgid ""
+"Suppose you wanted to deploy another pycsw instance which serves metadata "
+"from the same database, but only from a specific subset.  Here we set the "
+"``repository.filter`` option:"
+msgstr ""
+"假设你要部署其他pycsw应用实例,此实例来自同一个数据库的元数据,但它只能来自"
+"一个特定子集。在这里,我们设置了``repository.filter``选项:"
+
+#: ../../repofilters.rst:52 ../../repofilters.rst:67
+msgid ""
+"The same CSW `GetRecords` filter as per above then yields the following "
+"results:"
+msgstr "依上述所说,同一CSW`GetRecords`过滤器将得到以下结果:"
+
+#: ../../repofilters.rst:59
+msgid "Another example:"
+msgstr "另一个例子:"
+
+#: ../../repofilters.rst:74
+msgid ""
+"The ``repository.filter`` option accepts all core queryables set in the "
+"pycsw core model (see ``pycsw.config.StaticContext.md_core_model`` for the "
+"complete list)."
+msgstr ""
+"该``数据库.过滤器``选项功能是在pycsw核心模式中接收所有核心查询设置(见"
+"``pycsw.config.StaticContext.md_core_model``的完整列表)。"
diff --git a/docs/locale/zh/LC_MESSAGES/repositories.po b/docs/locale/zh/LC_MESSAGES/repositories.po
new file mode 100644
index 0000000..afa7544
--- /dev/null
+++ b/docs/locale/zh/LC_MESSAGES/repositories.po
@@ -0,0 +1,91 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) 2010-2015, Tom Kralidis This work is licensed under a
+# Creative Commons Attribution 4.0 International License
+# This file is distributed under the same license as the pycsw package.
+# FIRST AUTHOR <EMAIL at ADDRESS>, 2016.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: pycsw 2.1-dev\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2016-12-17 17:33+0800\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL at ADDRESS>\n"
+"Language-Team: LANGUAGE <LL at li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 2.3.4\n"
+
+#: ../../repositories.rst:4
+msgid "Repository Plugins"
+msgstr ""
+
+#: ../../repositories.rst:7
+msgid "Overview"
+msgstr ""
+
+#: ../../repositories.rst:9
+msgid ""
+"pycsw allows for the implementation of custom repositories in order to "
+"connect to a backend different from the pycsw's default.  This is "
+"especially useful when downstream applications manage their own metadata "
+"model/database/document store and want pycsw to connect to it directly "
+"instead of using pycsw's default model, thus creating duplicate "
+"repositories which then require syncronization/accounting.  Repository "
+"plugins enable a single metadata backend which is independent from the "
+"pycsw setup.  pycsw thereby becomes a pure wrapper around a given backend"
+" in providing CSW and other APIs atop a given application."
+msgstr ""
+
+#: ../../repositories.rst:11
+msgid ""
+"All outputschemas must be placed in the ``pycsw/plugins/outputschemas`` "
+"directory."
+msgstr ""
+
+#: ../../repositories.rst:14
+msgid "Requirements"
+msgstr ""
+
+#: ../../repositories.rst:16
+msgid "Repository plugins:"
+msgstr ""
+
+#: ../../repositories.rst:18
+msgid "can be developed and referenced / connected external to pycsw"
+msgstr ""
+
+#: ../../repositories.rst:19
+msgid "must be accessible within the ``PYTHONPATH`` of a given application"
+msgstr ""
+
+#: ../../repositories.rst:20
+msgid ""
+"must implement pycsw's ``pycsw.core.repository.Repository`` properties "
+"and methods"
+msgstr ""
+
+#: ../../repositories.rst:21
+msgid ""
+"must be specified in the pycsw :ref:`configuration` as a class reference "
+"(e.g. ``path.to.repo_plugin.MyRepository``)"
+msgstr ""
+
+#: ../../repositories.rst:22
+msgid ""
+"must minimally implement the ``query_insert``, ``query_domain``, "
+"``query_ids``, and ``query`` methods"
+msgstr ""
+
+#: ../../repositories.rst:25
+msgid "Configuration"
+msgstr ""
+
+#: ../../repositories.rst:27
+msgid ""
+"set pycsw's ``repository.source`` setting to the class which implements "
+"the custom repository:"
+msgstr ""
+
diff --git a/docs/locale/zh/LC_MESSAGES/sitemaps.po b/docs/locale/zh/LC_MESSAGES/sitemaps.po
new file mode 100644
index 0000000..1918e45
--- /dev/null
+++ b/docs/locale/zh/LC_MESSAGES/sitemaps.po
@@ -0,0 +1,31 @@
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: pycsw 2.0-dev\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2015-11-23 21:42+0800\n"
+"PO-Revision-Date: 2016-06-08 15:18+0800\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+"Last-Translator: \n"
+"Language-Team: \n"
+"Language: zh_CN\n"
+"X-Generator: Poedit 1.8.7\n"
+
+#: ../../sitemaps.rst:4
+msgid "XML Sitemaps"
+msgstr "XML网站地图"
+
+#: ../../sitemaps.rst:6
+msgid "`XML Sitemaps`_ can be generated by running:"
+msgstr "`XML 网站地图`_ 可以通过以下……运行"
+
+#: ../../sitemaps.rst:12
+msgid ""
+"The ``sitemap.xml`` file should be saved to an an area on your web server "
+"(parallel to or above your pycsw install location) to enable web crawlers "
+"to index your repository."
+msgstr ""
+"该 ``sitemap.xml`` 文件应保存到你Web服务器中任意一个地方(平行于或高于pycsw安装位置),使Web爬虫搜索你的数据库。"
diff --git a/docs/locale/zh/LC_MESSAGES/soap.po b/docs/locale/zh/LC_MESSAGES/soap.po
new file mode 100644
index 0000000..0d6be12
--- /dev/null
+++ b/docs/locale/zh/LC_MESSAGES/soap.po
@@ -0,0 +1,28 @@
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: pycsw 2.0-dev\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2015-11-23 21:42+0800\n"
+"PO-Revision-Date: 2016-06-08 15:23+0800\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+"Last-Translator: \n"
+"Language-Team: \n"
+"Language: zh_CN\n"
+"X-Generator: Poedit 1.8.7\n"
+
+#: ../../soap.rst:4
+msgid "SOAP"
+msgstr "简单对象访问协议"
+
+#: ../../soap.rst:6
+msgid ""
+"pycsw supports handling of SOAP encoded requests and responses as per "
+"subclause 10.3.2 of OGC:CSW 2.0.2.  SOAP request examples can be found in "
+"``tests/index.html``."
+msgstr ""
+"pycsw支持SOAP编码请求,参照OGC:CSW 2.0.2分条款中10.3.2。 SOAP请求的示例在"
+"``测试/ index.html``中。"
diff --git a/docs/locale/zh/LC_MESSAGES/sru.po b/docs/locale/zh/LC_MESSAGES/sru.po
new file mode 100644
index 0000000..161bfe7
--- /dev/null
+++ b/docs/locale/zh/LC_MESSAGES/sru.po
@@ -0,0 +1,39 @@
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: pycsw 2.0-dev\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2015-11-23 21:42+0800\n"
+"PO-Revision-Date: 2016-06-08 15:29+0800\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+"Last-Translator: \n"
+"Language-Team: \n"
+"Language: zh_CN\n"
+"X-Generator: Poedit 1.8.7\n"
+
+#: ../../sru.rst:4
+msgid "Search/Retrieval via URL (SRU) Support"
+msgstr "通过UR(SRU) 查找或取回"
+
+#: ../../sru.rst:6
+msgid ""
+"pycsw supports the `Search/Retrieval via URL`_ search protocol "
+"implementation as per subclause 8.4 of the OpenGIS Catalogue Service "
+"Implementation Specification."
+msgstr ""
+"pycsw支持 `Search/Retrieval via URL`_ 的搜索协议,参照的是OpenGIS目录服务实现规范的分条例8.4。"
+
+#: ../../sru.rst:8
+msgid ""
+"SRU support is enabled by default.  HTTP GET requests must be specified "
+"with ``mode=sru`` for SRU requests, e.g.:"
+msgstr ""
+"SRU支持默认情况下启用。 HTTP GET请求必须用 ``mode=sru`` 特化SRU要求,例如:"
+
+#: ../../sru.rst:14
+msgid ""
+"See http://www.loc.gov/standards/sru/simple.html for example SRU requests."
+msgstr "参见 http://www.loc.gov/standards/sru/simple.html SRU 请求的示例。"
diff --git a/docs/locale/zh/LC_MESSAGES/support.po b/docs/locale/zh/LC_MESSAGES/support.po
new file mode 100644
index 0000000..8d6d39c
--- /dev/null
+++ b/docs/locale/zh/LC_MESSAGES/support.po
@@ -0,0 +1,31 @@
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: pycsw 2.0-dev\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2015-11-23 21:42+0800\n"
+"PO-Revision-Date: 2016-06-08 15:39+0800\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+"Last-Translator: \n"
+"Language-Team: \n"
+"Language: zh_CN\n"
+"X-Generator: Poedit 1.8.7\n"
+
+#: ../../support.rst:4
+msgid "Support"
+msgstr "技术支持"
+
+#: ../../support.rst:7
+msgid "Community"
+msgstr "团队"
+
+#: ../../support.rst:9
+msgid ""
+"Please see the `Community </community.html>`_ page for information on the "
+"pycsw community, getting support, and how to get involved."
+msgstr ""
+"请参阅`Community </community.html>`_ 有关pycsw团队信息,有关于获取支持的内容,以"
+"及如何获取的内容。"
diff --git a/docs/locale/zh/LC_MESSAGES/testing.po b/docs/locale/zh/LC_MESSAGES/testing.po
new file mode 100644
index 0000000..3da8f87
--- /dev/null
+++ b/docs/locale/zh/LC_MESSAGES/testing.po
@@ -0,0 +1,248 @@
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: pycsw 2.0-dev\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2015-11-23 21:42+0800\n"
+"PO-Revision-Date: 2016-06-08 16:56+0800\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+"Last-Translator: \n"
+"Language-Team: \n"
+"Language: zh_CN\n"
+"X-Generator: Poedit 1.8.7\n"
+
+#: ../../testing.rst:4
+msgid "Testing"
+msgstr "测试"
+
+#: ../../testing.rst:9
+msgid "OGC CITE"
+msgstr "OGC引用"
+
+#: ../../testing.rst:11
+msgid ""
+"Compliance benchmarking is done via the OGC `Compliance & Interoperability "
+"Testing & Evaluation Initiative`_.  The pycsw `wiki <https://github.com/"
+"geopython/pycsw/wiki/OGC-CITE-Compliance>`_ documents testing procedures "
+"and status."
+msgstr ""
+"合规性基准是通过OGC `合规性和互操作性测试与自发性评估`_ 完成的。该pycsw维基"
+" `<https://github.com/geopython/pycsw/wiki/OGC-CITE-Compliance>`_ 文档测试程序和状态。"
+
+#: ../../testing.rst:16
+msgid "Tester"
+msgstr "测试仪"
+
+#: ../../testing.rst:18
+msgid ""
+"The pycsw tests framework (in ``tests``) is a collection of testsuites to "
+"perform automated regession testing of the codebase.  Test are run against "
+"all pushes to the GitHub repository via `Travis CI`_."
+msgstr ""
+"该pycsw测试框架(在 ``tests`` 里)是测试包的集合体,用来执行代码库的自动"
+"regession测试。通过 `Travis CI`_ ,测试在GitHub的库中运行。"
+
+#: ../../testing.rst:21
+msgid "Running Locally"
+msgstr "本地运行"
+
+#: ../../testing.rst:23
+msgid ""
+"The tests framework can be run from ``tests`` using `Paver`_ (see "
+"``pavement.py``) tasks for convenience:"
+msgstr ""
+"为方便工作,测试框架可以用 `Paver`_ (见 ``pavement.py``) 在 ``tests`` 中运行:"
+
+#: ../../testing.rst:35
+msgid ""
+"The tests perform HTTP GET and POST requests against ``http://"
+"localhost:8000``.  The expected output for each test can be found in "
+"``expected``.  Results are categorized as ``passed``, ``failed``, or "
+"``initialized``.  A summary of results is output at the end of the run."
+msgstr ""
+"针对 ``http://localhost:8000``,测试执行HTTP GET和POST请求。每个测试的输出都"
+"在``expected``中。结果被归类为``通过``,``失败``,或``初始化``。总结的结果会"
+"在运行结束时输出。"
+
+#: ../../testing.rst:38
+msgid "Failed Tests"
+msgstr "测试失败"
+
+#: ../../testing.rst:40
+msgid ""
+"If a given test has failed, the output is saved in ``results``.  The "
+"resulting failure can be analyzed by running ``diff tests/expected/"
+"name_of_test.xml tests/results/name_of_test.xml`` to find variances.  The "
+"Paver task returns a status code which indicates the number of tests which "
+"have failed (i.e. ``echo $?``)."
+msgstr ""
+"如果某个测试失败,输出将保存在``结果``中。 运行``diff tests/expected/"
+"name_of_test.xml tests/results/name_of_test.xml`` ,会自动统计失败结果以找到"
+"差异。Paver任务会返回一个状态代码,表示已失败的测试数目(即``echo $?``)。"
+
+#: ../../testing.rst:43
+msgid "Test Suites"
+msgstr "测试套件"
+
+#: ../../testing.rst:45
+msgid ""
+"The tests framework is run against a series of 'suites' (in ``tests/"
+"suites``), each of which specifies a given configuration to test various "
+"functionality of the codebase.  Each suite is structured as follows:"
+msgstr ""
+"测试框架将针对一系列“套件”(在``测试/ suites``)完成运行,其中每一项均指定一"
+"个给定的配置,以测试基本代码的各种功能。每个套件的结构如下:"
+
+#: ../../testing.rst:47
+msgid "``tests/suites/suite/default.cfg``: the configuration for the suite"
+msgstr "`tests/suites/suite/default.cfg`:对于该套件的配置"
+
+#: ../../testing.rst:48
+msgid ""
+"``tests/suites/suite/post``: directory of XML documents for HTTP POST "
+"requests"
+msgstr "`tests/suites/suite/post`:XML文档目录的HTTP POST请求"
+
+#: ../../testing.rst:49
+msgid ""
+"``tests/suites/suite/get/requests.txt``: directory and text file of KVP for "
+"HTTP GET requests"
+msgstr ""
+"`tests/suites/suite/get/requests.txt`:KVP的目录和文本文件,用于HTTP GET请求"
+
+#: ../../testing.rst:50
+msgid ""
+"``tests/suites/suite/data``: directory of sample XML data required for the "
+"test suite.  Database and test data are setup/loaded automatically as part "
+"of testing"
+msgstr ""
+"`tests/suites/suite/data`:测试套件所需样本的XML数据目录。作为测试的一部分,"
+"数据库和测试数据是自动设置或自动加载的"
+
+#: ../../testing.rst:52
+msgid "When the tests are invoked, the following operations are run:"
+msgstr "当测试被调用,将执行以下操作:"
+
+#: ../../testing.rst:54
+msgid "pycsw configuration is set to ``tests/suites/suite/default.cfg``"
+msgstr "pycsw配置设置为`tests/suites/suite/default.cfg`"
+
+#: ../../testing.rst:55
+msgid "HTTP POST requests are run against ``tests/suites/suite/post/*.xml``"
+msgstr "HTTP POST请求是针对 `tests/suites/suite/post/*.xml` 运行的"
+
+#: ../../testing.rst:56
+msgid ""
+"HTTP GET requests are run against each request in ``tests/suites/suite/get/"
+"requests.txt``"
+msgstr "HTTP GET请求是针对 ``tests/suites/suite/get/requests.txt`` 运行的"
+
+#: ../../testing.rst:58
+msgid ""
+"The CSV format of ``tests/suites/suite/get/requests.txt`` is ``testname,"
+"request``, with one line for each test.  The ``testname`` value is a unique "
+"test name (this value sets the name of the output file in the test "
+"results).  The ``request`` value is the HTTP GET request.  The "
+"``PYCSW_SERVER`` token is replaced at runtime with the URL to the pycsw "
+"install."
+msgstr ""
+"在每项测试的第一行中, `tests/suites/suite/get/requests.txt` 的CSV格式是 "
+" `testname,request` 。该 ``testname`` 值是唯一的测试名(此值设置在测试结果输出文"
+"件的名称内)。该 ``request`` 值是HTTP GET请求的值。该 ``PYCSW_SERVER`` 在URL "
+"pycsw安装运行时会被替换掉的。"
+
+#: ../../testing.rst:61
+msgid "Adding New Tests"
+msgstr "添加新测试"
+
+#: ../../testing.rst:63
+msgid "To add tests to an existing suite:"
+msgstr "在现有套件中添加测试:"
+
+#: ../../testing.rst:65
+msgid "for HTTP POST tests, add XML documents to ``tests/suites/suite/post``"
+msgstr "对于HTTP POST测试,在 ``tests/suites/suite/post`` 添加XML文档"
+
+#: ../../testing.rst:66
+msgid ""
+"for HTTP GET tests, add tests (one per line) to ``tests/suites/suite/get/"
+"requests.txt``"
+msgstr ""
+"对于HTTP GET测试,在 ``tests/suites/suite/get/requests.txt`` 中添加测试(每行的第一项)"
+
+#: ../../testing.rst:67
+msgid "run ``paver test``"
+msgstr "运行`paver test`"
+
+#: ../../testing.rst:69
+msgid "To add a new test suite:"
+msgstr "添加新的测试套件:"
+
+#: ../../testing.rst:71
+msgid "create a new directory under ``tests/suites`` (e.g. ``foo``)"
+msgstr "在 ``tests/suites`` (如 ``foo`` )下创建一个新目录"
+
+#: ../../testing.rst:72
+msgid "create a new configuration in ``tests/suites/foo/default.cfg``"
+msgstr "在 ``tests/suites/foo/default.cfg`` 创建一个新的配置"
+
+#: ../../testing.rst:74
+msgid "Ensure that all file paths are relative to ``path/to/pycsw``"
+msgstr "确保所有文件的路径都关联 ``path/to/pycsw`` "
+
+#: ../../testing.rst:75
+msgid ""
+"Ensure that ``repository.database`` points to an SQLite3 database called "
+"``tests/suites/foo/data/records.db``.  The database *must* be called "
+"``records.db`` and the directory ``tests/suites/foo/data`` *must* exist"
+msgstr ""
+"确保 ``repository.database`` 指定于 ``tests/suites/foo/data/records.db`` 的一个"
+"sqlite3数据库。该数据库*必须*被写为 ``records.db``,目录 ``tests/suites/foo/data`` "
+"也必须存在"
+
+#: ../../testing.rst:77
+msgid "populate HTTP POST requests in ``tests/suites/foo/post``"
+msgstr "将HTTP POST请求移到 ``tests/suites/foo/post`` "
+
+#: ../../testing.rst:78
+msgid "populate HTTP GET requests in ``tests/suites/foo/get/requests.txt``"
+msgstr "将HTTP GET请求移到 ``tests/suites/foo/get/requests.txt`` "
+
+#: ../../testing.rst:79
+msgid ""
+"if the testsuite requires test data, create ``tests/suites/foo/data`` are "
+"store XML file there"
+msgstr ""
+"如果需要测试组件的测试数据,创建 ``tests/suites/foo/data``,以存储XML文件"
+
+#: ../../testing.rst:80
+msgid ""
+"run ``paver test`` (or ``paver test -s foo`` to test only the new test "
+"suite)"
+msgstr "运行 ``paver test`` (或 ``paver test-s foo`` , 仅用来测试新的测试套件)"
+
+#: ../../testing.rst:82
+msgid ""
+"The new test suite database will be created automatically and used as part "
+"of tests."
+msgstr "新的测试套件数据库将自动创建,并且会成为测试的一部分。"
+
+#: ../../testing.rst:85
+msgid "Web Testing"
+msgstr "Web测试"
+
+#: ../../testing.rst:87
+msgid ""
+"You can also use the pycsw tests via your web browser to perform sample "
+"requests against your pycsw install.  The tests are is located in ``tests/"
+"``.  To generate the HTML page:"
+msgstr ""
+"您还可以通过Web浏览器使用pycsw测试,来执行你的pycsw安装样例申请。这些测试在"
+"``tests/`` 中。生成HTML页面:"
+
+#: ../../testing.rst:93
+msgid "Then navigate to ``http://host/path/to/pycsw/tests/index.html``."
+msgstr "然后导航到 ``http://host/path/to/pycsw/tests/index.html`` 。"
diff --git a/docs/locale/zh/LC_MESSAGES/tools.po b/docs/locale/zh/LC_MESSAGES/tools.po
new file mode 100644
index 0000000..567be86
--- /dev/null
+++ b/docs/locale/zh/LC_MESSAGES/tools.po
@@ -0,0 +1,91 @@
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: pycsw 2.0-dev\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2016-07-21 19:51+0800\n"
+"PO-Revision-Date: 2016-06-08 15:43+0800\n"
+"Last-Translator: \n"
+"Language-Team: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 2.3.4\n"
+
+#: ../../tools.rst:4
+msgid "Cataloguing and Metadata Tools"
+msgstr "编目和元数据工具"
+
+#: ../../tools.rst:7
+msgid "CSW Clients"
+msgstr "CSW客户端"
+
+#: ../../tools.rst:9
+msgid ""
+"`Geoportal CSW Clients "
+"<http://sourceforge.net/apps/mediawiki/geoportal/index.php?title=Geoportal_CSW_Clients>`_"
+msgstr ""
+"`Geoportal CSW客户端 "
+"<http://sourceforge.net/apps/mediawiki/geoportal/index.php?title=Geoportal_CSW_Clients>`_"
+
+#: ../../tools.rst:10
+#, fuzzy
+msgid "`OWSLib <http://geopython.github.io/OWSLib>`_"
+msgstr "OWSLib <http://geopython.github.io/OWSLib>"
+
+#: ../../tools.rst:11
+msgid ""
+"`MetaSearch <https://hub.qgis.org/wiki/quantum-gis/MetaSearch>`_ (`QGIS "
+"<http://qgis.org/>`_ plugin)"
+msgstr ""
+" `联合检索<https://hub.qgis.org/wiki/quantum-gis/MetaSearch>`_ (`QGIS "
+"<http://qgis.org/>`_ 插件)"
+
+#: ../../tools.rst:14
+msgid "CSW Servers"
+msgstr "CSW服务器"
+
+#: ../../tools.rst:16
+msgid "`deegree <http://deegree.org/>`_"
+msgstr "`deegree <http://deegree.org/>`_"
+
+#: ../../tools.rst:17
+msgid "`eXcat <http://gdsc.nlr.nl/gdsc/en/tools/excat>`_"
+msgstr "`eXcat <http://gdsc.nlr.nl/gdsc/en/tools/excat>`_"
+
+#: ../../tools.rst:18
+msgid "`GeoNetwork opensource <http://geonetwork-opensource.org/>`_"
+msgstr "`开源地理 <http://geonetwork-opensource.org/>`_"
+
+#: ../../tools.rst:21
+msgid "Metadata Editing Tools"
+msgstr "元数据编辑工具"
+
+#: ../../tools.rst:23
+msgid "`CatMDEdit <http://catmdedit.sourceforge.net/>`_"
+msgstr "`CatMDEdit <http://catmdedit.sourceforge.net/>`_"
+
+#: ../../tools.rst:24
+msgid "`EUOSME <https://joinup.ec.europa.eu/software/euosme/description>`_"
+msgstr "`EUOSME <https://joinup.ec.europa.eu/software/euosme/description>`_"
+
+#: ../../tools.rst:25
+msgid "`GIMED <http://sourceforge.net/projects/gimed/>`_"
+msgstr "`GIMED <http://sourceforge.net/projects/gimed/>`_"
+
+#: ../../tools.rst:26
+msgid ""
+"`Metatools <http://hub.qgis.org/projects/metatools>`_ (`QGIS "
+"<http://qgis.org/>`_ plugin)"
+msgstr ""
+"`Metatools <http://hub.qgis.org/projects/metatools>`_ (`QGIS "
+"<http://qgis.org/>`_ plugin)"
+
+#: ../../tools.rst:27
+msgid ""
+"`QSphere <http://hub.qgis.org/plugins/qsphere>`_ (`QGIS "
+"<http://qgis.org/>`_ plugin)"
+msgstr ""
+"`QSphere <http://hub.qgis.org/plugins/qsphere>`_ (`QGIS "
+"<http://qgis.org/>`_ plugin)"
+
diff --git a/docs/locale/zh/LC_MESSAGES/transactions.po b/docs/locale/zh/LC_MESSAGES/transactions.po
new file mode 100644
index 0000000..0f14610
--- /dev/null
+++ b/docs/locale/zh/LC_MESSAGES/transactions.po
@@ -0,0 +1,274 @@
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: pycsw 2.0-dev\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2016-12-17 17:33+0800\n"
+"PO-Revision-Date: 2016-06-08 16:20+0800\n"
+"Last-Translator: \n"
+"Language-Team: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 2.3.4\n"
+
+#: ../../transactions.rst:4 ../../transactions.rst:67
+msgid "Transactions"
+msgstr "订单"
+
+#: ../../transactions.rst:6
+msgid ""
+"pycsw has the ability to process CSW Harvest and Transaction requests "
+"(CSW-T).  Transactions are disabled by default; to enable, "
+"``manager.transactions`` must be set to ``true``.  Access to "
+"transactional functionality is limited to IP addresses which must be set "
+"in ``manager.allowed_ips``."
+msgstr "pycsw可获取CSW和交易请求(CSW-T)。交易在默认情况下是禁用的;``manager.transactions``必须设置为值``是``。进入交易后,功能仅可以设置IP地址,IP地址必须在``manager.allowed_ips``中。"
+
+#: ../../transactions.rst:9
+msgid "Supported Resource Types"
+msgstr "支持的源类型"
+
+#: ../../transactions.rst:11
+msgid ""
+"For transactions and harvesting, pycsw supports the following metadata "
+"resource types by default:"
+msgstr "对于交易和获限,pycsw默认支持以下元数据源类型:"
+
+#: ../../transactions.rst:1
+msgid "Resource Type"
+msgstr "源类型"
+
+#: ../../transactions.rst:1
+msgid "Namespace"
+msgstr "空间名称"
+
+#: ../../transactions.rst:1
+msgid "Transaction"
+msgstr "订单"
+
+#: ../../transactions.rst:1
+msgid "Harvest"
+msgstr "获取"
+
+#: ../../transactions.rst:1
+msgid "Dublin Core"
+msgstr "Dublin Core"
+
+#: ../../transactions.rst:1
+msgid "``http://www.opengis.net/cat/csw/2.0.2``"
+msgstr "``http://www.opengis.net/cat/csw/2.0.2``"
+
+#: ../../transactions.rst:1
+msgid "yes"
+msgstr "是"
+
+#: ../../transactions.rst:1
+msgid "FGDC"
+msgstr "FGDC"
+
+#: ../../transactions.rst:1
+msgid "``http://www.opengis.net/cat/csw/csdgm``"
+msgstr "``http://www.opengis.net/cat/csw/csdgm``"
+
+#: ../../transactions.rst:1
+msgid "GM03"
+msgstr "GM03"
+
+#: ../../transactions.rst:1
+msgid "``http://www.interlis.ch/INTERLIS2.3``"
+msgstr "``http://www.interlis.ch/INTERLIS2.3``"
+
+#: ../../transactions.rst:1
+msgid "ISO 19139"
+msgstr "ISO 19139"
+
+#: ../../transactions.rst:1
+msgid "``http://www.isotc211.org/2005/gmd``"
+msgstr "``http://www.isotc211.org/2005/gmd``"
+
+#: ../../transactions.rst:1
+msgid "ISO GMI"
+msgstr "ISO GMI"
+
+#: ../../transactions.rst:1
+msgid "``http://www.isotc211.org/2005/gmi``"
+msgstr "``http://www.isotc211.org/2005/gmi``"
+
+#: ../../transactions.rst:1
+msgid "OGC:CSW 2.0.2"
+msgstr "OGC:CSW 2.0.2"
+
+#: ../../transactions.rst:1
+msgid "OGC:WMS 1.1.1/1.3.0"
+msgstr ""
+
+#: ../../transactions.rst:1
+msgid "``http://www.opengis.net/wms``"
+msgstr "``http://www.opengis.net/wms``"
+
+#: ../../transactions.rst:1
+msgid "OGC:WMTS 1.0.0"
+msgstr "OGC:WMTS 1.0.0"
+
+#: ../../transactions.rst:1
+msgid "``http://www.opengis.net/wmts/1.0``"
+msgstr "``http://www.opengis.net/wmts/1.0``"
+
+#: ../../transactions.rst:1
+msgid "OGC:WFS 1.0.0/1.1.0/2.0.0"
+msgstr ""
+
+#: ../../transactions.rst:1
+msgid "``http://www.opengis.net/wfs``"
+msgstr "``http://www.opengis.net/wfs``"
+
+#: ../../transactions.rst:1
+msgid "OGC:WCS 1.0.0"
+msgstr "OGC:WCS 1.0.0"
+
+#: ../../transactions.rst:1
+msgid "``http://www.opengis.net/wcs``"
+msgstr "``http://www.opengis.net/wcs``"
+
+#: ../../transactions.rst:1
+msgid "OGC:WPS 1.0.0"
+msgstr "OGC:WPS 1.0.0"
+
+#: ../../transactions.rst:1
+msgid "``http://www.opengis.net/wps/1.0.0``"
+msgstr "``http://www.opengis.net/wps/1.0.0``"
+
+#: ../../transactions.rst:1
+msgid "OGC:SOS 1.0.0"
+msgstr "OGC:SOS 1.0.0"
+
+#: ../../transactions.rst:1
+msgid "``http://www.opengis.net/sos/1.0``"
+msgstr "``http://www.opengis.net/sos/1.0``"
+
+#: ../../transactions.rst:1
+msgid "OGC:SOS 2.0.0"
+msgstr "OGC:SOS 2.0.0"
+
+#: ../../transactions.rst:1
+msgid "``http://www.opengis.net/sos/2.0``"
+msgstr "``http://www.opengis.net/sos/2.0``"
+
+#: ../../transactions.rst:1
+msgid "`WAF`_"
+msgstr "`WAF`_"
+
+#: ../../transactions.rst:1
+msgid "``urn:geoss:urn``"
+msgstr "``urn:geoss:urn``"
+
+#: ../../transactions.rst:31
+msgid ""
+"Additional metadata models are supported by enabling the appropriate "
+":ref:`profiles`."
+msgstr "其它元数据模型,请参考 :ref:`profiles` 。"
+
+#: ../../transactions.rst:35
+msgid ""
+"For transactions to be functional when using SQLite3, the SQLite3 "
+"database file (**and its parent directory**) must be fully writable.  For"
+" example:"
+msgstr "当使用sqlite3时,sqlite3的数据库文件(及其母目录)一定得完整可写的。例如:"
+
+#: ../../transactions.rst:44
+msgid ""
+"For CSW-T deployments, it is strongly advised that this directory reside "
+"in an area that is not accessible by HTTP."
+msgstr "对于CSW-T部署,强烈建议在此目录驻留一定区域,此区域是HTTP访问不到的。"
+
+#: ../../transactions.rst:47
+msgid "Harvesting"
+msgstr "获取"
+
+#: ../../transactions.rst:51
+msgid ""
+"Your server must be able to make outgoing HTTP requests for this "
+"functionality."
+msgstr "你的服务器必须能够使此功能传出HTTP请求。"
+
+#: ../../transactions.rst:53
+msgid ""
+"pycsw supports the CSW-T ``Harvest`` operation.  Records which are "
+"harvested require to setup a cronjob to periodically refresh records in "
+"the local repository.  A sample cronjob is available in ``etc/harvest-"
+"all.cron`` which points to ``pycsw-admin.py`` (you must specify the "
+"correct path to your configuration).  Harvest operation results can be "
+"sent by email (via ``mailto:``) or ftp (via ``ftp://``) if the Harvest "
+"request specifies ``csw:ResponseHandler``."
+msgstr ""
+"pycsw支持CSW-T ``Harvest`` 操作。获取的记录需要设置一个cronjob来定期刷新本地数据库记录。在 ``etc"
+"/harvest-all.cron`` 中,样本cronjob是可以利用到的,此样本cronjob指向 ``pycsw-admin.py`` "
+"(必须指定一个配置的正确路径)。如果获取请求指定为 ``CSW:ResponseHandler`` ,其获取的结果会由电子邮件(通过 "
+"``mailto`` )或是ftp(通过``FTP://`` )发送,"
+
+#: ../../transactions.rst:57
+msgid ""
+"For ``csw:ResponseHandler`` values using the ``mailto:`` protocol, you "
+"must have ``server.smtp_host`` set in your :ref:`configuration "
+"<configuration>`."
+msgstr ""
+"对于使用 ``mailto:`` 协议的 ``csw:ResponseHandler`` 值,你必须在你的 :ref:`configuration"
+" <configuration>` 设定 ``server.smtp_host`` "
+
+#: ../../transactions.rst:60
+msgid "OGC Web Services"
+msgstr "OGC Web服务"
+
+#: ../../transactions.rst:62
+msgid ""
+"When harvesting OGC web services, requests can provide the base URL of "
+"the service as part of the Harvest request.  pycsw will construct a "
+"``GetCapabilities`` request dynamically."
+msgstr "当获取OGC Web服务时,可以请求提供服务的基本URL作为获取的一部分。 pycsw将动态地创建``GetCapabilities``请求。"
+
+#: ../../transactions.rst:64
+msgid ""
+"When harvesting other CSW servers, pycsw pages through the entire CSW in "
+"default increments of 10.  This value can be modified via the "
+"``manager.csw_harvest_pagesize`` :ref:`configuration <configuration>` "
+"option.  It is strongly advised to use the ``csw:ResponseHandler`` "
+"parameter for harvesting large CSW catalogues to prevent HTTP timeouts."
+msgstr ""
+"当获取其它CSW服务器时,pycsw页面就默认在10这个值上。可以在 ``manager.csw_harvest_pagesize`` "
+"程序中将此值修改,请参照 :ref:`configuration <configuration>` 选项。强烈建议使用 "
+"``CSW:ResponseHandler`` 参数为收获大的CSW目录,以防止HTTP超时。"
+
+#: ../../transactions.rst:69
+msgid ""
+"pycsw supports 3 modes of the ``Transaction`` operation (``Insert``, "
+"``Update``, ``Delete``):"
+msgstr "pycsw支持 ``Transaction`` 操作( ``Insert`` , ``Update`` , ``Delete`` )的3种模式:"
+
+#: ../../transactions.rst:71
+msgid "**Insert**: full XML documents can be inserted as per CSW-T"
+msgstr "**Insert**:完整的XML文档可以用CSW-T插入"
+
+#: ../../transactions.rst:72
+msgid ""
+"**Update**: updates can be made as full record updates or record "
+"properties against a ``csw:Constraint``"
+msgstr "**Update**:针对``CSW:Constraint``,可做到完整记录的更新与记录属性的更新"
+
+#: ../../transactions.rst:73
+msgid "**Delete**: deletes can be made against a ``csw:Constraint``"
+msgstr "删除:针对``CSW:Constraint``进行删除"
+
+#: ../../transactions.rst:75
+msgid ""
+"Transaction operation results can be sent by email (via ``mailto:``) or "
+"ftp (via ``ftp://``) if the Transaction request specifies "
+"``csw:ResponseHandler``."
+msgstr ""
+"若交易请求指定于``csw:ResponseHandler``,可通过email ( ``mailto:``) "
+"或ftp(``FTP://``)发送交易操作的结果"
+
+#: ../../transactions.rst:77
+msgid "The :ref:`tests` contain CSW-T request examples."
+msgstr "参考: :ref:`tests` ,包含有CSW-T 请求示例。"
+
diff --git a/docs/odc.rst b/docs/odc.rst
index 73757aa..961b8ca 100644
--- a/docs/odc.rst
+++ b/docs/odc.rst
@@ -12,4 +12,6 @@ Open Data Catalog Setup
 
 Open Data Catalog provides CSW functionality using pycsw out of the box (installing ODC will also install pycsw).  Settings are defined in https://github.com/azavea/Open-Data-Catalog/blob/master/OpenDataCatalog/settings.py#L165.
 
+ODC settings must ensure that ``REGISTRY_PYCSW['repository']['source']`` is set to``hypermap.search.pycsw_repository``.
+
 At this point, pycsw is able to read from the Open Data Catalog repository using the Django ORM.
diff --git a/docs/repositories.rst b/docs/repositories.rst
new file mode 100644
index 0000000..f72f3a2
--- /dev/null
+++ b/docs/repositories.rst
@@ -0,0 +1,32 @@
+.. _repositories:
+
+Repository Plugins
+==================
+
+Overview
+--------
+
+pycsw allows for the implementation of custom repositories in order to connect to a backend different from the pycsw's default.  This is especially useful when downstream applications manage their own metadata model/database/document store and want pycsw to connect to it directly instead of using pycsw's default model, thus creating duplicate repositories which then require syncronization/accounting.  Repository plugins enable a single metadata backend which is independent from the pycsw [...]
+
+All outputschemas must be placed in the ``pycsw/plugins/outputschemas`` directory.
+
+Requirements
+------------
+
+Repository plugins:
+
+- can be developed and referenced / connected external to pycsw
+- must be accessible within the ``PYTHONPATH`` of a given application
+- must implement pycsw's ``pycsw.core.repository.Repository`` properties and methods
+- must be specified in the pycsw :ref:`configuration` as a class reference (e.g. ``path.to.repo_plugin.MyRepository``)
+- must minimally implement the ``query_insert``, ``query_domain``, ``query_ids``, and ``query`` methods
+
+Configuration
+-------------
+
+- set pycsw's ``repository.source`` setting to the class which implements the custom repository:
+
+.. code-block:: none
+
+  [repository]
+  mappings='path.to.repo_plugin.MyRepository'
diff --git a/docs/requirements-mocked.txt b/docs/requirements-mocked.txt
new file mode 100644
index 0000000..b9a294f
--- /dev/null
+++ b/docs/requirements-mocked.txt
@@ -0,0 +1,5 @@
+# This file holds some fake requirements to fool the readthedocs service into
+# building the documentation. For more information, see
+# https://github.com/geopython/pycsw/issues/521
+mock
+sphinx
diff --git a/docs/testing.rst b/docs/testing.rst
index 8729e8a..1109802 100644
--- a/docs/testing.rst
+++ b/docs/testing.rst
@@ -1,92 +1,340 @@
-.. _testing:
+.. _tests:
 
 Testing
 =======
 
+Pycsw uses `pytest`_ for managing its automated tests. There are a number of
+test suites that perform mostly functional testing. These tests ensure that
+pycsw is compliant with the various supported standards.
+There is also a growing set of unit tests. These focus on smaller scope 
+testing, in order to verify that individual bits of code are working as
+expected.
+
+Tests can be run locally as part of the development cycle. They are also
+run on pycsw's `Travis`_ continuous integration server against all pushes and
+pull requests to the code repository.
+
+
 .. _ogc-cite:
 
 OGC CITE
 --------
 
-Compliance benchmarking is done via the OGC `Compliance & Interoperability Testing & Evaluation Initiative`_.  The pycsw `wiki <https://github.com/geopython/pycsw/wiki/OGC-CITE-Compliance>`_ documents testing procedures and status.
+In addition to pycsw's own tests, all public releases are also tested via the
+OGC `Compliance & Interoperability Testing & Evaluation Initiative`_ (CITE).
+The pycsw `wiki`_ documents CITE testing procedures and status.
 
-.. _tests:
 
-Tester
-------
+Functional test suites
+----------------------
 
-The pycsw tests framework (in ``tests``) is a collection of testsuites to perform automated regession testing of the codebase.  Test are run against all pushes to the GitHub repository via `Travis CI`_.
+Currently most of pycsw's tests are `functional tests`_. This means that
+each test case is based on the requirements mandated by the specifications of
+the various standards that pycsw implements. These tests focus on making sure
+that pycsw works as expected.
 
-Running Locally
-^^^^^^^^^^^^^^^
+Each test follows the same workflow:
 
-The tests framework can be run from ``tests`` using `Paver`_ (see ``pavement.py``) tasks for convenience:
+* Create a new pycsw instance with a custom configuration and data repository
+  for each suite of tests;
 
-.. code-block:: bash
+* Perform a series of GET and POST requests to the running pycsw instance;
 
-  $ cd /path/to/pycsw
-  # run all tests (starts up http://localhost:8000)
-  $ paver test
-  # run tests only against specific testsuites 
-  $ paver test -s apiso,fgdc
-  # run all tests, including harvesting (this is turned off by default given the volatility of remote services/data testing)
-  $ paver test -r
-  # run all tests with 1000ms time benchmark
-  $ paver test -t 1000
+* Compare the results of each request against a previously prepared expected
+  result. If the test result matches the expected outcome the test passes,
+  otherwise it fails.
 
-The tests perform HTTP GET and POST requests against ``http://localhost:8000``.  The expected output for each test can be found in ``expected``.  Results are categorized as ``passed``, ``failed``, or ``initialized``.  A summary of results is output at the end of the run.
 
-Failed Tests
-^^^^^^^^^^^^
+A number of different test suites exist under ``tests/functionaltests/suites``.
+Each suite specifies the following structure:
 
-If a given test has failed, the output is saved in ``results``.  The resulting failure can be analyzed by running ``diff tests/expected/name_of_test.xml tests/results/name_of_test.xml`` to find variances.  The Paver task returns a status code which indicates the number of tests which have failed (i.e. ``echo $?``).
+* A mandatory ``default.cfg`` file with the pycsw configuration that must be
+  used by the test suite;
 
-Test Suites
-^^^^^^^^^^^
+* A mandatory ``expected/`` directory containing the expected results for each
+  request;
+
+* An optional ``data/`` directory that contains ``.xml`` files with testing
+  data that is to be loaded into the suite's database before running the tests.
+  The presence of this directory and its contents have the following meaning
+  for tests:
+
+  * If ``data/`` directory is present and contains files, they will be loaded
+    into a new database for running the tests of the suite;
+
+  * If ``data/`` directory is present and does not contain any data files, a
+    new empty database is used in the tests;
+
+  * If ``data/`` directory is absent, the suite will use a database populated
+    with test data from the ``CITE`` suite.
+
+* An optional ``get/requests.txt`` file that holds request parameters used for
+  making HTTP GET requests.
 
-The tests framework is run against a series of 'suites' (in ``tests/suites``), each of which specifies a given configuration to test various functionality of the codebase.  Each suite is structured as follows:
+  Each line in the file must be formatted with the following scheme:
 
-* ``tests/suites/suite/default.cfg``: the configuration for the suite
-* ``tests/suites/suite/post``: directory of XML documents for HTTP POST requests
-* ``tests/suites/suite/get/requests.txt``: directory and text file of KVP for HTTP GET requests
-* ``tests/suites/suite/data``: directory of sample XML data required for the test suite.  Database and test data are setup/loaded automatically as part of testing
+      test_id,request_query_string
 
-When the tests are invoked, the following operations are run:
+  For example:
 
-* pycsw configuration is set to ``tests/suites/suite/default.cfg``
-* HTTP POST requests are run against ``tests/suites/suite/post/*.xml``
-* HTTP GET requests are run against each request in ``tests/suites/suite/get/requests.txt``
+    TestGetCapabilities,service=CSW&version=2.0.2&request=GetCapabilities
+
+  When tests are run, the *test_id* is used for naming each test and for
+  finding the expected result.
+
+* An optional ``post/`` directory that holds ``.xml`` files used for making
+  HTTP POST requests
+
+
+Test identifiers
+^^^^^^^^^^^^^^^^
+
+Each test has an identifier that is built using the following rule:
+
+    <test_function>[<suite_name>_<http_method>_<test_name>]
+
+For example:
+
+    test_suites[default_post_GetRecords-end]
+
+
+Functional tests' implementation
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Functional tests are generated for each suite directory present under 
+`tests/functionaltests/suites`. Test generation uses pytest's 
+`pytest_generate_tests`_ function. This function is implemented in 
+`tests/functionaltests/conftest.py`. It provides an automatic parametrization 
+of the `tests/functionaltests/test_suites_functional:test_suites` function. 
+This parametrization causes the generation of a test for each of the GET and 
+POST requests defined in a suite's directory.
 
-The CSV format of ``tests/suites/suite/get/requests.txt`` is ``testname,request``, with one line for each test.  The ``testname`` value is a unique test name (this value sets the name of the output file in the test results).  The ``request`` value is the HTTP GET request.  The ``PYCSW_SERVER`` token is replaced at runtime with the URL to the pycsw install.
 
 Adding New Tests
 ^^^^^^^^^^^^^^^^
 
 To add tests to an existing suite:
 
-* for HTTP POST tests, add XML documents to ``tests/suites/suite/post``
-* for HTTP GET tests, add tests (one per line) to ``tests/suites/suite/get/requests.txt``
-* run ``paver test``
+* for HTTP POST tests, add XML documents to 
+  ``tests/functionaltests/suites/<suite>/post``
+* for HTTP GET tests, add tests (one per line) to
+  ``tests/functionaltests/suites/<suite>/get/requests.txt``
 
 To add a new test suite:
 
-* create a new directory under ``tests/suites`` (e.g. ``foo``)
-* create a new configuration in ``tests/suites/foo/default.cfg``
+* Create a new directory under ``tests/functionaltests/suites`` (e.g. ``foo``)
+* Create a new configuration in ``tests/suites/foo/default.cfg``
+* Populate HTTP POST requests in ``tests/suites/foo/post``
+* Populate HTTP GET requests in ``tests/suites/foo/get/requests.txt``
+* If the test suite requires test data, create ``tests/suites/foo/data`` and
+  store XML files there. These will be inserted in the test catalogue at test
+  runtime
+* Use pytest or tox as described above in order to run the tests
+
+The new test suite database will be created automatically and used as part of
+tests.
+
+
+Unit tests
+----------
+
+pycsw also features unit tests. These deal with testing the expected behaviour
+of individual functions.
+
+The usual implementation of unit tests is to import the function/method under
+test, run it with a set of known arguments and assert that the result matches
+the expected outcome.
+
+Unit tests are defined in `pycsw/tests/unittests/<module_name>`.
+
+pycsw's unit tests are marked with the `unit` marker. This makes it easy to run
+them in isolation:
+
+.. code:: bash
+
+   # running only the unit tests (not the functional ones)
+   py.test -m unit
+
+
+
+Running tests
+-------------
+
+Since pycsw uses `pytest`_, tests are run with the ``py.test`` runner. A basic
+test run can be made with:
+
+.. code:: bash
+
+   py.test
+
+This command will run all tests and report on the number of successes, failures
+and also the time it took to run them. The `py.test` command accepts several
+additional parameters that can be used in order to customize the execution of
+tests. Look into `pytest's invocation documentation`_ for a more complete
+description. You can also get a description of the available parameters by
+running:
+
+.. code:: bash
+
+   py.test --help
+
+
+Running specific suites and test cases
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+py.test allows tagging tests with markers. These can be used to selectively run
+some tests. pycsw uses two markers:
+
+* ``unit`` - run only inut tests
+* ``functional``- run onyl functional tests
+
+Markers can be specified by using the ``-m <marker_name>`` flag.
+
+.. code:: bash
+
+   py.test -m functional  # run only functional tests
+
+You can also use the ``-k <name_expression>`` flag to select which tests to run. Since each
+test's name includes the suite name, http method and an identifier for the
+test, it is easy to run only certain tests.
+
+.. code:: bash
 
-  * Ensure that all file paths are relative to ``path/to/pycsw``
-  * Ensure that ``repository.database`` points to an SQLite3 database called ``tests/suites/foo/data/records.db``.  The database *must* be called ``records.db`` and the directory ``tests/suites/foo/data`` *must* exist
+   py.test -k "apiso and GetRecords"  # run only tests from the apiso suite that have GetRecords in their name
+   py.test -k "post and GetRecords"  # run only tests that use HTTP POST and GetRecords in their name
+   py.test -k "not harvesting"  # run all tests except those from the harvesting suite
 
-* populate HTTP POST requests in ``tests/suites/foo/post``
-* populate HTTP GET requests in ``tests/suites/foo/get/requests.txt``
-* if the testsuite requires test data, create ``tests/suites/foo/data`` are store XML file there
-* run ``paver test`` (or ``paver test -s foo`` to test only the new test suite)
 
-The new test suite database will be created automatically and used as part of tests.
+The ``-m`` and ``-k`` flags can be combined.
+
+
+Exiting fast
+^^^^^^^^^^^^
+
+The ``--exitfirst`` (or ``-x``) flag can be used to stop the test runner
+immediately as soon as a test case fails.
+
+.. code:: bash
+
+   py.test --exitfirst
+
+
+Seeing more output
+^^^^^^^^^^^^^^^^^^
+
+There are three main ways to get more output from running tests:
+
+* The ``--verbose`` (or ``-v``) flag;
+
+* The ``--capture=no`` flag - Messages sent to stdout by a test are not
+  suppressed;
+
+* The ``--pycsw-loglevel`` flag - Sets the log level of the pycsw instance
+  under test. Set this value to ``debug`` in order to see all debug messages
+  sent by pycsw while processing a request.
+
+
+.. code:: bash
+
+   py.test --verbose
+   py.test --pycsw-loglevel=debug
+   py.test -v --capture=no --pycsw-loglevel=debug
+
+
+Comparing results with difflib instead of XML c14n
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The functional tests compare results with their expected values by using
+[XML canonicalisation - XML c14n](https://www.w3.org/TR/xml-c14n/).
+Alternatively, you can call py.test with the ``--functional-prefer-diffs``
+flag. This will enable comparison based on Python's ``difflib``. Comparison
+is made on a line-by-line basis and in case of failure, a unified diff will
+be printed to standard output.
+
+.. code:: bash
+
+   py.test -m functional -k 'harvesting' --functional-prefer-diffs
+
+
+Saving test results for disk
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The result of each functional test can be saved to disk by using the
+``--functional-save-results-directory`` option. Each result file is named
+after the test identifier it has when running with pytest.
+
+.. code:: bash
+
+   py.test -m functional -k 'not harvesting' --functional-save-results-directory=/tmp/pycsw-test-results
+
+
+
+Test coverage
+^^^^^^^^^^^^^
+
+Use the `--cov pycsw` flag in order to see information on code coverage. It is
+possible to get output in a variety of formats.
+
+.. code:: bash
+
+   py.test --cov pycsw
+
+
+Specifying a timeout for tests
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The `--timeout <seconds>` option can be used to specify that if a test takes
+more than `<seconds>` to run it is considered to have failed. Seconds can be
+a float, so it is possibe to specify sub-second timeouts
+
+.. code:: bash
+
+   py.test --timeout=1.5
+
+
+Linting with flake8
+^^^^^^^^^^^^^^^^^^^
+
+Use the `--flake8` flag to also check if the code complies with Python's style
+guide
+
+.. code:: bash
+
+   py.test --flake8
+
+
+Testing multiple Python versions
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+For testing multiple Python versions and configurations simultaneously you can
+use `tox`_. pycsw includes a `tox.ini` file with a suitable configuration. It
+can be used to run tests against multiple Python versions and also multiple
+database backends. When running `tox` you can send arguments to the `py.test`
+runner by using the invocation `tox <tox arguments> -- <py.test arguments>`.
+Examples:
+
+.. code:: bash
+
+   # install tox on your system
+   sudo pip install tox
+
+   # run all tests on multiple Python versions against all databases,
+   # with default arguments
+   tox
+
+   # run tests only with python2.7 and using sqlite as backend
+   tox -e py27-sqlite
+
+   # run only csw30 suite tests with python3.5 and postgresql as backend
+   tox -e py35-postgresql -- -k 'csw30'
+
 
 Web Testing
 ^^^^^^^^^^^
 
-You can also use the pycsw tests via your web browser to perform sample requests against your pycsw install.  The tests are is located in ``tests/``.  To generate the HTML page:
+You can also use the pycsw tests via your web browser to perform sample
+requests against your pycsw install.  The tests are is located in
+``tests/``.  To generate the HTML page:
 
 .. code-block:: bash
 
@@ -94,6 +342,14 @@ You can also use the pycsw tests via your web browser to perform sample requests
 
 Then navigate to ``http://host/path/to/pycsw/tests/index.html``.
 
-.. _`Compliance & Interoperability Testing & Evaluation Initiative`: http://cite.opengeospatial.org/
-.. _`Travis CI`: http://travis-ci.org/geopython/pycsw
+
+
+.. _Compliance & Interoperability Testing & Evaluation Initiative: http://cite.opengeospatial.org/
+.. _functional tests: https://en.wikipedia.org/wiki/Functional_testing
 .. _`Paver`: http://paver.github.io/paver/
+.. _pytest's invocation documentation: http://docs.pytest.org/en/latest/usage.html
+.. _pytest: http://pytest.org/latest/
+.. _Travis: http://travis-ci.org/geopython/pycsw
+.. _tox: https://tox.readthedocs.io
+.. _wiki: https://github.com/geopython/pycsw/wiki/OGC-CITE-Compliance
+.. _pytest_generate_tests: http://docs.pytest.org/en/latest/parametrize.html#basic-pytest-generate-tests-example
diff --git a/docs/transactions.rst b/docs/transactions.rst
index 1eb47da..97aab78 100644
--- a/docs/transactions.rst
+++ b/docs/transactions.rst
@@ -19,9 +19,9 @@ For transactions and harvesting, pycsw supports the following metadata resource
   ISO 19139,``http://www.isotc211.org/2005/gmd``,yes,yes
   ISO GMI,``http://www.isotc211.org/2005/gmi``,yes,yes
   OGC:CSW 2.0.2,``http://www.opengis.net/cat/csw/2.0.2``,,yes
-  OGC:WMS 1.1.1,``http://www.opengis.net/wms``,,yes
+  OGC:WMS 1.1.1/1.3.0,``http://www.opengis.net/wms``,,yes
   OGC:WMTS 1.0.0,``http://www.opengis.net/wmts/1.0``,,yes
-  OGC:WFS 1.1.0,``http://www.opengis.net/wfs``,,yes
+  OGC:WFS 1.0.0/1.1.0/2.0.0,``http://www.opengis.net/wfs``,,yes
   OGC:WCS 1.0.0,``http://www.opengis.net/wcs``,,yes
   OGC:WPS 1.0.0,``http://www.opengis.net/wps/1.0.0``,,yes
   OGC:SOS 1.0.0,``http://www.opengis.net/sos/1.0``,,yes
diff --git a/etc/pycsw.desktop b/etc/pycsw.desktop
index 5c5b5f7..72a60b3 100644
--- a/etc/pycsw.desktop
+++ b/etc/pycsw.desktop
@@ -3,7 +3,6 @@ Type=Application
 Encoding=UTF-8
 Name=pycsw
 Comment=pycsw catalog server
-Categories=Application;Education;Geography;
 Exec=firefox http://localhost/pycsw/tests/index.html
 Icon=/var/www/html/pycsw/docs/_static/pycsw-logo.png
 Terminal=false
diff --git a/pavement.py b/pavement.py
index 840b7ba..fcf64a8 100644
--- a/pavement.py
+++ b/pavement.py
@@ -2,8 +2,10 @@
 # =================================================================
 #
 # Authors: Tom Kralidis <tomkralidis at gmail.com>
+#          Ricardo Garcia Silva <ricardo.garcia.silva at gmail.com>
 #
 # Copyright (c) 2015 Tom Kralidis
+# Copyright (c) 2016 Ricardo Garcia Silva
 #
 # Permission is hereby granted, free of charge, to any person
 # obtaining a copy of this software and associated documentation
@@ -28,17 +30,10 @@
 #
 # =================================================================
 
-from __future__ import (absolute_import, division, print_function)
-
-import glob
 import os
-import sys
-import time
-
-from six.moves import configparser
 
 from paver.easy import task, cmdopts, needs, \
-    pushd, sh, call_task, path, info, BuildFailure
+    pushd, sh, call_task, path, info
 
 DOCS = 'docs'
 STAGE_DIR = '/tmp'
@@ -92,7 +87,7 @@ def gen_tests_html():
     """Generate tests/index.html for online testing"""
     with pushd('tests'):
         # ensure manager testsuite is writeable
-        os.chmod(os.path.join('suites', 'manager', 'data'), 0o777)
+        os.chmod(os.path.join('functionaltests', 'suites', 'manager', 'data'), 0o777)
         sh('python gen_html.py > index.html')
 
 
@@ -145,203 +140,3 @@ def package_tar_gz(options):
         tar = tarfile.open(filename, 'w:gz')
         tar.add(package_name)
         tar.close()
-
- at task
-def setup_testdata():
-    """Create test databases and load test data"""
-
-    test_database_parameters = {
-        # suite: has_testdata
-        'apiso': True,
-        'cite': True,
-        'harvesting': False,
-        'manager': False
-    }
-
-    for suite in test_database_parameters.keys():
-        dbfile = 'tests/suites/%s/data/records.db' % suite
-        if os.path.isfile(dbfile):
-            os.remove(dbfile)
-
-    for database, has_testdata in test_database_parameters.items():
-        info('Setting up test database %s' % database)
-        cfg = path('tests/suites/%s/default.cfg' % database)
-        sh('pycsw-admin.py -c setup_db -f %s' % cfg)
-        if has_testdata:
-            datapath = path('tests/suites/%s/data' % database)
-            info('Loading test data from %s' % datapath)
-            sh('pycsw-admin.py -c load_records -f %s -p %s' % (cfg, datapath))
-            exportpath = path('tests/results/exports')
-            sh('pycsw-admin.py -c export_records -f %s -p %s' % (cfg, exportpath))
-
- at task
- at cmdopts([
-    ('url=', 'u', 'pycsw endpoint'),
-    ('suites=', 's', 'comma-separated list of testsuites'),
-    ('database=', 'd', 'database (SQLite3 [default], PostgreSQL, MySQL)'),
-    ('user=', 'U', 'database username'),
-    ('pass=', 'p', 'database password'),
-    ('pedantic', 'P', 'run tests in pedantic mode (byte level diff check) (default: c14n mode)'),
-    ('remote', 'r', 'remote testing (harvesting)'),
-    ('time=', 't', 'time (milliseconds) in which requests should complete')
-])
-def test(options):
-    """Run unit tests"""
-
-    db_setup = False
-    db_conn = None
-    cfg_files = []
-    status = 0
-
-    url = options.get('url', None)
-    suites = options.get('suites', None)
-    database = options.get('database', 'SQLite3')
-    remote = options.get('remote')
-    timems = options.get('time', None)
-    pedantic = options.get('pedantic', False)
-
-    if url is None:
-        # run against default server
-        call_task('stop')
-        call_task('reset')
-        if database == 'SQLite3':
-            call_task('setup_testdata')
-        call_task('start')
-        url = 'http://localhost:8000'
-
-    if suites is not None:
-        cmd = 'python run_tests.py -u %s -s %s' % (url, suites)
-    else:
-        cmd = 'python run_tests.py -u %s' % url
-
-    if remote:
-        cmd = '%s -r' % cmd
-
-    if pedantic:
-        cmd = '%s -p' % cmd
-
-    if timems:
-        cmd = '%s -t %s' % (cmd, timems)
-
-    # configure/setup database if not default
-    if database != 'SQLite3':
-        db_setup = True
-        temp_db = 'pycsw_ci_test_pid_%d' % os.getpid()
-
-        if database == 'PostgreSQL':  # configure PG
-
-            from pycsw.admin import setup_db, load_records, export_records
-            from pycsw.config import StaticContext
-
-            cmd = '%s -d %s' % (cmd, database)
-
-            init_sfsql = True
-            home = os.path.abspath(os.path.dirname(__file__))
-            user = options.get('user', 'postgres')
-            password = options.get('pass', '')
-            context = StaticContext()
-
-            db_conn = 'postgresql://%s:%s@localhost/%s' % (
-                      user, password, temp_db)
-
-            if password:
-                sh('set PGPASSWORD=%s' % password)
-
-            sh('createdb %s -U %s' % (temp_db, user))
-            sh('createlang --dbname=%s plpythonu -U %s' % (temp_db, user))
-
-            # update all default.cfg files to point to test DB
-            cfg_files = glob.glob('tests%ssuites%s*%s*.cfg' % (3*(os.sep,)))
-
-            for cfg in cfg_files:
-                # generate table
-                suite = cfg.split(os.sep)[2]
-
-                tablename = 'records_cite'
-
-                if suite == 'manager':
-                    tablename = 'records_manager'
-                elif suite == 'apiso':
-                    tablename = 'records_apiso'
-
-                config = configparser.SafeConfigParser()
-                with open(cfg) as read_data:
-                    config.readfp(read_data)
-                config.set('repository', 'database', db_conn)
-                config.set('repository', 'table', tablename)
-                with open(cfg, 'wb') as config2:
-                    config.write(config2)
-
-                if suite in ['cite', 'manager', 'apiso']:  # setup tables
-                    setup_db(db_conn, tablename, home, init_sfsql, init_sfsql)
-                    init_sfsql = False
-
-                if suite in ['cite', 'apiso']:  # load test data
-                    dirname = '%s%sdata' % (os.path.dirname(cfg), os.sep)
-                    load_records(context, db_conn, tablename, dirname)
-
-                if suite in ['cite', 'apiso']:  # export test data
-                    exportpath = 'tests/results/exports'
-                    export_records(context, db_conn, tablename, exportpath)
-
-        else:
-            raise Exception('Invalid database specified')
-
-    with pushd('tests'):
-        try:
-            sh(cmd)
-        except BuildFailure as err:
-            status = 1
-        # stop pycsw instance
-        call_task('stop')
-
-    if db_setup:  # tearDown
-        for cfg in cfg_files:
-            sh('git checkout %s' % cfg)
-        if database == 'PostgreSQL':
-            sh("psql -c \"select pg_terminate_backend(procpid) from pg_stat_activity where datname='%s';\" -U %s" % (temp_db, user))
-            sh('dropdb %s -U %s' % (temp_db, user))
-            sh('unset PGPASSWORD')
-
-    sys.exit(status)
-
-
- at task
-def start(options):
-    """Start local WSGI server instance"""
-    sh('python pycsw/wsgi.py 8000 &')
-    time.sleep(10)
-
-
- at task
-def stop():
-    """Stop local WSGI server instance"""
-
-    kill_process('python', 'pycsw/wsgi.py')
-
-
- at task
- at cmdopts([
-    ('force', 'f', 'forces git clean'),
-])
-def reset(options):
-    """Return codebase to pristine state"""
-
-    force = options.get('force')
-    if force:
-        sh('git clean -dxf')
-
-
-def kill_process(procname, scriptname):
-    """kill WSGI processes that may be running in development"""
-
-    # from http://stackoverflow.com/a/2940878
-    import subprocess, signal
-    p = subprocess.Popen(['ps', 'aux'], stdout=subprocess.PIPE)
-    out, err = p.communicate()
-
-    for line in out.decode().splitlines():
-        if procname in line and scriptname in line:
-            pid = int(line.split()[1])
-            info('Stopping %s %s %d' % (procname, scriptname, pid))
-            os.kill(pid, signal.SIGKILL)
diff --git a/pycsw/__init__.py b/pycsw/__init__.py
index 156d82b..b017be0 100644
--- a/pycsw/__init__.py
+++ b/pycsw/__init__.py
@@ -2,8 +2,10 @@
 # =================================================================
 #
 # Authors: Tom Kralidis <tomkralidis at gmail.com>
+#          Ricardo Garcia Silva <ricardo.garcia.silva at gmail.com>
 #
 # Copyright (c) 2015 Tom Kralidis
+# Copyright (c) 2017 Ricardo Garcia Silva
 #
 # Permission is hereby granted, free of charge, to any person
 # obtaining a copy of this software and associated documentation
@@ -28,4 +30,6 @@
 #
 # =================================================================
 
-__version__ = '2.0.3'
+import pkg_resources
+
+__version__ = pkg_resources.require("pycsw")[0].version
diff --git a/pycsw/core/admin.py b/pycsw/core/admin.py
index 3746d86..2f44388 100644
--- a/pycsw/core/admin.py
+++ b/pycsw/core/admin.py
@@ -37,6 +37,7 @@ from glob import glob
 
 from pycsw.core import metadata, repository, util
 from pycsw.core.etree import etree
+from pycsw.core.etree import PARSER
 
 LOGGER = logging.getLogger(__name__)
 
@@ -57,9 +58,9 @@ def setup_db(database, table, home, create_sfsql_tables=True, create_plpythonu_f
 
     dbase = create_engine(database)
 
-    schema, table = util.sniff_table(table)
+    schema_name, table_name = table.rpartition(".")[::2]
 
-    mdata = MetaData(dbase, schema=schema)
+    mdata = MetaData(dbase, schema=schema_name or None)
     create_postgis_geometry = False
 
     # If PostGIS 2.x detected, do not create sfsql tables.
@@ -70,7 +71,7 @@ def setup_db(database, table, home, create_sfsql_tables=True, create_plpythonu_f
                 postgis_lib_version = row[0]
             create_sfsql_tables=False
             create_postgis_geometry = True
-            LOGGER.info('PostGIS %s detected: Skipping SFSQL tables creation' % postgis_lib_version)
+            LOGGER.info('PostGIS %s detected: Skipping SFSQL tables creation', postgis_lib_version)
         except:
             pass
 
@@ -104,15 +105,15 @@ def setup_db(database, table, home, create_sfsql_tables=True, create_plpythonu_f
 
         i = geom.insert()
         i.execute(f_table_catalog='public', f_table_schema='public',
-                  f_table_name=table, f_geometry_column='wkt_geometry',
+                  f_table_name=table_name, f_geometry_column='wkt_geometry',
                   geometry_type=3, coord_dimension=2,
                   srid=4326, geometry_format='WKT')
 
     # abstract metadata information model
 
-    LOGGER.info('Creating table %s', table)
+    LOGGER.info('Creating table %s', table_name)
     records = Table(
-        table, mdata,
+        table_name, mdata,
         # core; nothing happens without these
         Column('identifier', Text, primary_key=True),
         Column('typename', Text,
@@ -216,7 +217,7 @@ def setup_db(database, table, home, create_sfsql_tables=True, create_plpythonu_f
         AS $$
             import sys
             sys.path.append('%s')
-            from pycsw import util
+            from pycsw.core import util
             return util.get_anytext(xml)
             $$ LANGUAGE plpythonu;
         ''' % pycsw_home
@@ -226,8 +227,8 @@ def setup_db(database, table, home, create_sfsql_tables=True, create_plpythonu_f
         AS $$
             import sys
             sys.path.append('%s')
-            from pycsw import util
-            return util.query_spatial(bbox_data_wkt, bbox_input_wkt, predicate, distance)
+            from pycsw.core import repository
+            return repository.query_spatial(bbox_data_wkt, bbox_input_wkt, predicate, distance)
             $$ LANGUAGE plpythonu;
         ''' % pycsw_home
             function_update_xpath = '''
@@ -236,8 +237,8 @@ def setup_db(database, table, home, create_sfsql_tables=True, create_plpythonu_f
         AS $$
             import sys
             sys.path.append('%s')
-            from pycsw import util
-            return util.update_xpath(nsmap, xml, recprops)
+            from pycsw.core import repository
+            return repository.update_xpath(nsmap, xml, recprops)
             $$ LANGUAGE plpythonu;
         ''' % pycsw_home
             function_get_geometry_area = '''
@@ -246,8 +247,8 @@ def setup_db(database, table, home, create_sfsql_tables=True, create_plpythonu_f
         AS $$
             import sys
             sys.path.append('%s')
-            from pycsw import util
-            return util.get_geometry_area(geom)
+            from pycsw.core import repository
+            return repository.get_geometry_area(geom)
             $$ LANGUAGE plpythonu;
         ''' % pycsw_home
             function_get_spatial_overlay_rank = '''
@@ -256,8 +257,8 @@ def setup_db(database, table, home, create_sfsql_tables=True, create_plpythonu_f
         AS $$
             import sys
             sys.path.append('%s')
-            from pycsw import util
-            return util.get_spatial_overlay_rank(target_geom, query_geom)
+            from pycsw.core import repository
+            return repository.get_spatial_overlay_rank(target_geom, query_geom)
             $$ LANGUAGE plpythonu;
         ''' % pycsw_home
             conn.execute(function_get_anytext)
@@ -268,21 +269,21 @@ def setup_db(database, table, home, create_sfsql_tables=True, create_plpythonu_f
 
     if dbase.name == 'postgresql':
         LOGGER.info('Creating PostgreSQL Free Text Search (FTS) GIN index')
-        tsvector_fts = "alter table %s add column anytext_tsvector tsvector" % table
+        tsvector_fts = "alter table %s add column anytext_tsvector tsvector" % table_name
         conn.execute(tsvector_fts)
-        index_fts = "create index fts_gin_idx on %s using gin(anytext_tsvector)" % table
+        index_fts = "create index fts_gin_idx on %s using gin(anytext_tsvector)" % table_name
         conn.execute(index_fts)
         # This needs to run if records exist "UPDATE records SET anytext_tsvector = to_tsvector('english', anytext)"
-        trigger_fts = "create trigger ftsupdate before insert or update on %s for each row execute procedure tsvector_update_trigger('anytext_tsvector', 'pg_catalog.%s', 'anytext')" % (table, language)
+        trigger_fts = "create trigger ftsupdate before insert or update on %s for each row execute procedure tsvector_update_trigger('anytext_tsvector', 'pg_catalog.%s', 'anytext')" % (table_name, language)
         conn.execute(trigger_fts)
 
     if dbase.name == 'postgresql' and create_postgis_geometry:
         # create native geometry column within db
         LOGGER.info('Creating native PostGIS geometry column')
         if postgis_lib_version < '2':
-            create_column_sql = "SELECT AddGeometryColumn('%s', '%s', 4326, 'POLYGON', 2)" % (table, postgis_geometry_column)
+            create_column_sql = "SELECT AddGeometryColumn('%s', '%s', 4326, 'POLYGON', 2)" % (table_name, postgis_geometry_column)
         else:
-            create_column_sql = "ALTER TABLE %s ADD COLUMN %s geometry(Geometry,4326);" % (table, postgis_geometry_column)
+            create_column_sql = "ALTER TABLE %s ADD COLUMN %s geometry(Geometry,4326);" % (table_name, postgis_geometry_column)
         create_insert_update_trigger_sql = '''
 DROP TRIGGER IF EXISTS %(table)s_update_geometry ON %(table)s;
 DROP FUNCTION IF EXISTS %(table)s_update_geometry();
@@ -298,10 +299,10 @@ $%(table)s_update_geometry$ LANGUAGE plpgsql;
 
 CREATE TRIGGER %(table)s_update_geometry BEFORE INSERT OR UPDATE ON %(table)s
 FOR EACH ROW EXECUTE PROCEDURE %(table)s_update_geometry();
-    ''' % {'table': table, 'geometry': postgis_geometry_column}
+    ''' % {'table': table_name, 'geometry': postgis_geometry_column}
 
         create_spatial_index_sql = 'CREATE INDEX %(geometry)s_idx ON %(table)s USING GIST (%(geometry)s);' \
-        % {'table': table, 'geometry': postgis_geometry_column}
+        % {'table': table_name, 'geometry': postgis_geometry_column}
 
         conn.execute(create_column_sql)
         conn.execute(create_insert_update_trigger_sql)
@@ -334,7 +335,7 @@ def load_records(context, database, table, xml_dirpath, recursive=False, force_u
         try:
             exml = etree.parse(recfile, context.parser)
         except Exception as err:
-            LOGGER.warn('XML document is not well-formed: %s', str(err))
+            LOGGER.exception('XML document is not well-formed')
             continue
 
         record = metadata.parse_record(context, exml, repo)
@@ -353,7 +354,7 @@ def load_records(context, database, table, xml_dirpath, recursive=False, force_u
                     repo.update(rec)
                     LOGGER.info('Updated')
                 else:
-                    LOGGER.warn('ERROR: not inserted %s', err)
+                    LOGGER.error('ERROR: not inserted %s', err)
 
 
 def export_records(context, database, table, xml_dirpath):
@@ -374,6 +375,7 @@ def export_records(context, database, table, xml_dirpath):
         try:
             os.makedirs(dirpath)
         except OSError as err:
+            LOGGER.exception('Could not create directory')
             raise RuntimeError('Could not create %s %s' % (dirpath, err))
 
     for record in records.all():
@@ -400,6 +402,7 @@ def export_records(context, database, table, xml_dirpath):
                 xml.write(str_xml)
 
         except Exception as err:
+            LOGGER.exception('Error writing to disk')
             raise RuntimeError("Error writing to %s" % filename, err)
 
 
@@ -437,7 +440,7 @@ def refresh_harvested_records(context, database, table, url):
                 csw.harvest(source, schema)
                 LOGGER.info(csw.response)
             except Exception as err:
-                LOGGER.warn(err)
+                LOGGER.exception('Could not harvest')
     else:
         LOGGER.info('No harvested records')
 
@@ -506,6 +509,7 @@ def post_xml(url, xml, timeout=30):
         with open(xml) as f:
             return http_post(url=url, request=f.read(), timeout=timeout)
     except Exception as err:
+        LOGGER.exception('HTTP XML POST error')
         raise RuntimeError(err)
 
 
@@ -565,12 +569,12 @@ def validate_xml(xml, xsd):
     LOGGER.info('Validating %s against schema %s', xml, xsd)
 
     schema = etree.XMLSchema(file=xsd)
-    parser = etree.XMLParser(schema=schema, resolve_entities=False)
 
     try:
-        valid = etree.parse(xml, parser)
+        valid = etree.parse(xml, PARSER)
         return 'Valid'
     except Exception as err:
+        LOGGER.exception('Invalid XML')
         raise RuntimeError('ERROR: %s' % str(err))
 
 
diff --git a/pycsw/core/config.py b/pycsw/core/config.py
index 33d8c4e..9c57a7b 100644
--- a/pycsw/core/config.py
+++ b/pycsw/core/config.py
@@ -29,7 +29,7 @@
 # =================================================================
 
 import logging
-from pycsw.core.etree import etree
+from pycsw.core.etree import PARSER
 from pycsw import __version__
 
 LOGGER = logging.getLogger(__name__)
@@ -45,7 +45,7 @@ class StaticContext(object):
 
         self.ogc_schemas_base = 'http://schemas.opengis.net'
 
-        self.parser = etree.XMLParser(resolve_entities=False)
+        self.parser = PARSER
 
         self.languages = {
             'en': 'english',
@@ -363,7 +363,7 @@ class StaticContext(object):
                         },
                         'parameters': {
                             'typeNames': {
-                                'values': ['csw:Record']
+                                'values': ['csw:Record', 'csw30:Record']
                             },
                             'outputSchema': {
                                 'values': ['http://www.opengis.net/cat/csw/3.0']
@@ -571,7 +571,7 @@ class StaticContext(object):
     def refresh_dc(self, mappings):
         """Refresh Dublin Core mappings"""
 
-        LOGGER.debug('refreshing Dublin Core mappings with %s' % str(mappings))
+        LOGGER.debug('refreshing Dublin Core mappings with %s', str(mappings))
 
         defaults = {
             'dc:title': 'pycsw:Title',
diff --git a/pycsw/core/etree.py b/pycsw/core/etree.py
index 491a80b..c270bb2 100644
--- a/pycsw/core/etree.py
+++ b/pycsw/core/etree.py
@@ -2,8 +2,10 @@
 # =================================================================
 #
 # Authors: Tom Kralidis <tomkralidis at gmail.com>
+#          Ricardo Garcia Silva <ricardo.garcia.silva at gmail.com>
 #
 # Copyright (c) 2015 Tom Kralidis
+# Copyright (c) 2017 Ricardo Garcia Silva
 #
 # Permission is hereby granted, free of charge, to any person
 # obtaining a copy of this software and associated documentation
@@ -28,4 +30,14 @@
 #
 # =================================================================
 
+"""Custom etree objects for pycsw
+
+Be sure to use the ``PARSER`` object defined in this module whenever it is
+necessary to parse external XML objects. This parser offers better protection
+against known XML attacks.
+
+"""
+
 from lxml import etree
+
+PARSER = etree.XMLParser(resolve_entities=False)
diff --git a/pycsw/core/formats/fmt_json.py b/pycsw/core/formats/fmt_json.py
index ded6ac6..0c8c3ee 100644
--- a/pycsw/core/formats/fmt_json.py
+++ b/pycsw/core/formats/fmt_json.py
@@ -2,8 +2,10 @@
 # =================================================================
 #
 # Authors: Tom Kralidis <tomkralidis at gmail.com>
+#          Ricardo Garcia Silva <ricardo.garcia.silva at gmail.com>
 #
 # Copyright (c) 2015 Tom Kralidis
+# Copyright (c) 2017 Ricardo Garcia Silva
 #
 # Permission is hereby granted, free of charge, to any person
 # obtaining a copy of this software and associated documentation
@@ -29,7 +31,30 @@
 # =================================================================
 
 import json
-from pycsw.core.util import xml2dict
+
+import xmltodict
+
+
+def xml2dict(xml_string, namespaces):
+    """Convert an xml document to a dictionary.
+
+    Parameters
+    ----------
+    xml_string: str
+        XML representation to convert to a dictionary.
+    namespaces: dict
+        Namespaces used in the ``xml_string`` parameter
+
+    Returns
+    -------
+    ordereddict
+        An ordered dictionary with the contents of the xml data
+
+    """
+
+    namespaces_reverse = dict((v, k) for k, v in namespaces.items())
+    return xmltodict.parse(xml_string, process_namespaces=True,
+                           namespaces=namespaces_reverse)
 
 
 def xml2json(xml_string, namespaces, pretty_print=False):
diff --git a/pycsw/core/log.py b/pycsw/core/log.py
index 2f32e6f..f0a6221 100644
--- a/pycsw/core/log.py
+++ b/pycsw/core/log.py
@@ -92,7 +92,7 @@ def setup_logger(config=None):
                         datefmt=TIME_FORMAT,
                         format=MSG_FORMAT)
 
-    LOGGER.info('Logging initialized (level: %s).' % loglevel)
+    LOGGER.info('Logging initialized (level: %s).', loglevel)
 
     if loglevel == 'DEBUG':  # turn on CGI debugging
         LOGGER.info('CGI debugging enabled.')
diff --git a/pycsw/core/metadata.py b/pycsw/core/metadata.py
index e9788a4..58a9c37 100644
--- a/pycsw/core/metadata.py
+++ b/pycsw/core/metadata.py
@@ -2,9 +2,11 @@
 # =================================================================
 #
 # Authors: Tom Kralidis <tomkralidis at gmail.com>
+#          Ricardo Garcia Silva <ricardo.garcia.silva at gmail.com>
 #
 # Copyright (c) 2017 Tom Kralidis
 # Copyright (c) 2016 James F. Dickens
+# Copyright (c) 2017 Ricardo Garcia Silva
 #
 # Permission is hereby granted, free of charge, to any person
 # obtaining a copy of this software and associated documentation
@@ -33,10 +35,14 @@ import logging
 import uuid
 from six.moves import range
 from six.moves.urllib.parse import urlparse
-from owslib.util import build_get_url
+
 from geolinks import sniff_link
-from pycsw.core import util
+from owslib.util import build_get_url
+from shapely.wkt import loads
+from shapely.geometry import MultiPolygon
+
 from pycsw.core.etree import etree
+from pycsw.core import util
 
 LOGGER = logging.getLogger(__name__)
 
@@ -51,7 +57,7 @@ def parse_record(context, record, repos=None,
     # parse web services
     if (mtype == 'http://www.opengis.net/cat/csw/2.0.2' and
         isinstance(record, str) and record.startswith('http')):
-        LOGGER.debug('CSW service detected, fetching via HTTP')
+        LOGGER.info('CSW service detected, fetching via HTTP')
         # CSW service, not csw:Record
         try:
             return _parse_csw(context, repos, record, identifier, pagesize)
@@ -59,7 +65,7 @@ def parse_record(context, record, repos=None,
             # TODO: implement better exception handling
             if str(err).find('ExceptionReport') != -1:
                 msg = 'CSW harvesting error: %s' % str(err)
-                LOGGER.debug(msg)
+                LOGGER.exception(msg)
                 raise RuntimeError(msg)
             LOGGER.debug('Not a CSW, attempting to fetch Dublin Core')
             try:
@@ -69,40 +75,44 @@ def parse_record(context, record, repos=None,
             return [_parse_dc(context, repos, etree.fromstring(content, context.parser))]
 
     elif mtype == 'urn:geoss:waf':  # WAF
-        LOGGER.debug('WAF detected, fetching via HTTP')
+        LOGGER.info('WAF detected, fetching via HTTP')
         return _parse_waf(context, repos, record, identifier)
 
     elif mtype == 'http://www.opengis.net/wms':  # WMS
-        LOGGER.debug('WMS detected, fetching via OWSLib')
+        LOGGER.info('WMS detected, fetching via OWSLib')
         return _parse_wms(context, repos, record, identifier)
 
     elif mtype == 'http://www.opengis.net/wmts/1.0':  # WMTS
-        LOGGER.debug('WMTS 1.0.0 detected, fetching via OWSLib')
+        LOGGER.info('WMTS 1.0.0 detected, fetching via OWSLib')
         return _parse_wmts(context, repos, record, identifier)
 
     elif mtype == 'http://www.opengis.net/wps/1.0.0':  # WPS
-        LOGGER.debug('WPS detected, fetching via OWSLib')
-        return [_parse_wps(context, repos, record, identifier)]
+        LOGGER.info('WPS detected, fetching via OWSLib')
+        return _parse_wps(context, repos, record, identifier)
 
-    elif mtype == 'http://www.opengis.net/wfs':  # WFS
-        LOGGER.debug('WFS detected, fetching via OWSLib')
-        return _parse_wfs(context, repos, record, identifier)
+    elif mtype == 'http://www.opengis.net/wfs':  # WFS 1.1.0
+        LOGGER.info('WFS detected, fetching via OWSLib')
+        return _parse_wfs(context, repos, record, identifier, '1.1.0')
+
+    elif mtype == 'http://www.opengis.net/wfs/2.0':  # WFS 2.0.0
+        LOGGER.info('WFS detected, fetching via OWSLib')
+        return _parse_wfs(context, repos, record, identifier, '2.0.0')
 
     elif mtype == 'http://www.opengis.net/wcs':  # WCS
-        LOGGER.debug('WCS detected, fetching via OWSLib')
+        LOGGER.info('WCS detected, fetching via OWSLib')
         return _parse_wcs(context, repos, record, identifier)
 
     elif mtype == 'http://www.opengis.net/sos/1.0':  # SOS 1.0.0
-        LOGGER.debug('SOS 1.0.0 detected, fetching via OWSLib')
+        LOGGER.info('SOS 1.0.0 detected, fetching via OWSLib')
         return _parse_sos(context, repos, record, identifier, '1.0.0')
 
     elif mtype == 'http://www.opengis.net/sos/2.0':  # SOS 2.0.0
-        LOGGER.debug('SOS 2.0.0 detected, fetching via OWSLib')
+        LOGGER.info('SOS 2.0.0 detected, fetching via OWSLib')
         return _parse_sos(context, repos, record, identifier, '2.0.0')
 
     elif (mtype == 'http://www.opengis.net/cat/csw/csdgm' and
           record.startswith('http')):  # FGDC
-        LOGGER.debug('FGDC detected, fetching via HTTP')
+        LOGGER.info('FGDC detected, fetching via HTTP')
         record = util.http_request('GET', record)
 
     return _parse_metadata(context, repos, record)
@@ -124,7 +134,7 @@ def _parse_metadata(context, repos, record):
 
     root = exml.tag
 
-    LOGGER.debug('Serialized metadata, parsing content model')
+    LOGGER.info('Serialized metadata, parsing content model')
 
     if root == '{%s}MD_Metadata' % context.namespaces['gmd']:  # ISO
         return [_parse_iso(context, repos, exml)]
@@ -135,6 +145,8 @@ def _parse_metadata(context, repos, record):
         return [_parse_fgdc(context, repos, exml)]
     elif root == '{%s}TRANSFER' % context.namespaces['gm03']:  # GM03
         return [_parse_gm03(context, repos, exml)]
+    elif root == '{http://www.geocat.ch/2008/che}CHE_MD_Metadata': # GM03 ISO profile
+        return [_parse_iso(context, repos, exml)]
     elif root == '{%s}Record' % context.namespaces['csw']:  # Dublin Core CSW
         return [_parse_dc(context, repos, exml)]
     elif root == '{%s}RDF' % context.namespaces['rdf']:  # Dublin Core RDF
@@ -155,14 +167,19 @@ def _parse_csw(context, repos, record, identifier, pagesize=10):
     # if init raises error, this might not be a CSW
     md = CatalogueServiceWeb(record, timeout=60)
 
-    LOGGER.debug('Setting CSW service metadata')
+    LOGGER.info('Setting CSW service metadata')
     # generate record of service instance
     _set(context, serviceobj, 'pycsw:Identifier', identifier)
     _set(context, serviceobj, 'pycsw:Typename', 'csw:Record')
     _set(context, serviceobj, 'pycsw:Schema', 'http://www.opengis.net/cat/csw/2.0.2')
     _set(context, serviceobj, 'pycsw:MdSource', record)
     _set(context, serviceobj, 'pycsw:InsertDate', util.get_today_and_now())
-    _set(context, serviceobj, 'pycsw:AnyText', util.get_anytext(md._exml))
+    _set(
+        context,
+        serviceobj,
+        'pycsw:AnyText',
+        util.get_anytext(md._exml)
+    )
     _set(context, serviceobj, 'pycsw:Type', 'service')
     _set(context, serviceobj, 'pycsw:Title', md.identification.title)
     _set(context, serviceobj, 'pycsw:Abstract', md.identification.abstract)
@@ -200,7 +217,7 @@ def _parse_csw(context, repos, record, identifier, pagesize=10):
     grop = md.get_operation_by_name('GetRecords')
     if all(['gmd:MD_Metadata' in grop.parameters['typeNames']['values'],
             'http://www.isotc211.org/2005/gmd' in grop.parameters['outputSchema']['values']]):
-        LOGGER.info('CSW supports ISO')
+        LOGGER.debug('CSW supports ISO')
         csw_typenames = 'gmd:MD_Metadata'
         csw_outputschema = 'http://www.isotc211.org/2005/gmd'
 
@@ -218,7 +235,7 @@ def _parse_csw(context, repos, record, identifier, pagesize=10):
     if pagesize > matches:
         pagesize = matches
 
-    LOGGER.debug('Harvesting %d CSW records' % matches)
+    LOGGER.info('Harvesting %d CSW records', matches)
 
     # loop over all catalogue records incrementally
     for r in range(1, matches+1, pagesize):
@@ -230,7 +247,7 @@ def _parse_csw(context, repos, record, identifier, pagesize=10):
         for k, v in md.records.items():
             # try to parse metadata
             try:
-                LOGGER.debug('Parsing metadata record: %s', v.xml)
+                LOGGER.info('Parsing metadata record: %s', v.xml)
                 if csw_typenames == 'gmd:MD_Metadata':
                     recobjs.append(_parse_iso(context, repos,
                                               etree.fromstring(v.xml, context.parser)))
@@ -238,7 +255,7 @@ def _parse_csw(context, repos, record, identifier, pagesize=10):
                     recobjs.append(_parse_dc(context, repos,
                                              etree.fromstring(v.xml, context.parser)))
             except Exception as err:  # parsing failed for some reason
-                LOGGER.warning('Metadata parsing failed %s', err)
+                LOGGER.exception('Metadata parsing failed')
 
     return recobjs
 
@@ -259,7 +276,7 @@ def _parse_waf(context, repos, record, identifier):
     up = urlparse(record)
     links = []
 
-    LOGGER.debug('collecting links')
+    LOGGER.info('collecting links')
     for link in tree.xpath('//a/@href'):
         link = link.strip()
         if not link:
@@ -282,7 +299,7 @@ def _parse_waf(context, repos, record, identifier):
 
     LOGGER.debug('%d links found', len(links))
     for link in links:
-        LOGGER.debug('Processing link %s', link)
+        LOGGER.info('Processing link %s', link)
         # fetch and parse
         linkcontent = util.http_request('GET', link)
         recobj = _parse_metadata(context, repos, linkcontent)[0]
@@ -300,6 +317,11 @@ def _parse_wms(context, repos, record, identifier):
     serviceobj = repos.dataset()
 
     md = WebMapService(record)
+    try:
+        md = WebMapService(record, version='1.3.0')
+    except Exception as err:
+        LOGGER.info('Looks like WMS 1.3.0 is not supported; trying 1.1.1', err)
+        md = WebMapService(record)
 
     # generate record of service instance
     _set(context, serviceobj, 'pycsw:Identifier', identifier)
@@ -307,7 +329,12 @@ def _parse_wms(context, repos, record, identifier):
     _set(context, serviceobj, 'pycsw:Schema', 'http://www.opengis.net/wms')
     _set(context, serviceobj, 'pycsw:MdSource', record)
     _set(context, serviceobj, 'pycsw:InsertDate', util.get_today_and_now())
-    _set(context, serviceobj, 'pycsw:AnyText', util.get_anytext(md.getServiceXML()))
+    _set(
+        context,
+        serviceobj,
+        'pycsw:AnyText',
+        util.get_anytext(md.getServiceXML())
+    )
     _set(context, serviceobj, 'pycsw:Type', 'service')
     _set(context, serviceobj, 'pycsw:Title', md.identification.title)
     _set(context, serviceobj, 'pycsw:Abstract', md.identification.abstract)
@@ -345,7 +372,7 @@ def _parse_wms(context, repos, record, identifier):
 
     # generate record foreach layer
 
-    LOGGER.debug('Harvesting %d WMS layers' % len(md.contents))
+    LOGGER.info('Harvesting %d WMS layers', len(md.contents))
 
     for layer in md.contents:
         recobj = repos.dataset()
@@ -361,10 +388,16 @@ def _parse_wms(context, repos, record, identifier):
         _set(context, recobj, 'pycsw:Abstract', md.contents[layer].abstract)
         _set(context, recobj, 'pycsw:Keywords', ','.join(md.contents[layer].keywords))
 
-        _set(context, recobj, 'pycsw:AnyText',
-             util.get_anytext([md.contents[layer].title,
-                              md.contents[layer].abstract,
-                              ','.join(md.contents[layer].keywords)]))
+        _set(
+            context,
+            recobj,
+            'pycsw:AnyText',
+            util.get_anytext([
+                md.contents[layer].title,
+                md.contents[layer].abstract,
+                ','.join(md.contents[layer].keywords)
+            ])
+        )
 
         bbox = md.contents[layer].boundingBoxWGS84
         if bbox is not None:
@@ -433,7 +466,12 @@ def _parse_wmts(context, repos, record, identifier):
     _set(context, serviceobj, 'pycsw:Schema', 'http://www.opengis.net/wmts/1.0')
     _set(context, serviceobj, 'pycsw:MdSource', record)
     _set(context, serviceobj, 'pycsw:InsertDate', util.get_today_and_now())
-    _set(context, serviceobj, 'pycsw:AnyText', util.get_anytext(md.getServiceXML()))
+    _set(
+        context,
+        serviceobj,
+        'pycsw:AnyText',
+        util.get_anytext(md.getServiceXML())
+    )
     _set(context, serviceobj, 'pycsw:Type', 'service')
     _set(context, serviceobj, 'pycsw:Title', md.identification.title)
     _set(context, serviceobj, 'pycsw:Abstract', md.identification.abstract)
@@ -472,7 +510,7 @@ def _parse_wmts(context, repos, record, identifier):
 
     # generate record for each layer
 
-    LOGGER.debug('Harvesting %d WMTS layers' % len(md.contents))
+    LOGGER.debug('Harvesting %d WMTS layers', len(md.contents))
 
     for layer in md.contents:
         recobj = repos.dataset()
@@ -497,11 +535,16 @@ def _parse_wmts(context, repos, record, identifier):
             keywords = ','.join(md.contents[layer].keywords)
         _set(context, recobj, 'pycsw:Keywords', keywords)
 
-        _set(context, recobj, 'pycsw:AnyText',
-             util.get_anytext([md.contents[layer].title,
-                              md.contents[layer].abstract,
-                             ','.join(keywords)
-                             ]))
+        _set(
+            context,
+            recobj,
+            'pycsw:AnyText',
+             util.get_anytext([
+                 md.contents[layer].title,
+                 md.contents[layer].abstract,
+                 ','.join(keywords)
+             ])
+        )
 
         bbox = md.contents[layer].boundingBoxWGS84
 
@@ -539,7 +582,7 @@ def _parse_wmts(context, repos, record, identifier):
     return recobjs
 
 
-def _parse_wfs(context, repos, record, identifier):
+def _parse_wfs(context, repos, record, identifier, version):
 
     from owslib.wfs import WebFeatureService
 
@@ -547,7 +590,11 @@ def _parse_wfs(context, repos, record, identifier):
     recobjs = []
     serviceobj = repos.dataset()
 
-    md = WebFeatureService(record, '1.1.0')
+    try:
+        md = WebFeatureService(record, version)
+    except Exception as err:
+        if version == '1.1.0':
+            md = WebFeatureService(record, '1.0.0')
 
     # generate record of service instance
     _set(context, serviceobj, 'pycsw:Identifier', identifier)
@@ -555,7 +602,12 @@ def _parse_wfs(context, repos, record, identifier):
     _set(context, serviceobj, 'pycsw:Schema', 'http://www.opengis.net/wfs')
     _set(context, serviceobj, 'pycsw:MdSource', record)
     _set(context, serviceobj, 'pycsw:InsertDate', util.get_today_and_now())
-    _set(context, serviceobj, 'pycsw:AnyText', util.get_anytext(etree.tostring(md._capabilities)))
+    _set(
+        context,
+        serviceobj,
+        'pycsw:AnyText',
+        util.get_anytext(etree.tostring(md._capabilities))
+    )
     _set(context, serviceobj, 'pycsw:Type', 'service')
     _set(context, serviceobj, 'pycsw:Title', md.identification.title)
     _set(context, serviceobj, 'pycsw:Abstract', md.identification.abstract)
@@ -584,7 +636,7 @@ def _parse_wfs(context, repos, record, identifier):
 
     # generate record foreach featuretype
 
-    LOGGER.debug('Harvesting %d WFS featuretypes' % len(md.contents))
+    LOGGER.info('Harvesting %d WFS featuretypes', len(md.contents))
 
     for featuretype in md.contents:
         recobj = repos.dataset()
@@ -600,10 +652,16 @@ def _parse_wfs(context, repos, record, identifier):
         _set(context, recobj, 'pycsw:Abstract', md.contents[featuretype].abstract)
         _set(context, recobj, 'pycsw:Keywords', ','.join(md.contents[featuretype].keywords))
 
-        _set(context, recobj, 'pycsw:AnyText',
-             util.get_anytext([md.contents[featuretype].title,
-                              md.contents[featuretype].abstract,
-                              ','.join(md.contents[featuretype].keywords)]))
+        _set(
+            context,
+            recobj,
+            'pycsw:AnyText',
+            util.get_anytext([
+                md.contents[featuretype].title,
+                md.contents[featuretype].abstract,
+                ','.join(md.contents[featuretype].keywords)
+            ])
+        )
 
         bbox = md.contents[featuretype].boundingBoxWGS84
         if bbox is not None:
@@ -633,7 +691,7 @@ def _parse_wfs(context, repos, record, identifier):
 
     # Derive a bbox based on aggregated featuretype bbox values
 
-    bbox_agg = util.bbox_from_polygons(bboxs)
+    bbox_agg = bbox_from_polygons(bboxs)
 
     if bbox_agg is not None:
         _set(context, serviceobj, 'pycsw:BoundingBox', bbox_agg)
@@ -660,7 +718,12 @@ def _parse_wcs(context, repos, record, identifier):
     _set(context, serviceobj, 'pycsw:Schema', 'http://www.opengis.net/wcs')
     _set(context, serviceobj, 'pycsw:MdSource', record)
     _set(context, serviceobj, 'pycsw:InsertDate', util.get_today_and_now())
-    _set(context, serviceobj, 'pycsw:AnyText', util.get_anytext(etree.tostring(md._capabilities)))
+    _set(
+        context,
+        serviceobj,
+        'pycsw:AnyText',
+        util.get_anytext(etree.tostring(md._capabilities))
+    )
     _set(context, serviceobj, 'pycsw:Type', 'service')
     _set(context, serviceobj, 'pycsw:Title', md.identification.title)
     _set(context, serviceobj, 'pycsw:Abstract', md.identification.abstract)
@@ -689,7 +752,7 @@ def _parse_wcs(context, repos, record, identifier):
 
     # generate record foreach coverage
 
-    LOGGER.debug('Harvesting %d WCS coverages ' % len(md.contents))
+    LOGGER.info('Harvesting %d WCS coverages ', len(md.contents))
 
     for coverage in md.contents:
         recobj = repos.dataset()
@@ -705,10 +768,16 @@ def _parse_wcs(context, repos, record, identifier):
         _set(context, recobj, 'pycsw:Abstract', md.contents[coverage].abstract)
         _set(context, recobj, 'pycsw:Keywords', ','.join(md.contents[coverage].keywords))
 
-        _set(context, recobj, 'pycsw:AnyText',
-             util.get_anytext([md.contents[coverage].title,
-                              md.contents[coverage].abstract,
-                              ','.join(md.contents[coverage].keywords)]))
+        _set(
+            context,
+            recobj,
+            'pycsw:AnyText',
+            util.get_anytext([
+                md.contents[coverage].title,
+                md.contents[coverage].abstract,
+                ','.join(md.contents[coverage].keywords)
+            ])
+        )
 
         bbox = md.contents[coverage].boundingBoxWGS84
         if bbox is not None:
@@ -730,7 +799,7 @@ def _parse_wcs(context, repos, record, identifier):
 
     # Derive a bbox based on aggregated coverage bbox values
 
-    bbox_agg = util.bbox_from_polygons(bboxs)
+    bbox_agg = bbox_from_polygons(bboxs)
 
     if bbox_agg is not None:
         _set(context, serviceobj, 'pycsw:BoundingBox', bbox_agg)
@@ -744,6 +813,7 @@ def _parse_wps(context, repos, record, identifier):
 
     from owslib.wps import WebProcessingService
 
+    recobjs = []
     serviceobj = repos.dataset()
 
     md = WebProcessingService(record)
@@ -754,7 +824,12 @@ def _parse_wps(context, repos, record, identifier):
     _set(context, serviceobj, 'pycsw:Schema', 'http://www.opengis.net/wps/1.0.0')
     _set(context, serviceobj, 'pycsw:MdSource', record)
     _set(context, serviceobj, 'pycsw:InsertDate', util.get_today_and_now())
-    _set(context, serviceobj, 'pycsw:AnyText', util.get_anytext(md._capabilities))
+    _set(
+        context,
+        serviceobj,
+        'pycsw:AnyText',
+        util.get_anytext(md._capabilities)
+    )
     _set(context, serviceobj, 'pycsw:Type', 'service')
     _set(context, serviceobj, 'pycsw:Title', md.identification.title)
     _set(context, serviceobj, 'pycsw:Abstract', md.identification.abstract)
@@ -782,7 +857,48 @@ def _parse_wps(context, repos, record, identifier):
     _set(context, serviceobj, 'pycsw:Links', '^'.join(links))
     _set(context, serviceobj, 'pycsw:XML', caps2iso(serviceobj, md, context))
 
-    return serviceobj
+    recobjs.append(serviceobj)
+
+    # generate record foreach process
+
+    LOGGER.info('Harvesting %d WPS processes', len(md.processes))
+
+    for process in md.processes:
+        recobj = repos.dataset()
+        identifier2 = '%s-%s' % (identifier, process.identifier)
+        _set(context, recobj, 'pycsw:Identifier', identifier2)
+        _set(context, recobj, 'pycsw:Typename', 'csw:Record')
+        _set(context, recobj, 'pycsw:Schema', 'http://www.opengis.net/wps/1.0.0')
+        _set(context, recobj, 'pycsw:MdSource', record)
+        _set(context, recobj, 'pycsw:InsertDate', util.get_today_and_now())
+        _set(context, recobj, 'pycsw:Type', 'software')
+        _set(context, recobj, 'pycsw:ParentIdentifier', identifier)
+        _set(context, recobj, 'pycsw:Title', process.title)
+        _set(context, recobj, 'pycsw:Abstract', process.abstract)
+
+        _set(
+            context,
+            recobj,
+            'pycsw:AnyText',
+            util.get_anytext([process.title, process.abstract])
+        )
+
+        params = {
+            'service': 'WPS',
+            'version': '1.0.0',
+            'request': 'DescribeProcess',
+            'identifier': process.identifier
+        }
+
+        links.append(
+        '%s,OGC-WPS DescribeProcess service (ver 1.0.0),OGC:WPS-1.0.0-http-describe-process,%s' % (identifier, build_get_url(md.url, {'service': 'WPS', 'version': '1.0.0', 'request': 'DescribeProcess', 'identifier': process.identifier})))
+
+        _set(context, recobj, 'pycsw:Links', '^'.join(links))
+        _set(context, recobj, 'pycsw:XML', caps2iso(recobj, md, context))
+
+        recobjs.append(recobj)
+
+    return recobjs
 
 
 def _parse_sos(context, repos, record, identifier, version):
@@ -806,7 +922,12 @@ def _parse_sos(context, repos, record, identifier, version):
     _set(context, serviceobj, 'pycsw:Schema', schema)
     _set(context, serviceobj, 'pycsw:MdSource', record)
     _set(context, serviceobj, 'pycsw:InsertDate', util.get_today_and_now())
-    _set(context, serviceobj, 'pycsw:AnyText', util.get_anytext(etree.tostring(md._capabilities)))
+    _set(
+        context,
+        serviceobj,
+        'pycsw:AnyText',
+        util.get_anytext(etree.tostring(md._capabilities))
+    )
     _set(context, serviceobj, 'pycsw:Type', 'service')
     _set(context, serviceobj, 'pycsw:Title', md.identification.title)
     _set(context, serviceobj, 'pycsw:Abstract', md.identification.abstract)
@@ -835,7 +956,7 @@ def _parse_sos(context, repos, record, identifier, version):
 
     # generate record foreach offering
 
-    LOGGER.debug('Harvesting %d SOS ObservationOffering\'s ', len(md.contents))
+    LOGGER.info('Harvesting %d SOS ObservationOffering\'s ', len(md.contents))
 
     for offering in md.contents:
         recobj = repos.dataset()
@@ -849,8 +970,12 @@ def _parse_sos(context, repos, record, identifier, version):
         _set(context, recobj, 'pycsw:ParentIdentifier', identifier)
         _set(context, recobj, 'pycsw:Title', md.contents[offering].description)
         _set(context, recobj, 'pycsw:Abstract', md.contents[offering].description)
-        _set(context, recobj, 'pycsw:TempExtent_begin', util.datetime2iso8601(md.contents[offering].begin_position))
-        _set(context, recobj, 'pycsw:TempExtent_end', util.datetime2iso8601(md.contents[offering].end_position))
+        begin = md.contents[offering].begin_position
+        end = md.contents[offering].end_position
+        _set(context, recobj, 'pycsw:TempExtent_begin',
+             util.datetime2iso8601(begin) if begin is not None else None)
+        _set(context, recobj, 'pycsw:TempExtent_end',
+             util.datetime2iso8601(end) if end is not None else None)
 
         #For observed_properties that have mmi url or urn, we simply want the observation name.
         observed_properties = []
@@ -884,7 +1009,7 @@ def _parse_sos(context, repos, record, identifier, version):
 
     # Derive a bbox based on aggregated featuretype bbox values
 
-    bbox_agg = util.bbox_from_polygons(bboxs)
+    bbox_agg = bbox_from_polygons(bboxs)
 
     if bbox_agg is not None:
         _set(context, serviceobj, 'pycsw:BoundingBox', bbox_agg)
@@ -1089,11 +1214,15 @@ def _parse_gm03(context, repos, exml):
 def _parse_iso(context, repos, exml):
 
     from owslib.iso import MD_Metadata
+    from owslib.iso_che import CHE_MD_Metadata
 
     recobj = repos.dataset()
     links = []
 
-    md = MD_Metadata(exml)
+    if exml.tag == '{http://www.geocat.ch/2008/che}CHE_MD_Metadata':
+        md = CHE_MD_Metadata(exml)
+    else:
+        md = MD_Metadata(exml)
 
     _set(context, recobj, 'pycsw:Identifier', md.identifier)
     _set(context, recobj, 'pycsw:Typename', 'gmd:MD_Metadata')
@@ -1256,7 +1385,7 @@ def _parse_iso(context, repos, exml):
                         (scpt.name, scpt.description, scpt.protocol, scpt.url)
                         links.append(linkstr)
     except Exception as err:  # srv: identification does not exist
-        LOGGER.debug('no srv:SV_ServiceIdentification links found')
+        LOGGER.exception('no srv:SV_ServiceIdentification links found')
 
     if len(links) > 0:
         _set(context, recobj, 'pycsw:Links', '^'.join(links))
@@ -1354,3 +1483,29 @@ def caps2iso(record, caps, context):
     queryables = dict(apiso_obj.repository['queryables']['SupportedISOQueryables'].items())
     iso_xml = apiso_obj.write_record(record, 'full', 'http://www.isotc211.org/2005/gmd', queryables, caps)
     return etree.tostring(iso_xml)
+
+
+def bbox_from_polygons(bboxs):
+    """Derive an aggregated bbox from n polygons
+
+    Parameters
+    ----------
+    bboxs: list
+        A sequence of strings containing Well-Known Text representations of
+        polygons
+
+    Returns
+    -------
+    str
+        Well-Known Text representation of the aggregated bounding box for
+        all the input polygons
+    """
+
+    try:
+        multi_pol = MultiPolygon(
+            [loads(bbox) for bbox in bboxs]
+        )
+        bstr = ",".join(["{0:.2f}".format(b) for b in multi_pol.bounds])
+        return util.bbox2wktpolygon(bstr)
+    except Exception as err:
+        raise RuntimeError('Cannot aggregate polygons: %s' % str(err))
diff --git a/pycsw/core/repository.py b/pycsw/core/repository.py
index aba9369..c1bdd6e 100644
--- a/pycsw/core/repository.py
+++ b/pycsw/core/repository.py
@@ -3,9 +3,11 @@
 #
 # Authors: Tom Kralidis <tomkralidis at gmail.com>
 #          Angelos Tzotsos <tzotsos at gmail.com>
+#          Ricardo Garcia Silva <ricardo.garcia.silva at gmail.com>
 #
 # Copyright (c) 2015 Tom Kralidis
 # Copyright (c) 2015 Angelos Tzotsos
+# Copyright (c) 2017 Ricardo Garcia Silva
 #
 # Permission is hereby granted, free of charge, to any person
 # obtaining a copy of this software and associated documentation
@@ -30,16 +32,25 @@
 #
 # =================================================================
 
+import inspect
 import logging
 import os
-from sqlalchemy import create_engine, asc, desc, func, __version__, select
+
+import six
+from shapely.wkt import loads
+from shapely.geos import ReadingError
+from sqlalchemy import create_engine, func, __version__, select
 from sqlalchemy.sql import text
 from sqlalchemy.ext.declarative import declarative_base
 from sqlalchemy.orm import create_session
+
 from pycsw.core import util
+from pycsw.core.etree import etree
+from pycsw.core.etree import PARSER
 
 LOGGER = logging.getLogger(__name__)
 
+
 class Repository(object):
     _engines = {}
 
@@ -56,7 +67,7 @@ class Repository(object):
         Engines are memoized by url
         '''
         if url not in clazz._engines:
-            LOGGER.debug('creating new engine: %s', url)
+            LOGGER.info('creating new engine: %s', url)
             engine = create_engine('%s' % url, echo=False)
 
             # load SQLite query bindings
@@ -66,16 +77,7 @@ class Repository(object):
                 from sqlalchemy import event
                 @event.listens_for(engine, "connect")
                 def connect(dbapi_connection, connection_rec):
-                    dbapi_connection.create_function(
-                    'query_spatial', 4, util.query_spatial)
-                    dbapi_connection.create_function(
-                    'update_xpath', 3, util.update_xpath)
-                    dbapi_connection.create_function('get_anytext', 1,
-                    util.get_anytext)
-                    dbapi_connection.create_function('get_geometry_area', 1,
-                    util.get_geometry_area)
-                    dbapi_connection.create_function('get_spatial_overlay_rank', 2,
-                    util.get_spatial_overlay_rank)
+                    create_custom_sql_functions(dbapi_connection)
 
             clazz._engines[url] = engine
 
@@ -100,15 +102,23 @@ class Repository(object):
 
         base = declarative_base(bind=self.engine)
 
-        LOGGER.debug('binding ORM to existing database')
+        LOGGER.info('binding ORM to existing database')
 
         self.postgis_geometry_column = None
 
-        schema, table = util.sniff_table(table)
+        schema_name, table_name = table.rpartition(".")[::2]
 
-        self.dataset = type('dataset', (base,),
-        dict(__tablename__=table,__table_args__={'autoload': True,
-                                                 'schema': schema}))
+        self.dataset = type(
+            'dataset',
+            (base,),
+            {
+                "__tablename__": table_name,
+                "__table_args__": {
+                    "autoload": True,
+                    "schema": schema_name or None,
+                },
+            }
+        )
 
         self.dbtype = self.engine.name
 
@@ -123,7 +133,7 @@ class Repository(object):
                 temp_dbtype = 'postgresql+postgis+wkt'
                 LOGGER.debug('PostgreSQL+PostGIS1+WKT detected')
             except Exception as err:
-                LOGGER.debug('PostgreSQL+PostGIS1+WKT detection failed')
+                LOGGER.exception('PostgreSQL+PostGIS1+WKT detection failed')
 
             # check if PostgreSQL is enabled with PostGIS 2.x
             try:
@@ -131,17 +141,23 @@ class Repository(object):
                 temp_dbtype = 'postgresql+postgis+wkt'
                 LOGGER.debug('PostgreSQL+PostGIS2+WKT detected')
             except Exception as err:
-                LOGGER.debug('PostgreSQL+PostGIS2+WKT detection failed')
+                LOGGER.exception('PostgreSQL+PostGIS2+WKT detection failed')
 
             # check if a native PostGIS geometry column exists
             try:
-                result = self.session.execute("select f_geometry_column from geometry_columns where f_table_name = '%s' and f_geometry_column != 'wkt_geometry' limit 1;" % table)
+                result = self.session.execute(
+                    "select f_geometry_column "
+                    "from geometry_columns "
+                    "where f_table_name = '%s' "
+                    "and f_geometry_column != 'wkt_geometry' "
+                    "limit 1;" % table_name
+                )
                 row = result.fetchone()
                 self.postgis_geometry_column = str(row['f_geometry_column'])
                 temp_dbtype = 'postgresql+postgis+native'
                 LOGGER.debug('PostgreSQL+PostGIS+Native detected')
             except Exception as err:
-                LOGGER.debug('PostgreSQL+PostGIS+Native not picked up: %s', str(err))
+                LOGGER.exception('PostgreSQL+PostGIS+Native not picked up: %s')
 
             # check if a native PostgreSQL FTS GIN index exists
             result = self.session.execute("select relname from pg_class where relname='fts_gin_idx'").scalar()
@@ -149,25 +165,16 @@ class Repository(object):
             LOGGER.debug('PostgreSQL FTS enabled: %r', self.fts)
 
         if temp_dbtype is not None:
-            LOGGER.debug('%s support detected' % temp_dbtype)
+            LOGGER.debug('%s support detected', temp_dbtype)
             self.dbtype = temp_dbtype
 
         if self.dbtype in ['sqlite', 'sqlite3']:  # load SQLite query bindings
             # <= 0.6 behaviour
             if not __version__ >= '0.7':
                 self.connection = self.engine.raw_connection()
-                self.connection.create_function(
-                'query_spatial', 4, util.query_spatial)
-                self.connection.create_function(
-                'update_xpath', 3, util.update_xpath)
-                self.connection.create_function('get_anytext', 1,
-                util.get_anytext)
-                self.connection.create_function('get_geometry_area', 1,
-                util.get_geometry_area)
-                self.connection.create_function('get_spatial_overlay_rank', 2,
-                util.get_spatial_overlay_rank)
-
-        LOGGER.debug('setting repository queryables')
+                create_custom_sql_functions(self.connection)
+
+        LOGGER.info('setting repository queryables')
         # generate core queryables db and obj bindings
         self.queryables = {}
 
@@ -209,12 +216,12 @@ class Repository(object):
         domain_value = getattr(self.dataset, domain)
 
         if domainquerytype == 'range':
-            LOGGER.debug('Generating property name range values')
+            LOGGER.info('Generating property name range values')
             query = self.session.query(func.min(domain_value),
                                        func.max(domain_value))
         else:
             if count:
-                LOGGER.debug('Generating property name frequency counts')
+                LOGGER.info('Generating property name frequency counts')
                 query = self.session.query(getattr(self.dataset, domain),
                     func.count(domain_value)).group_by(domain_value)
             else:
@@ -293,7 +300,9 @@ class Repository(object):
             self.session.commit()
         except Exception as err:
             self.session.rollback()
-            raise RuntimeError('ERROR: %s' % str(err.orig))
+            msg = 'Cannot commit to repository'
+            LOGGER.exception(msg)
+            raise RuntimeError(msg)
 
     def update(self, record=None, recprops=None, constraint=None):
         ''' Update a record in the repository based on identifier '''
@@ -319,7 +328,9 @@ class Repository(object):
                 self.session.commit()
             except Exception as err:
                 self.session.rollback()
-                raise RuntimeError('ERROR: %s' % str(err.orig))
+                msg = 'Cannot commit to repository'
+                LOGGER.exception(msg)
+                raise RuntimeError(msg)
         else:  # update based on record properties
             LOGGER.debug('property based update')
             try:
@@ -352,7 +363,9 @@ class Repository(object):
                 return rows
             except Exception as err:
                 self.session.rollback()
-                raise RuntimeError('ERROR: %s' % str(err.orig))
+                msg = 'Cannot commit to repository'
+                LOGGER.exception(msg)
+                raise RuntimeError(msg)
 
     def delete(self, constraint):
         ''' Delete a record from the repository '''
@@ -380,7 +393,9 @@ class Repository(object):
             self.session.commit()
         except Exception as err:
             self.session.rollback()
-            raise RuntimeError('ERROR: %s' % str(err.orig))
+            msg = 'Cannot commit to repository'
+            LOGGER.exception(msg)
+            raise RuntimeError(msg)
 
         return rows
 
@@ -389,3 +404,148 @@ class Repository(object):
         if self.filter is not None:
             return query.filter(text(self.filter))
         return query
+
+
+def create_custom_sql_functions(connection):
+    """Register custom functions on the database connection."""
+    if six.PY2:
+        inspect_function = inspect.getargspec
+    else:  # python3
+        inspect_function = inspect.getfullargspec
+
+    for function_object in [
+        query_spatial,
+        update_xpath,
+        util.get_anytext,
+        get_geometry_area,
+        get_spatial_overlay_rank
+    ]:
+        argspec = inspect_function(function_object)
+        connection.create_function(
+            function_object.__name__,
+            len(argspec.args),
+            function_object
+        )
+
+
+def query_spatial(bbox_data_wkt, bbox_input_wkt, predicate, distance):
+    """Perform spatial query
+
+    Parameters
+    ----------
+    bbox_data_wkt: str
+        Well-Known Text representation of the data being queried
+    bbox_input_wkt: str
+        Well-Known Text representation of the input being queried
+    predicate: str
+        Spatial predicate to use in query
+    distance: int or float or str
+        Distance parameter for when using either of ``beyond`` or ``dwithin``
+        predicates.
+
+    Returns
+    -------
+    str
+        Either ``true`` or ``false`` depending on the result of the spatial
+        query
+
+    Raises
+    ------
+    RuntimeError
+        If an invalid predicate is used
+
+    """
+
+    try:
+        bbox1 = loads(bbox_data_wkt.split(';')[-1])
+        bbox2 = loads(bbox_input_wkt)
+        if predicate == 'bbox':
+            result = bbox1.intersects(bbox2)
+        elif predicate == 'beyond':
+            result = bbox1.distance(bbox2) > float(distance)
+        elif predicate == 'contains':
+            result = bbox1.contains(bbox2)
+        elif predicate == 'crosses':
+            result = bbox1.crosses(bbox2)
+        elif predicate == 'disjoint':
+            result = bbox1.disjoint(bbox2)
+        elif predicate == 'dwithin':
+            result = bbox1.distance(bbox2) <= float(distance)
+        elif predicate == 'equals':
+            result = bbox1.equals(bbox2)
+        elif predicate == 'intersects':
+            result = bbox1.intersects(bbox2)
+        elif predicate == 'overlaps':
+            result = bbox1.intersects(bbox2) and not bbox1.touches(bbox2)
+        elif predicate == 'touches':
+            result = bbox1.touches(bbox2)
+        elif predicate == 'within':
+            result = bbox1.within(bbox2)
+        else:
+            raise RuntimeError(
+                'Invalid spatial query predicate: %s' % predicate)
+    except (AttributeError, ValueError, ReadingError):
+        result = False
+    return "true" if result else "false"
+
+
+def update_xpath(nsmap, xml, recprop):
+    """Update XML document XPath values"""
+
+    if isinstance(xml, six.binary_type) or isinstance(xml, six.text_type):
+        # serialize to lxml
+        xml = etree.fromstring(xml, PARSER)
+
+    recprop = eval(recprop)
+    nsmap = eval(nsmap)
+    try:
+        nodes = xml.xpath(recprop['rp']['xpath'], namespaces=nsmap)
+        if len(nodes) > 0:  # matches
+            for node1 in nodes:
+                if node1.text != recprop['value']:  # values differ, update
+                    node1.text = recprop['value']
+    except Exception as err:
+        print(err)
+        raise RuntimeError('ERROR: %s' % str(err))
+
+    return etree.tostring(xml)
+
+
+def get_geometry_area(geometry):
+    """Derive area of a given geometry"""
+    try:
+        if geometry is not None:
+            return str(loads(geometry).area)
+        return '0'
+    except:
+        return '0'
+
+
+def get_spatial_overlay_rank(target_geometry, query_geometry):
+    """Derive spatial overlay rank for geospatial search as per Lanfear (2006)
+    http://pubs.usgs.gov/of/2006/1279/2006-1279.pdf"""
+
+    #TODO: Add those parameters to config file
+    kt = 1.0
+    kq = 1.0
+    if target_geometry is not None and query_geometry is not None:
+        try:
+            q_geom = loads(query_geometry)
+            t_geom = loads(target_geometry)
+            Q = q_geom.area
+            T = t_geom.area
+            if any(item == 0.0 for item in [Q, T]):
+                LOGGER.warning('Geometry has no area')
+                return '0'
+            X = t_geom.intersection(q_geom).area
+            if kt == 1.0 and kq == 1.0:
+                LOGGER.debug('Spatial Rank: %s', str((X/Q)*(X/T)))
+                return str((X/Q)*(X/T))
+            else:
+                LOGGER.debug('Spatial Rank: %s', str(((X/Q)**kq)*((X/T)**kt)))
+                return str(((X/Q)**kq)*((X/T)**kt))
+        except Exception as err:
+            LOGGER.warning('Cannot derive spatial overlay ranking %s', err)
+            return '0'
+    return '0'
+
diff --git a/pycsw/core/util.py b/pycsw/core/util.py
index b8b25fd..94b41aa 100644
--- a/pycsw/core/util.py
+++ b/pycsw/core/util.py
@@ -3,9 +3,11 @@
 #
 # Authors: Tom Kralidis <tomkralidis at gmail.com>
 #          Angelos Tzotsos <tzotsos at gmail.com>
+#          Ricardo Garcia Silva <ricardo.garcia.silva at gmail.com>
 #
 # Copyright (c) 2015 Tom Kralidis
 # Copyright (c) 2015 Angelos Tzotsos
+# Copyright (c) 2017 Ricardo Garcia Silva
 #
 # Permission is hereby granted, free of charge, to any person
 # obtaining a copy of this software and associated documentation
@@ -30,41 +32,54 @@
 #
 # =================================================================
 
-import time
 import datetime
 import logging
+import time
+
+import six
 from six.moves.urllib.request import Request, urlopen
+from six.moves.urllib.parse import urlparse
 from shapely.wkt import loads
 from owslib.util import http_post
-from pycsw.core.etree import etree
 
-from six import binary_type, text_type
+from pycsw.core.etree import etree, PARSER
+
 LOGGER = logging.getLogger(__name__)
 
-#Global variables for spatial ranking algorithm
+# Global variables for spatial ranking algorithm
 ranking_enabled = False
 ranking_pass = False
 ranking_query_geometry = ''
 
 
-PARSER = etree.XMLParser(resolve_entities=False)
-
 def get_today_and_now():
     """Get the date, right now, in ISO8601"""
     return time.strftime('%Y-%m-%dT%H:%M:%SZ', time.localtime())
 
 
 def datetime2iso8601(value):
-    """Return a datetime value as ISO8601"""
-    if value is None:
-        return None
-    if isinstance(value, datetime.date):
-        return value.strftime('%Y-%m-%d')
-    if value.hour == 0 and value.minute == 0 and value.second == 0:
-        # YYYY-MM-DD only
-        return value.strftime('%Y-%m-%d')
-    else:
-        return value.strftime('%Y-%m-%dT%H:%M:%SZ')
+    """Return a datetime value as ISO8601
+
+    Parameters
+    ----------
+    value: datetime.date or datetime.datetime
+        The temporal value to be converted
+
+    Returns
+    -------
+    str
+        A string with the temporal value in ISO8601 format.
+
+    """
+
+    if isinstance(value, datetime.datetime):
+        if value == value.replace(hour=0, minute=0, second=0, microsecond=0):
+            result = value.strftime("%Y-%m-%d")
+        else:
+            result = value.strftime("%Y-%m-%dT%H:%M:%SZ")
+    else:  # value is a datetime.date
+        result = value.strftime('%Y-%m-%d')
+    return result
 
 
 def get_time_iso2unix(isotime):
@@ -74,285 +89,179 @@ def get_time_iso2unix(isotime):
 
 
 def get_version_integer(version):
-    """Get an integer of the OGC version value x.y.z"""
-    if version is not None:  # split and make integer
-        xyz = version.split('.')
-        if len(xyz) != 3:
-            return -1
-        try:
-            return int(xyz[0]) * 10000 + int(xyz[1]) * 100 + int(xyz[2])
-        except Exception as err:
-            raise RuntimeError('%s' % str(err))
-    else:  # not a valid version string
-        return -1
-
-
-def find_exml(val, attrib=False):
-    """Test that the XML value exists, return value, else return None"""
-    if val is not None:
-        if attrib:  # it's an XML attribute
-            return val
-        else:  # it's an XML value
-            return val.text
-    else:
-        return None
+    """Get an integer of the OGC version value x.y.z
 
+    In case of an invalid version string this returns -1.
 
-def nspath_eval(xpath, nsmap):
-    """Return an etree friendly xpath"""
-    out = []
-    for chunks in xpath.split('/'):
-        namespace, element = chunks.split(':')
-        out.append('{%s}%s' % (nsmap[namespace], element))
-    return '/'.join(out)
+    Parameters
+    ----------
+    version: str
+        The version string that is to be transformed into an integer
 
+    Returns
+    -------
+    int
+        The transformed version
 
-def xmltag_split(tag):
-    """Return XML element bare tag name (without prefix)"""
-    try:
-        return tag.split('}')[1]
-    except:
-        return tag
+    Raises
+    ------
+    RuntimeError
+        When the input version is neither a string or None
 
+    """
 
-def xmltag_split2(tag, namespaces, colon=False):
-    """Return XML namespace prefix of element"""
     try:
-        nsuri = tag.split('}')[0].split('{')[1]
-        nsprefix = [key for key, value in namespaces.items()
-                    if value == nsuri]
-        value = nsprefix[0]
-        if colon:
-            return '%s:' % nsprefix[0]
+        xyz = version.split('.')
+        if len(xyz) == 3:
+            result = int(xyz[0]) * 10000 + int(xyz[1]) * 100 + int(xyz[2])
         else:
-            return nsprefix[0]
-    except:
-        return ''
+            result = -1
+    except AttributeError as err:
+        raise RuntimeError('%s' % str(err))
+    return result
 
 
-def wkt2geom(wkt, bounds=True):
-    """return Shapely geometry object based on WKT/EWKT"""
+def nspath_eval(xpath, nsmap):
+    """Return an etree friendly xpath.
 
-    geometry = None
+    This function converts XPath expressions that use prefixes into
+    their full namespace. This is the form expected by lxml [1]_.
 
-    if wkt.find('SRID') != -1:
-        wkt = wkt.split(';')[-1]
+    Parameters
+    ----------
+    xpath: str
+        The XPath expression to be converted
+    nsmap: dict
 
-    geometry = loads(wkt)
+    Returns
+    -------
+    str
+        The XPath expression using namespaces instead of prefixes.
 
-    if bounds:
-        return geometry.envelope.bounds
-    else:
-        return geometry
+    References
+    ----------
+    .. [1] http://lxml.de/tutorial.html#namespaces
 
+    """
 
-def bbox2wktpolygon(bbox):
-    """Return OGC WKT Polygon of a simple bbox string"""
-    tmp = bbox.split(',')
-    minx = float(tmp[0])
-    miny = float(tmp[1])
-    maxx = float(tmp[2])
-    maxy = float(tmp[3])
-    return 'POLYGON((%.2f %.2f, %.2f %.2f, %.2f %.2f, %.2f %.2f, %.2f %.2f))' \
-        % (minx, miny, minx, maxy, maxx, maxy, maxx, miny, minx, miny)
+    out = []
+    for node in xpath.split('/'):
+        chunks = node.split(":")
+        if len(chunks) == 2:
+            prefix, element = node.split(':')
+            out.append('{%s}%s' % (nsmap[prefix], element))
+        elif len(chunks) == 1:
+            out.append(node)
+        else:
+            raise RuntimeError("Invalid XPath expression: {0}".format(xpath))
+    return '/'.join(out)
 
 
-def query_spatial(bbox_data_wkt, bbox_input_wkt, predicate, distance):
-    """perform spatial query"""
+def wktenvelope2bbox(envelope):
+    """returns bbox string of WKT ENVELOPE definition"""
 
-    if bbox_data_wkt is None or bbox_input_wkt is None:
-        return 'false'
+    tmparr = [x.strip() for x in envelope.split('(')[1].split(')')[0].split(',')]
+    bbox = '%s,%s,%s,%s' % (tmparr[0], tmparr[3], tmparr[1], tmparr[2])
+    return bbox
 
-    if predicate in ['beyond', 'dwithin'] and distance == 'false':
-        return 'false'
 
-    if bbox_data_wkt.find('SRID') != -1:  # it's EWKT; chop off 'SRID=\d+;'
-        bbox1 = loads(bbox_data_wkt.split(';')[-1])
-    else:
-        bbox1 = loads(bbox_data_wkt)
-
-    bbox2 = loads(bbox_input_wkt)
-
-    # map query to Shapely Binary Predicates:
-    if predicate == 'bbox':
-        result = bbox1.intersects(bbox2)
-    elif predicate == 'beyond':
-        result = bbox1.distance(bbox2) > float(distance)
-    elif predicate == 'contains':
-        result = bbox1.contains(bbox2)
-    elif predicate == 'crosses':
-        result = bbox1.crosses(bbox2)
-    elif predicate == 'disjoint':
-        result = bbox1.disjoint(bbox2)
-    elif predicate == 'dwithin':
-        result = bbox1.distance(bbox2) <= float(distance)
-    elif predicate == 'equals':
-        result = bbox1.equals(bbox2)
-    elif predicate == 'intersects':
-        result = bbox1.intersects(bbox2)
-    elif predicate == 'overlaps':
-        if bbox1.intersects(bbox2) and not bbox1.touches(bbox2):
-            result = True
-        else:
-            result = False
-    elif predicate == 'touches':
-        result = bbox1.touches(bbox2)
-    elif predicate == 'within':
-        result = bbox1.within(bbox2)
-    else:
-        raise RuntimeError('Invalid spatial query predicate: %s' % predicate)
+def wkt2geom(ewkt, bounds=True):
+    """Return Shapely geometry object based on WKT/EWKT
 
-    if result:
-        return 'true'
-    else:
-        return 'false'
+    Parameters
+    ----------
+    ewkt: str
+        The geometry to convert, in Extended Well-Known Text format. More info
+        on this format at [1]_
+    bounds: bool
+        Whether to return only the bounding box of the geometry as a tuple or
+        the full shapely geometry instance
 
+    Returns
+    -------
+    shapely.geometry.base.BaseGeometry or tuple
+        Depending on the value of the ``bounds`` parameter, returns either 
+        the shapely geometry instance or a tuple with the bounding box.
 
-def get_geometry_area(geometry):
-    """Derive area of a given geometry"""
-    try:
-        if geometry is not None:
-            return str(loads(geometry).area)
-        return '0'
-    except:
-        return '0'
-
-def get_spatial_overlay_rank(target_geometry, query_geometry):
-    """Derive spatial overlay rank for geospatial search as per Lanfear (2006)
-    http://pubs.usgs.gov/of/2006/1279/2006-1279.pdf"""
-
-    from shapely.geometry.base import BaseGeometry
-    #TODO: Add those parameters to config file
-    kt = 1.0
-    kq = 1.0
-    if target_geometry is not None and query_geometry is not None:
-        try:
-            q_geom = loads(query_geometry)
-            t_geom = loads(target_geometry)
-            Q = q_geom.area
-            T = t_geom.area
-            if any(item == 0.0 for item in [Q, T]):
-                    LOGGER.warn('Geometry has no area')
-                    return '0'
-            X = t_geom.intersection(q_geom).area
-            if kt == 1.0 and kq == 1.0:
-                LOGGER.debug('Spatial Rank: %s', str((X/Q)*(X/T)))
-                return str((X/Q)*(X/T))
-            else:
-                LOGGER.debug('Spatial Rank: %s', str(((X/Q)**kq)*((X/T)**kt)))
-                return str(((X/Q)**kq)*((X/T)**kt))
-        except Exception as err:
-                LOGGER.warn('Cannot derive spatial overlay ranking %s', err)
-                return '0'
-    return '0'
-
-def bbox_from_polygons(bboxs):
-    """Derive an aggregated bbox from n polygons"""
-
-    from shapely.geometry import MultiPolygon
-
-    polys = []
-    for bbx in bboxs:
-        polys.append(loads(bbx))
+    References
+    ----------
+    .. [1] http://postgis.net/docs/ST_GeomFromEWKT.html
 
-    try:
-        bbx = MultiPolygon(polys).bounds
-        bstr = '%.2f,%.2f,%.2f,%.2f' % (bbx[0], bbx[1], bbx[2], bbx[3])
-        return bbox2wktpolygon(bstr)
-    except Exception as err:
-        raise RuntimeError('Cannot aggregate polygons: %s' % str(err))
+    """
 
+    wkt = ewkt.split(";")[-1] if ewkt.find("SRID") != -1 else ewkt
+    if wkt.startswith('ENVELOPE'):
+        wkt = bbox2wktpolygon(wktenvelope2bbox(wkt))
+    geometry = loads(wkt)
+    return geometry.envelope.bounds if bounds else geometry
 
-def update_xpath(nsmap, xml, recprop):
-    """Update XML document XPath values"""
 
-    if isinstance(xml, binary_type) or isinstance(xml, text_type):
-        # serialize to lxml
-        xml = etree.fromstring(xml, PARSER)
+def bbox2wktpolygon(bbox):
+    """Return OGC WKT Polygon of a simple bbox string
 
-    recprop = eval(recprop)
-    nsmap = eval(nsmap)
-    try:
-        nodes = xml.xpath(recprop['rp']['xpath'], namespaces=nsmap)
-        if len(nodes) > 0:  # matches
-            for node1 in nodes:
-                if node1.text != recprop['value']:  # values differ, update
-                    node1.text = recprop['value']
-    except Exception as err:
-        print(err)
-        raise RuntimeError('ERROR: %s' % str(err))
-
-    return etree.tostring(xml)
-
-
-def transform_mappings(queryables, typename, reverse=False):
-    """transform metadata model mappings"""
-    if reverse:  # from csw:Record
-        for qbl in queryables.keys():
-            if qbl in typename.values():
-                tmp = next(k for k, v in typename.items() if v == qbl)
-                val = queryables[tmp]
-                queryables[qbl] = {}
-                queryables[qbl]['xpath'] = val['xpath']
-                queryables[qbl]['dbcol'] = val['dbcol']
-    else:  # to csw:Record
-        for qbl in queryables.keys():
-            if qbl in typename.keys():
-                queryables[qbl] = queryables[qbl]
+    Parameters
+    ----------
+    bbox: str
+        The bounding box to convert to WKT.
 
+    Returns
+    -------
+    str
+        The bounding box's Well-Known Text representation.
 
-def get_anytext(bag):
-    """
-    generate bag of text for free text searches
-    accepts list of words, string of XML, or etree.Element
     """
 
-    if isinstance(bag, list):  # list of words
-        return ' '.join([_f for _f in bag if _f]).strip()
-    else:  # xml
-        if isinstance(bag, binary_type) or isinstance(bag, text_type):
-            # serialize to lxml
-            bag = etree.fromstring(bag, PARSER)
-        # get all XML element content
-        return ' '.join([value.strip() for value in bag.xpath('//text()')])
+    if bbox.startswith('ENVELOPE'):
+        bbox = wktenvelope2bbox(bbox)
+    minx, miny, maxx, maxy = [float(coord) for coord in bbox.split(",")]
+    return 'POLYGON((%.2f %.2f, %.2f %.2f, %.2f %.2f, %.2f %.2f, %.2f %.2f))' \
+        % (minx, miny, minx, maxy, maxx, maxy, maxx, miny, minx, miny)
 
 
-def xml2dict(xml_string, namespaces):
-    """Convert an lxml object to a dictionary"""
+def transform_mappings(queryables, typename):
+    """Transform metadata model mappings
 
-    import xmltodict
+    Parameters
+    ----------
+    queryables: dict
+    typename: dict
 
-    namespaces_reverse = dict((v, k) for k, v in namespaces.items())
+    """
 
-    return xmltodict.parse(xml_string, process_namespaces=True,
-                           namespaces=namespaces_reverse)
+    for item in queryables:
+        try:
+            matching_typename = [key for key, value in typename.items() if
+                                 value == item][0]
+            queryable_value = queryables[matching_typename]
+            queryables[item] = {
+                "xpath": queryable_value["xpath"],
+                "dbcol": queryable_value["dbcol"],
+            }
+        except IndexError:
+            pass
 
 
 def getqattr(obj, name):
-    """get value of an object, safely"""
+    """Get value of an object, safely"""
+    result = None
     try:
-        value = getattr(obj, name)
-        if hasattr(value, '__call__'):  # function generated value
-            LOGGER.debug('attribute is a function')
-            if name.find('link') != -1:  # list of link tuple quadruplets
-                LOGGER.debug('attribute is a link')
-                return _linkify(value())
-            return value()
-        elif (isinstance(value, datetime.datetime)
-              or isinstance(value, datetime.date)):  # datetime object
-            LOGGER.debug('attribute is a date')
-            return datetime2iso8601(value)
-        return value
-    except:
-        return None
-
-
-def _linkify(value):
-    """create link format"""
-    out = []
-    for link in value:
-        out.append(','.join(list(link)))
-    return '^'.join(out)
+        item = getattr(obj, name)
+        value = item()
+        if "link" in name:  # create link format
+            links = []
+            for link in value:
+                links.append(','.join(list(link)))
+            result = '^'.join(links)
+        else:
+            result = value
+    except TypeError:  # item is not callable
+        try:
+            result = datetime2iso8601(item)
+        except AttributeError:  # item is not date(time)
+            result = item
+    except AttributeError:  # obj does not have a name property
+        pass
+    return result
 
 
 def http_request(method, url, request=None, timeout=30):
@@ -364,41 +273,42 @@ def http_request(method, url, request=None, timeout=30):
         request.add_header('User-Agent', 'pycsw (http://pycsw.org/)')
         return urlopen(request, timeout=timeout).read()
 
+
 def bind_url(url):
     """binds an HTTP GET query string endpoint"""
-    if url.find('?') == -1: # like http://host/wms
-        binder = '?'
-
-    # if like http://host/wms?foo=bar& or http://host/wms?foo=bar
-    if url.find('=') != -1:
-        if url.find('&', -1) != -1: # like http://host/wms?foo=bar&
-            binder = ''
-        else: # like http://host/wms?foo=bar
-            binder = '&'
-
-    # if like http://host/wms?foo
-    if url.find('?') != -1:
-        if url.find('?', -1) != -1: # like http://host/wms?
-            binder = ''
-        elif url.find('&', -1) == -1: # like http://host/wms?foo=bar
-            binder = '&'
-    return '%s%s' % (url, binder)
+    parsed_url = urlparse(url)
+    if parsed_url.query == "":
+        binder = "?"
+    elif parsed_url.query.endswith("&"):
+        binder = ""
+    else:
+        binder = "&"
+    return "".join((parsed_url.geturl(), binder))
+
 
 def ip_in_network_cidr(ip, net):
     """decipher whether IP is within CIDR range"""
-    ipaddr = int(''.join([ '%02x' % int(x) for x in ip.split('.') ]), 16)
+    ipaddr = int(
+        ''.join(['%02x' % int(x) for x in ip.split('.')]),
+        16
+    )
     netstr, bits = net.split('/')
-    netaddr = int(''.join([ '%02x' % int(x) for x in netstr.split('.') ]), 16)
+    netaddr = int(
+        ''.join(['%02x' % int(x) for x in netstr.split('.')]),
+        16
+    )
     mask = (0xffffffff << (32 - int(bits))) & 0xffffffff
     return (ipaddr & mask) == (netaddr & mask)
 
+
 def ipaddress_in_whitelist(ipaddress, whitelist):
-    """
-    decipher whether IP is in IP whitelist
+    """decipher whether IP is in IP whitelist
+
     IP whitelist is a list supporting:
     - single IP address (e.g. 192.168.0.1)
     - IP range using CIDR (e.g. 192.168.0/22)
     - IP range using subnet wildcard (e.g. 192.168.0.*, 192.168.*)
+
     """
 
     if ipaddress in whitelist:
@@ -413,29 +323,18 @@ def ipaddress_in_whitelist(ipaddress, whitelist):
                         return True
     return False
 
-def sniff_table(table):
-    """Checks whether repository.table is a schema namespaced"""
-    schema = None
-    table = table
-    if table.find('.') != - 1:
-        schema, table = table.split('.')
-    return [schema, table]
-
-
-def validate_4326(bbox_list):
-    ''' Helper function to validate 4326 '''
 
-    is_valid = False
-
-    if ((-180.0 <= float(bbox_list[0]) <= 180.0) and
-        (-90.0 <= float(bbox_list[1]) <= 90.0) and
-        (-180.0 <= float(bbox_list[2]) <= 180.0) and
-        (-90.0 <= float(bbox_list[3]) <= 90.0)):
-        is_valid = True
-
-    return is_valid
-
-def get_elapsed_time(begin, end):
-    ''' Helper function to calculate elapsed time in milliseconds'''
+def get_anytext(bag):
+    """
+    generate bag of text for free text searches
+    accepts list of words, string of XML, or etree.Element
+    """
 
-    return int((end - begin) * 1000)
+    if isinstance(bag, list):  # list of words
+        return ' '.join([_f for _f in bag if _f]).strip()
+    else:  # xml
+        if isinstance(bag, six.binary_type) or isinstance(bag, six.text_type):
+            # serialize to lxml
+            bag = etree.fromstring(bag, PARSER)
+        # get all XML element content
+        return ' '.join([value.strip() for value in bag.xpath('//text()')])
diff --git a/pycsw/oaipmh.py b/pycsw/oaipmh.py
index 39282ce..3b65ac0 100644
--- a/pycsw/oaipmh.py
+++ b/pycsw/oaipmh.py
@@ -117,7 +117,7 @@ class OAIPMH(object):
     def request(self, kvp):
         """process OAI-PMH request"""
         kvpout = {'service': 'CSW', 'version': '2.0.2', 'mode': 'oaipmh'}
-        LOGGER.debug('Incoming kvp: %s' % kvp)
+        LOGGER.debug('Incoming kvp: %s', kvp)
         if 'verb' in kvp:
             if 'metadataprefix' in kvp:
                 self.metadata_prefix = kvp['metadataprefix']
@@ -127,7 +127,7 @@ class OAIPMH(object):
                     kvpout['outputschema'] = kvp['metadataprefix']
             else:
                 self.metadata_prefix = 'csw-record'
-            LOGGER.info('metadataPrefix: %s' % self.metadata_prefix)
+            LOGGER.debug('metadataPrefix: %s', self.metadata_prefix)
             if kvp['verb'] in ['ListRecords', 'ListIdentifiers', 'GetRecord']:
                 kvpout['request'] = 'GetRecords'
                 kvpout['resulttype'] = 'results'
@@ -154,7 +154,7 @@ class OAIPMH(object):
 
 
                 start = end = None
-                LOGGER.info('Scanning temporal parameters')
+                LOGGER.debug('Scanning temporal parameters')
                 if 'from' in kvp:
                     start = 'dc:date >= %s' % kvp['from']
                 if 'until' in kvp:
@@ -168,7 +168,7 @@ class OAIPMH(object):
                         time_query = end
                     kvpout['constraintlanguage'] = 'CQL_TEXT'
                     kvpout['constraint'] = time_query
-        LOGGER.debug('Resulting parameters: %s' % kvpout)
+        LOGGER.debug('Resulting parameters: %s', kvpout)
         return kvpout
 
     def response(self, response, kvp, repository, server_url):
@@ -181,7 +181,7 @@ class OAIPMH(object):
 
         node = etree.Element(util.nspath_eval('oai:OAI-PMH', self.namespaces), nsmap=self.namespaces)
         node.set(util.nspath_eval('xsi:schemaLocation', self.namespaces), '%s http://www.openarchives.org/OAI/2.0/OAI-PMH.xsd' % self.namespaces['oai'])
-        LOGGER.info(etree.tostring(node))
+        LOGGER.debug(etree.tostring(node))
 
         etree.SubElement(node, util.nspath_eval('oai:responseDate', self.namespaces)).text = util.get_today_and_now()
         etree.SubElement(node, util.nspath_eval('oai:request', self.namespaces), attrib=kvp).text = url
@@ -194,7 +194,7 @@ class OAIPMH(object):
             etree.SubElement(node, util.nspath_eval('oai:error', self.namespaces), code='badArgument').text = 'Unknown verb \'%s\'' % kvp['verb']
             return node
 
-        if util.xmltag_split(response.tag) == 'ExceptionReport':
+        if etree.QName(response).localname == 'ExceptionReport':
             etree.SubElement(node, util.nspath_eval('oai:error', self.namespaces), code='badArgument').text = response.xpath('//ows:ExceptionText|//ows20:ExceptionText', namespaces=self.context.namespaces)[0].text
             return node
 
diff --git a/pycsw/ogc/csw/csw2.py b/pycsw/ogc/csw/csw2.py
index d959d10..bd3d403 100644
--- a/pycsw/ogc/csw/csw2.py
+++ b/pycsw/ogc/csw/csw2.py
@@ -42,6 +42,7 @@ from pycsw.ogc.csw.cql import cql2fes1
 from pycsw.plugins.profiles import profile as pprofile
 import pycsw.plugins.outputschemas
 from pycsw.core import config, log, metadata, util
+from pycsw.core.formats.fmt_json import xml2dict
 from pycsw.ogc.fes import fes1
 import logging
 
@@ -112,7 +113,7 @@ class Csw2(object):
         metadata_main = dict(self.parent.config.items('metadata:main'))
 
         if serviceidentification:
-            LOGGER.debug('Writing section ServiceIdentification.')
+            LOGGER.info('Writing section ServiceIdentification')
 
             serviceidentification = etree.SubElement(node, \
             util.nspath_eval('ows:ServiceIdentification',
@@ -159,7 +160,7 @@ class Csw2(object):
             metadata_main.get('identification_accessconstraints', 'missing')
 
         if serviceprovider:
-            LOGGER.debug('Writing section ServiceProvider.')
+            LOGGER.info('Writing section ServiceProvider')
             serviceprovider = etree.SubElement(node,
             util.nspath_eval('ows:ServiceProvider', self.parent.context.namespaces))
 
@@ -261,7 +262,7 @@ class Csw2(object):
             metadata_main.get('contact_role', 'missing')
 
         if operationsmetadata:
-            LOGGER.debug('Writing section OperationsMetadata.')
+            LOGGER.info('Writing section OperationsMetadata')
             operationsmetadata = etree.SubElement(node,
             util.nspath_eval('ows:OperationsMetadata',
             self.parent.context.namespaces))
@@ -359,7 +360,7 @@ class Csw2(object):
                         operationsmetadata.append(ecnode)
 
         # always write out Filter_Capabilities
-        LOGGER.debug('Writing section Filter_Capabilities.')
+        LOGGER.info('Writing section Filter_Capabilities')
         fltcaps = etree.SubElement(node,
         util.nspath_eval('ogc:Filter_Capabilities', self.parent.context.namespaces))
 
@@ -467,7 +468,7 @@ class Csw2(object):
                 return self.exceptionreport('InvalidParameterValue',
                 'typename', 'Typename not qualified: %s' % typename)
             if typename == 'csw:Record':   # load core schema
-                LOGGER.debug('Writing csw:Record schema.')
+                LOGGER.info('Writing csw:Record schema')
                 schemacomponent = etree.SubElement(node,
                 util.nspath_eval('csw:SchemaComponent', self.parent.context.namespaces),
                 schemaLanguage='XMLSCHEMA',
@@ -508,7 +509,7 @@ class Csw2(object):
 
         if 'parametername' in self.parent.kvp:
             for pname in self.parent.kvp['parametername'].split(','):
-                LOGGER.debug('Parsing parametername %s.' % pname)
+                LOGGER.info('Parsing parametername %s', pname)
                 domainvalue = etree.SubElement(node,
                 util.nspath_eval('csw:DomainValues', self.parent.context.namespaces),
                 type='csw:Record')
@@ -533,7 +534,7 @@ class Csw2(object):
 
         if 'propertyname' in self.parent.kvp:
             for pname in self.parent.kvp['propertyname'].split(','):
-                LOGGER.debug('Parsing propertyname %s.' % pname)
+                LOGGER.info('Parsing propertyname %s', pname)
 
                 if pname.find('/') == 0:  # it's an XPath
                     pname2 = pname
@@ -562,10 +563,9 @@ class Csw2(object):
                 self.parent.context.namespaces)).text = pname
 
                 try:
-                    LOGGER.debug(
+                    LOGGER.info(
                     'Querying repository property %s, typename %s, \
-                    domainquerytype %s.' % \
-                    (pname2, dvtype, self.parent.domainquerytype))
+                    domainquerytype %s',  pname2, dvtype, self.parent.domainquerytype)
 
                     count = False
 
@@ -576,7 +576,7 @@ class Csw2(object):
                     results = self.parent.repository.query_domain(
                     pname2, dvtype, self.parent.domainquerytype, count)
 
-                    LOGGER.debug('Results: %s' % str(len(results)))
+                    LOGGER.debug('Results: %d', len(results))
 
                     if self.parent.domainquerytype == 'range':
                         rangeofvalues = etree.SubElement(domainvalue,
@@ -606,8 +606,9 @@ class Csw2(object):
                                 util.nspath_eval('csw:Value',
                                 self.parent.context.namespaces)).text = val
                 except Exception as err:
-                    LOGGER.debug('No results for propertyname %s: %s.' %
-                    (pname2, str(err)))
+                    # here we fail silently back to the client because
+                    # CSW tells us to
+                    LOGGER.exception('No results for propertynames')
         return node
 
     def getrecords(self):
@@ -715,7 +716,7 @@ class Csw2(object):
             tmp_filter = opensearch.kvp2filterxml(self.parent.kvp, self.parent.context)
             if tmp_filter is not "":
                 self.parent.kvp['constraint'] = tmp_filter
-                LOGGER.debug('OpenSearch Geo/Time parameters to Filter: %s.' % self.parent.kvp['constraint'])
+                LOGGER.debug('OpenSearch Geo/Time parameters to Filter: %s.', self.parent.kvp['constraint'])
 
         if self.parent.requesttype == 'GET':
             if 'constraint' in self.parent.kvp:
@@ -734,7 +735,7 @@ class Csw2(object):
                 if self.parent.kvp['constraintlanguage'] == 'CQL_TEXT':
                     tmp = self.parent.kvp['constraint']
                     try:
-                        LOGGER.debug('Transforming CQL into fes1')
+                        LOGGER.info('Transforming CQL into fes1')
                         LOGGER.debug('CQL: %s', tmp)
                         self.parent.kvp['constraint'] = {}
                         self.parent.kvp['constraint']['type'] = 'filter'
@@ -742,9 +743,9 @@ class Csw2(object):
                         self.parent.kvp['constraint']['where'], self.parent.kvp['constraint']['values'] = fes1.parse(cql,
                         self.parent.repository.queryables['_all'], self.parent.repository.dbtype,
                         self.parent.context.namespaces, self.parent.orm, self.parent.language['text'], self.parent.repository.fts)
+                        self.parent.kvp['constraint']['_dict'] = xml2dict(etree.tostring(cql), self.parent.context.namespaces)
                     except Exception as err:
-                        LOGGER.error('Invalid CQL query %s', tmp)
-                        LOGGER.error('Error message: %s', err, exc_info=True)
+                        LOGGER.exception('Invalid CQL query %s', tmp)
                         return self.exceptionreport('InvalidParameterValue',
                         'constraint', 'Invalid Filter syntax')
                 elif self.parent.kvp['constraintlanguage'] == 'FILTER':
@@ -752,12 +753,11 @@ class Csw2(object):
                     try:
                         schema = os.path.join(self.parent.config.get('server', 'home'),
                         'core', 'schemas', 'ogc', 'filter', '1.1.0', 'filter.xsd')
-                        LOGGER.debug('Validating Filter %s.' %
-                        self.parent.kvp['constraint'])
+                        LOGGER.info('Validating Filter %s', self.parent.kvp['constraint'])
                         schema = etree.XMLSchema(file=schema)
                         parser = etree.XMLParser(schema=schema, resolve_entities=False)
                         doc = etree.fromstring(self.parent.kvp['constraint'], parser)
-                        LOGGER.debug('Filter is valid XML.')
+                        LOGGER.debug('Filter is valid XML')
                         self.parent.kvp['constraint'] = {}
                         self.parent.kvp['constraint']['type'] = 'filter'
                         self.parent.kvp['constraint']['where'], self.parent.kvp['constraint']['values'] = \
@@ -765,11 +765,11 @@ class Csw2(object):
                         self.parent.repository.queryables['_all'],
                         self.parent.repository.dbtype,
                         self.parent.context.namespaces, self.parent.orm, self.parent.language['text'], self.parent.repository.fts)
+                        self.parent.kvp['constraint']['_dict'] = xml2dict(etree.tostring(doc), self.parent.context.namespaces)
                     except Exception as err:
                         errortext = \
                         'Exception: document not valid.\nError: %s.' % str(err)
-
-                        LOGGER.debug(errortext)
+                        LOGGER.exception(errortext)
                         return self.exceptionreport('InvalidParameterValue',
                         'constraint', 'Invalid Filter query: %s' % errortext)
             else:
@@ -778,7 +778,7 @@ class Csw2(object):
         if 'sortby' not in self.parent.kvp:
             self.parent.kvp['sortby'] = None
         elif 'sortby' in self.parent.kvp and self.parent.requesttype == 'GET':
-            LOGGER.debug('Sorted query specified.')
+            LOGGER.debug('Sorted query specified')
             tmp = self.parent.kvp['sortby']
             self.parent.kvp['sortby'] = {}
 
@@ -813,9 +813,9 @@ class Csw2(object):
 
         # query repository
         LOGGER.debug('Querying repository with constraint: %s,\
-        sortby: %s, typenames: %s, maxrecords: %s, startposition: %s.' %
-        (self.parent.kvp['constraint'], self.parent.kvp['sortby'], self.parent.kvp['typenames'],
-        self.parent.kvp['maxrecords'], self.parent.kvp['startposition']))
+        sortby: %s, typenames: %s, maxrecords: %s, startposition: %s',
+        self.parent.kvp['constraint'], self.parent.kvp['sortby'], self.parent.kvp['typenames'],
+        self.parent.kvp['maxrecords'], self.parent.kvp['startposition'])
 
         try:
             matched, results = self.parent.repository.query(
@@ -824,8 +824,8 @@ class Csw2(object):
             maxrecords=self.parent.kvp['maxrecords'],
             startposition=int(self.parent.kvp['startposition'])-1)
         except Exception as err:
-            LOGGER.debug('Invalid query syntax.  Query: %s', self.parent.kvp['constraint'])
-            LOGGER.debug('Invalid query syntax.  Result: %s', err)
+            LOGGER.exception('Invalid query syntax.  Query: %s', self.parent.kvp['constraint'])
+            LOGGER.exception('Invalid query syntax.  Result: %s', err)
             return self.exceptionreport('InvalidParameterValue', 'constraint',
             'Invalid query syntax')
 
@@ -836,7 +836,7 @@ class Csw2(object):
             self.parent.kvp['distributedsearch'] and self.parent.kvp['hopcount'] > 0):
             # do distributed search
 
-            LOGGER.debug('DistributedSearch specified (hopCount: %s).' %
+            LOGGER.debug('DistributedSearch specified (hopCount: %s).',
             self.parent.kvp['hopcount'])
 
             from owslib.csw import CatalogueServiceWeb
@@ -844,7 +844,7 @@ class Csw2(object):
             for fedcat in \
             self.parent.config.get('server', 'federatedcatalogues').split(','):
                 LOGGER.debug('Performing distributed search on federated \
-                catalogue: %s.' % fedcat)
+                catalogue: %s.', fedcat)
                 remotecsw = CatalogueServiceWeb(fedcat, skip_caps=True)
                 try:
                     remotecsw.getrecords2(xml=self.parent.request,
@@ -853,7 +853,7 @@ class Csw2(object):
                     if hasattr(remotecsw, 'results'):
                         LOGGER.debug(
                         'Distributed search results from catalogue \
-                        %s: %s.' % (fedcat, remotecsw.results))
+                        %s: %s.', fedcat, remotecsw.results)
 
                         remotecsw_matches = int(remotecsw.results['matches'])
                         plural = 's' if remotecsw_matches != 1 else ''
@@ -868,12 +868,12 @@ class Csw2(object):
                     error_string = 'remote CSW %s returned exception: ' % fedcat
                     dsresults.append(etree.Comment(
                     ' %s\n\n%s ' % (error_string, err)))
-                    LOGGER.debug(str(err))
+                    LOGGER.exception(error_string)
                 except Exception as err:
                     error_string = 'remote CSW %s returned error: ' % fedcat
                     dsresults.append(etree.Comment(
                     ' %s\n\n%s ' % (error_string, err)))
-                    LOGGER.debug(str(err))
+                    LOGGER.exception(error_string)
 
         if int(matched) == 0:
             returned = nextrecord = '0'
@@ -889,8 +889,8 @@ class Csw2(object):
                     nextrecord = str(int(self.parent.kvp['startposition']) + \
                     int(self.parent.kvp['maxrecords']))
 
-        LOGGER.debug('Results: matched: %s, returned: %s, next: %s.' % \
-        (matched, returned, nextrecord))
+        LOGGER.debug('Results: matched: %s, returned: %s, next: %s',
+        matched, returned, nextrecord)
 
         node = etree.Element(util.nspath_eval('csw:GetRecordsResponse',
         self.parent.context.namespaces),
@@ -922,7 +922,7 @@ class Csw2(object):
 
         if 'where' not in self.parent.kvp['constraint'] \
         and self.parent.kvp['resulttype'] is None:
-            LOGGER.debug('Empty result set returned.')
+            LOGGER.debug('Empty result set returned')
             return node
 
         if self.parent.kvp['resulttype'] == 'hits':
@@ -934,8 +934,8 @@ class Csw2(object):
                 max1 = len(results)
             else:
                 max1 = int(self.parent.kvp['startposition']) + (int(self.parent.kvp['maxrecords'])-1)
-            LOGGER.debug('Presenting records %s - %s.' %
-            (self.parent.kvp['startposition'], max1))
+            LOGGER.info('Presenting records %s - %s',
+            self.parent.kvp['startposition'], max1)
 
             for res in results:
                 try:
@@ -957,9 +957,11 @@ class Csw2(object):
                                 typename = self.parent.profiles['loaded'][prof].typename
                                 break
 
-                        util.transform_mappings(self.parent.repository.queryables['_all'],
-                        self.parent.context.model['typenames'][typename]\
-                        ['mappings']['csw:Record'], reverse=True)
+                        util.transform_mappings(
+                            self.parent.repository.queryables['_all'],
+                            self.parent.context.model['typenames'][typename][
+                                'mappings']['csw:Record']
+                        )
 
                         searchresults.append(self._write_record(
                         res, self.parent.repository.queryables['_all']))
@@ -1038,11 +1040,11 @@ class Csw2(object):
         (self.parent.context.namespaces['csw'], self.parent.config.get('server', 'ogc_schemas_base'))
 
         # query repository
-        LOGGER.debug('Querying repository with ids: %s.' % self.parent.kvp['id'][0])
+        LOGGER.info('Querying repository with ids: %s', self.parent.kvp['id'][0])
         results = self.parent.repository.query_ids(self.parent.kvp['id'])
 
         if raw:  # GetRepositoryItem request
-            LOGGER.debug('GetRepositoryItem request.')
+            LOGGER.debug('GetRepositoryItem request')
             if len(results) > 0:
                 return etree.fromstring(util.getqattr(results[0],
                 self.parent.context.md_core_model['mappings']['pycsw:XML']), self.parent.context.parser)
@@ -1067,9 +1069,11 @@ class Csw2(object):
                         break
 
                 if typename is not None:
-                    util.transform_mappings(self.parent.repository.queryables['_all'],
-                    self.parent.context.model['typenames'][typename]\
-                    ['mappings']['csw:Record'], reverse=True)
+                    util.transform_mappings(
+                        self.parent.repository.queryables['_all'],
+                        self.parent.context.model['typenames'][typename][
+                            'mappings']['csw:Record']
+                    )
 
                 node.append(self._write_record(
                 result, self.parent.repository.queryables['_all']))
@@ -1112,7 +1116,7 @@ class Csw2(object):
 
         insertresults = []
 
-        LOGGER.debug('Transaction list: %s' % self.parent.kvp['transactions'])
+        LOGGER.debug('Transaction list: %s', self.parent.kvp['transactions'])
 
         for ttype in self.parent.kvp['transactions']:
             if ttype['type'] == 'insert':
@@ -1120,11 +1124,12 @@ class Csw2(object):
                     record = metadata.parse_record(self.parent.context,
                     ttype['xml'], self.parent.repository)[0]
                 except Exception as err:
+                    LOGGER.exception('Transaction (insert) failed')
                     return self.exceptionreport('NoApplicableCode', 'insert',
                     'Transaction (insert) failed: record parsing failed: %s' \
                     % str(err))
 
-                LOGGER.debug('Transaction operation: %s' % record)
+                LOGGER.debug('Transaction operation: %s', record)
 
                 if not hasattr(record,
                 self.parent.context.md_core_model['mappings']['pycsw:Identifier']):
@@ -1160,14 +1165,12 @@ class Csw2(object):
                         % str(err))
 
                     # query repository to see if record already exists
-                    LOGGER.debug('checking if record exists (%s)' % \
-                    identifier)
+                    LOGGER.info('checking if record exists (%s)', identifier)
 
                     results = self.parent.repository.query_ids(ids=[identifier])
 
                     if len(results) == 0:
-                        LOGGER.debug('id %s does not exist in repository' % \
-                        identifier)
+                        LOGGER.debug('id %s does not exist in repository', identifier)
                     else:  # existing record, it's an update
                         try:
                             self.parent.repository.update(record)
@@ -1196,13 +1199,13 @@ class Csw2(object):
                             rp['rp']= \
                             self.parent.repository.queryables['_all'][rp['name']]
 
-                    LOGGER.debug('Record Properties: %s.' %
-                    ttype['recordproperty'])
+                    LOGGER.debug('Record Properties: %s.', ttype['recordproperty'])
                     try:
                         updated += self.parent.repository.update(record=None,
                         recprops=ttype['recordproperty'],
                         constraint=ttype['constraint'])
                     except Exception as err:
+                        LOGGER.exception('Transaction (updated) failed')
                         return self.exceptionreport('NoApplicableCode',
                         'update',
                         'Transaction (update) failed: %s.' % str(err))
@@ -1260,26 +1263,26 @@ class Csw2(object):
         if (self.parent.kvp['resourcetype'].find('opengis.net') == -1 and
             self.parent.kvp['resourcetype'].find('urn:geoss:waf') == -1):
             # fetch content-based resource
-            LOGGER.debug('Fetching resource %s' % self.parent.kvp['source'])
+            LOGGER.debug('Fetching resource %s', self.parent.kvp['source'])
             try:
                 content = util.http_request('GET', self.parent.kvp['source'])
             except Exception as err:
                 errortext = 'Error fetching resource %s.\nError: %s.' % \
                 (self.parent.kvp['source'], str(err))
-                LOGGER.debug(errortext)
+                LOGGER.exception(errortext)
                 return self.exceptionreport('InvalidParameterValue', 'source',
                 errortext)
         else:  # it's a service URL
             content = self.parent.kvp['source']
             # query repository to see if service already exists
-            LOGGER.debug('checking if service exists (%s)' % content)
+            LOGGER.info('checking if service exists (%s)', content)
             results = self.parent.repository.query_source(content)
 
             if len(results) > 0:  # exists, keep identifier for update
                 LOGGER.debug('Service already exists, keeping identifier and results')
                 service_identifier = getattr(results[0], self.parent.context.md_core_model['mappings']['pycsw:Identifier'])
                 service_results = results
-                LOGGER.debug('Identifier is %s' % service_identifier)
+                LOGGER.debug('Identifier is %s', service_identifier)
             #    return self.exceptionreport('NoApplicableCode', 'source',
             #    'Insert failed: service %s already in repository' % content)
 
@@ -1291,6 +1294,7 @@ class Csw2(object):
                 ir = self.parent.repository.insert(self.parent.kvp['resourcetype'], self.parent.kvp['source'])
                 inserted = len(ir)
             except Exception as err:
+                LOGGER.exception('Harvest (insert) failed')
                 return self.exceptionreport('NoApplicableCode',
                 'source', 'Harvest (insert) failed: %s.' % str(err))
         else:
@@ -1308,7 +1312,7 @@ class Csw2(object):
             updated = 0
             ir = []
 
-            LOGGER.debug('Total Records parsed: %d' % len(records_parsed))
+            LOGGER.debug('Total Records parsed: %d', len(records_parsed))
             for record in records_parsed:
                 if self.parent.kvp['resourcetype'] == 'urn:geoss:waf':
                     src = record.source
@@ -1335,14 +1339,14 @@ class Csw2(object):
                 record_identifier = getattr(record, self.parent.context.md_core_model['mappings']['pycsw:Identifier'])
 
                 if record_type == 'service' and service_identifier is not None:  # service endpoint
-                    LOGGER.debug('Replacing service identifier from %s to %s' % (record_identifier, service_identifier))
+                    LOGGER.info('Replacing service identifier from %s to %s', record_identifier, service_identifier)
                     old_identifier = record_identifier
                     identifier = record_identifier = service_identifier
                 if (record_type != 'service' and service_identifier is not None
                     and old_identifier is not None):  # service resource
                     if record_identifier.find(old_identifier) != -1:
                         new_identifier = record_identifier.replace(old_identifier, service_identifier)
-                        LOGGER.debug('Replacing service resource identifier from %s to %s' % (record_identifier, new_identifier))
+                        LOGGER.debug('Replacing service resource identifier from %s to %s', record_identifier, new_identifier)
                         identifier = record_identifier = new_identifier
 
                 ir.append({'identifier': identifier, 'title': title})
@@ -1350,11 +1354,11 @@ class Csw2(object):
                 results = []
                 if not self.parent.config.has_option('repository', 'source'):
                     # query repository to see if record already exists
-                    LOGGER.debug('checking if record exists (%s)' % identifier)
+                    LOGGER.info('checking if record exists (%s)', identifier)
                     results = self.parent.repository.query_ids(ids=[identifier])
 
                     if len(results) == 0:  # check for service identifier
-                        LOGGER.debug('checking if service id exists (%s)' % service_identifier)
+                        LOGGER.info('checking if service id exists (%s)', service_identifier)
                         results = self.parent.repository.query_ids(ids=[service_identifier])
 
                 LOGGER.debug(str(results))
@@ -1543,12 +1547,13 @@ class Csw2(object):
 
         tmp = element.find(util.nspath_eval('ogc:Filter', self.parent.context.namespaces))
         if tmp is not None:
-            LOGGER.debug('Filter constraint specified.')
+            LOGGER.debug('Filter constraint specified')
             try:
                 query['type'] = 'filter'
                 query['where'], query['values'] = fes1.parse(tmp,
                 self.parent.repository.queryables['_all'], self.parent.repository.dbtype,
                 self.parent.context.namespaces, self.parent.orm, self.parent.language['text'], self.parent.repository.fts)
+                query['_dict'] = xml2dict(etree.tostring(tmp), self.parent.context.namespaces)
             except Exception as err:
                 return 'Invalid Filter request: %s' % err
 
@@ -1556,15 +1561,16 @@ class Csw2(object):
         if tmp is not None:
             LOGGER.debug('CQL specified: %s.', tmp.text)
             try:
-                LOGGER.debug('Transforming CQL into OGC Filter')
+                LOGGER.info('Transforming CQL into OGC Filter')
                 query['type'] = 'filter'
                 cql = cql2fes1(tmp.text, self.parent.context.namespaces)
                 query['where'], query['values'] = fes1.parse(cql,
                 self.parent.repository.queryables['_all'], self.parent.repository.dbtype,
                 self.parent.context.namespaces, self.parent.orm, self.parent.language['text'], self.parent.repository.fts)
+                query['_dict'] = xml2dict(etree.tostring(cql), self.parent.context.namespaces)
             except Exception as err:
-                LOGGER.error('Invalid CQL request: %s', tmp.text)
-                LOGGER.error('Error message: %s', err, exc_info=True)
+                LOGGER.exception('Invalid CQL request: %s', tmp.text)
+                LOGGER.exception('Error message: %s', err)
                 return 'Invalid CQL request'
         return query
 
@@ -1573,20 +1579,19 @@ class Csw2(object):
 
         request = {}
         try:
-            LOGGER.debug('Parsing %s.' % postdata)
+            LOGGER.info('Parsing %s', postdata)
             doc = etree.fromstring(postdata, self.parent.context.parser)
         except Exception as err:
             errortext = \
             'Exception: document not well-formed.\nError: %s.' % str(err)
-
-            LOGGER.debug(errortext)
+            LOGGER.exception(errortext)
             return errortext
 
         # if this is a SOAP request, get to SOAP-ENV:Body/csw:*
         if (doc.tag == util.nspath_eval('soapenv:Envelope',
             self.parent.context.namespaces)):
 
-            LOGGER.debug('SOAP request specified.')
+            LOGGER.debug('SOAP request specified')
             self.parent.soap = True
 
             doc = doc.find(
@@ -1612,7 +1617,7 @@ class Csw2(object):
             len(doc.xpath('//csw:Update/child::*',
             namespaces=self.parent.context.namespaces)) == 0:
 
-                LOGGER.debug('Validating %s.' % postdata)
+                LOGGER.info('Validating %s', postdata)
                 schema = etree.XMLSchema(file=schema)
                 parser = etree.XMLParser(schema=schema, resolve_entities=False)
                 if hasattr(self.parent, 'soap') and self.parent.soap:
@@ -1626,11 +1631,11 @@ class Csw2(object):
         except Exception as err:
             errortext = \
             'Exception: the document is not valid.\nError: %s' % str(err)
-            LOGGER.debug(errortext)
+            LOGGER.exception(errortext)
             return errortext
 
-        request['request'] = util.xmltag_split(doc.tag)
-        LOGGER.debug('Request operation %s specified.' % request['request'])
+        request['request'] = etree.QName(doc).localname
+        LOGGER.debug('Request operation %s specified.', request['request'])
         tmp = doc.find('.').attrib.get('service')
         if tmp is not None:
             request['service'] = tmp
@@ -1745,12 +1750,12 @@ class Csw2(object):
                     return 'Invalid Constraint: %s' % request['constraint']
             else:
                 LOGGER.debug('No csw:Constraint (ogc:Filter or csw:CqlText) \
-                specified.')
+                specified')
 
             tmp = doc.find(util.nspath_eval('csw:Query/ogc:SortBy',
                   self.parent.context.namespaces))
             if tmp is not None:
-                LOGGER.debug('Sorted query specified.')
+                LOGGER.debug('Sorted query specified')
                 request['sortby'] = {}
 
 
@@ -1769,7 +1774,7 @@ class Csw2(object):
                 except Exception as err:
                     errortext = \
                     'Invalid ogc:SortProperty/ogc:PropertyName: %s' % str(err)
-                    LOGGER.debug(errortext)
+                    LOGGER.exception(errortext)
                     return errortext
 
                 tmp2 =  tmp.find(util.nspath_eval(
diff --git a/pycsw/ogc/csw/csw3.py b/pycsw/ogc/csw/csw3.py
index d817f9d..f4db68d 100644
--- a/pycsw/ogc/csw/csw3.py
+++ b/pycsw/ogc/csw/csw3.py
@@ -41,6 +41,7 @@ from pycsw import oaipmh, opensearch, sru
 from pycsw.plugins.profiles import profile as pprofile
 import pycsw.plugins.outputschemas
 from pycsw.core import config, log, metadata, util
+from pycsw.core.formats.fmt_json import xml2dict
 from pycsw.ogc.fes import fes2
 import logging
 
@@ -64,7 +65,7 @@ class Csw3(object):
         languages = False
 
         # validate acceptformats
-        LOGGER.debug('Validating ows20:AcceptFormats')
+        LOGGER.info('Validating ows20:AcceptFormats')
         LOGGER.debug(self.parent.context.model['operations']['GetCapabilities']['parameters']['acceptFormats']['values'])
         if 'acceptformats' in self.parent.kvp:
             bfound = False
@@ -138,7 +139,7 @@ class Csw3(object):
         metadata_main = dict(self.parent.config.items('metadata:main'))
 
         if serviceidentification:
-            LOGGER.debug('Writing section ServiceIdentification.')
+            LOGGER.info('Writing section ServiceIdentification')
 
             serviceidentification = etree.SubElement(node, \
             util.nspath_eval('ows20:ServiceIdentification',
@@ -194,7 +195,7 @@ class Csw3(object):
             metadata_main.get('identification_accessconstraints', 'missing')
 
         if serviceprovider:
-            LOGGER.debug('Writing section ServiceProvider.')
+            LOGGER.info('Writing section ServiceProvider')
             serviceprovider = etree.SubElement(node,
             util.nspath_eval('ows20:ServiceProvider', self.parent.context.namespaces))
 
@@ -296,7 +297,7 @@ class Csw3(object):
             metadata_main.get('contact_role', 'missing')
 
         if operationsmetadata:
-            LOGGER.debug('Writing section OperationsMetadata.')
+            LOGGER.info('Writing section OperationsMetadata')
             operationsmetadata = etree.SubElement(node,
             util.nspath_eval('ows20:OperationsMetadata',
             self.parent.context.namespaces))
@@ -403,7 +404,7 @@ class Csw3(object):
                         operationsmetadata.append(ecnode)
 
         if languages:
-            LOGGER.debug('Writing section ows:Languages')
+            LOGGER.info('Writing section ows:Languages')
             langs = etree.SubElement(node,
             util.nspath_eval('ows20:Languages', self.parent.context.namespaces))
             etree.SubElement(langs,
@@ -413,7 +414,7 @@ class Csw3(object):
             return node
 
         # always write out Filter_Capabilities
-        LOGGER.debug('Writing section Filter_Capabilities.')
+        LOGGER.info('Writing section Filter_Capabilities')
         fltcaps = etree.SubElement(node,
         util.nspath_eval('fes20:Filter_Capabilities', self.parent.context.namespaces))
 
@@ -503,7 +504,7 @@ class Csw3(object):
 
         if 'parametername' in self.parent.kvp:
             for pname in self.parent.kvp['parametername'].split(','):
-                LOGGER.debug('Parsing parametername %s.' % pname)
+                LOGGER.info('Parsing parametername %s', pname)
                 domainvalue = etree.SubElement(node,
                 util.nspath_eval('csw30:DomainValues', self.parent.context.namespaces),
                 type='csw30:Record', resultType='available')
@@ -527,7 +528,7 @@ class Csw3(object):
 
         if 'valuereference' in self.parent.kvp:
             for pname in self.parent.kvp['valuereference'].split(','):
-                LOGGER.debug('Parsing valuereference %s.' % pname)
+                LOGGER.info('Parsing valuereference %s', pname)
 
                 if pname.find('/') == 0:  # it's an XPath
                     pname2 = pname
@@ -558,13 +559,13 @@ class Csw3(object):
                 try:
                     LOGGER.debug(
                     'Querying repository property %s, typename %s, \
-                    domainquerytype %s.' % \
-                    (pname2, dvtype, self.parent.domainquerytype))
+                    domainquerytype %s',
+                    pname2, dvtype, self.parent.domainquerytype)
 
                     results = self.parent.repository.query_domain(
                     pname2, dvtype, self.parent.domainquerytype, True)
 
-                    LOGGER.debug('Results: %s' % str(len(results)))
+                    LOGGER.debug('Results: %d', len(results))
 
                     if self.parent.domainquerytype == 'range':
                         rangeofvalues = etree.SubElement(domainvalue,
@@ -591,8 +592,9 @@ class Csw3(object):
                                 self.parent.context.namespaces),
                                 count=str(result[1])).text = result[0]
                 except Exception as err:
-                    LOGGER.debug('No results for propertyname %s: %s.' %
-                    (pname2, str(err)))
+                    # here we fail silently back to the client because
+                    # CSW tells us to
+                    LOGGER.exception('No results for propertyname')
         return node
 
     def getrecords(self):
@@ -611,7 +613,7 @@ class Csw3(object):
                 'elementsetname',
                 'Missing one of ElementSetName or ElementName parameter(s)')
 
-        if 'elementsetname' in self.parent.kvp and 'elementname' in self.parent.kvp:
+        if 'elementsetname' in self.parent.kvp and 'elementname' in self.parent.kvp and self.parent.kvp['elementname']:
             # mutually exclusive required
             return self.exceptionreport('NoApplicableCode',
             'elementsetname',
@@ -639,11 +641,11 @@ class Csw3(object):
             if 'outputformat' in self.parent.kvp:
                 LOGGER.debug(self.parent.kvp['outputformat'])
                 for ofmt in self.parent.environ['HTTP_ACCEPT'].split(','):
-                    LOGGER.debug('Comparing %s and %s', ofmt, self.parent.kvp['outputformat'])
+                    LOGGER.info('Comparing %s and %s', ofmt, self.parent.kvp['outputformat'])
                     if ofmt.split('/')[0] in self.parent.kvp['outputformat']:
                         LOGGER.debug('FOUND OUTPUT MATCH')
                         formats_match = True
-                if not formats_match:
+                if not formats_match and self.parent.environ['HTTP_ACCEPT'] != '*/*':
                     return self.exceptionreport('InvalidParameterValue',
                     'outputformat', 'HTTP Accept header (%s) and outputformat (%s) must agree' %
                     (self.parent.environ['HTTP_ACCEPT'], self.parent.kvp['outputformat']))
@@ -661,7 +663,7 @@ class Csw3(object):
             self.parent.kvp['outputformat'])
 
         if 'outputformat' in self.parent.kvp:
-            LOGGER.debug('Setting content type')
+            LOGGER.info('Setting content type')
             self.parent.contenttype = self.parent.kvp['outputformat']
             if self.parent.kvp['outputformat'] == 'application/atom+xml':
                 self.parent.kvp['outputschema'] = self.parent.context.namespaces['atom']
@@ -686,7 +688,7 @@ class Csw3(object):
             self.parent.kvp['typenames'] = ['csw:Record' if x=='Record' else x for x in self.parent.kvp['typenames'].split(',')]
 
         if 'namespace' in self.parent.kvp:
-            LOGGER.debug('resolving KVP namespace bindings')
+            LOGGER.info('resolving KVP namespace bindings')
             LOGGER.debug(self.parent.kvp['typenames'])
             self.parent.kvp['typenames'] = self.resolve_nsmap(self.parent.kvp['typenames'])
             if 'elementname' in self.parent.kvp:
@@ -742,7 +744,7 @@ class Csw3(object):
 
             if tmp_filter is not "":
                 self.parent.kvp['constraint'] = tmp_filter
-                LOGGER.debug('OpenSearch Geo/Time parameters to Filter: %s.' % self.parent.kvp['constraint'])
+                LOGGER.debug('OpenSearch Geo/Time parameters to Filter: %s.', self.parent.kvp['constraint'])
 
         if self.parent.requesttype == 'GET':
             if 'constraint' in self.parent.kvp:
@@ -761,7 +763,7 @@ class Csw3(object):
                 if self.parent.kvp['constraintlanguage'] == 'CQL_TEXT':
                     tmp = self.parent.kvp['constraint']
                     try:
-                        LOGGER.debug('Transforming CQL into fes1')
+                        LOGGER.info('Transforming CQL into fes1')
                         LOGGER.debug('CQL: %s', tmp)
                         self.parent.kvp['constraint'] = {}
                         self.parent.kvp['constraint']['type'] = 'filter'
@@ -769,9 +771,9 @@ class Csw3(object):
                         self.parent.kvp['constraint']['where'], self.parent.kvp['constraint']['values'] = fes1.parse(cql,
                         self.parent.repository.queryables['_all'], self.parent.repository.dbtype,
                         self.parent.context.namespaces, self.parent.orm, self.parent.language['text'], self.parent.repository.fts)
+                        self.parent.kvp['constraint']['_dict'] = xml2dict(etree.tostring(cql), self.parent.context.namespaces)
                     except Exception as err:
-                        LOGGER.error('Invalid CQL query %s', tmp)
-                        LOGGER.error('Error message: %s', err, exc_info=True)
+                        LOGGER.exception('Invalid CQL query %s', tmp)
                         return self.exceptionreport('InvalidParameterValue',
                         'constraint', 'Invalid Filter syntax')
                 elif self.parent.kvp['constraintlanguage'] == 'FILTER':
@@ -779,8 +781,7 @@ class Csw3(object):
                     try:
                         schema = os.path.join(self.parent.config.get('server', 'home'),
                         'core', 'schemas', 'ogc', 'filter', '1.1.0', 'filter.xsd')
-                        LOGGER.debug('Validating Filter %s.' %
-                        self.parent.kvp['constraint'])
+                        LOGGER.info('Validating Filter %s.', self.parent.kvp['constraint'])
                         schema = etree.XMLSchema(file=schema)
                         parser = etree.XMLParser(schema=schema, resolve_entities=False)
                         doc = etree.fromstring(self.parent.kvp['constraint'], parser)
@@ -792,11 +793,12 @@ class Csw3(object):
                         self.parent.repository.queryables['_all'],
                         self.parent.repository.dbtype,
                         self.parent.context.namespaces, self.parent.orm, self.parent.language['text'], self.parent.repository.fts)
+                        self.parent.kvp['constraint']['_dict'] = xml2dict(etree.tostring(doc), self.parent.context.namespaces)
                     except Exception as err:
                         errortext = \
-                        'Exception: document not valid.\nError: %s.' % str(err)
+                        'Exception: document not valid.\nError: %s' % str(err)
 
-                        LOGGER.debug(errortext)
+                        LOGGER.exception(errortext)
                         return self.exceptionreport('InvalidParameterValue',
                         'bbox', 'Invalid Filter query: %s' % errortext)
             else:
@@ -805,7 +807,7 @@ class Csw3(object):
         if 'sortby' not in self.parent.kvp:
             self.parent.kvp['sortby'] = None
         elif 'sortby' in self.parent.kvp and self.parent.requesttype == 'GET':
-            LOGGER.debug('Sorted query specified.')
+            LOGGER.debug('Sorted query specified')
             tmp = self.parent.kvp['sortby']
             self.parent.kvp['sortby'] = {}
 
@@ -840,7 +842,7 @@ class Csw3(object):
 
         if 'recordids' in self.parent.kvp and self.parent.kvp['recordids'] != '':
             # query repository
-            LOGGER.debug('Querying repository with RECORD ids: %s.' % self.parent.kvp['recordids'])
+            LOGGER.info('Querying repository with RECORD ids: %s', self.parent.kvp['recordids'])
             results = self.parent.repository.query_ids(self.parent.kvp['recordids'].split(','))
             matched = str(len(results))
             if len(results) == 0:
@@ -848,10 +850,10 @@ class Csw3(object):
                 'No records found for \'%s\'' % self.parent.kvp['recordids'])
         else:
             # query repository
-            LOGGER.debug('Querying repository with constraint: %s,\
-            sortby: %s, typenames: %s, maxrecords: %s, startposition: %s.' %
-            (self.parent.kvp['constraint'], self.parent.kvp['sortby'], self.parent.kvp['typenames'],
-            self.parent.kvp['maxrecords'], self.parent.kvp['startposition']))
+            LOGGER.info('Querying repository with constraint: %s,\
+            sortby: %s, typenames: %s, maxrecords: %s, startposition: %s.',
+            self.parent.kvp['constraint'], self.parent.kvp['sortby'], self.parent.kvp['typenames'],
+            self.parent.kvp['maxrecords'], self.parent.kvp['startposition'])
 
             try:
                 matched, results = self.parent.repository.query(
@@ -860,8 +862,8 @@ class Csw3(object):
                 maxrecords=self.parent.kvp['maxrecords'],
                 startposition=int(self.parent.kvp['startposition'])-1)
             except Exception as err:
-                LOGGER.debug('Invalid query syntax.  Query: %s', self.parent.kvp['constraint'])
-                LOGGER.debug('Invalid query syntax.  Result: %s', err)
+                LOGGER.exception('Invalid query syntax.  Query: %s', self.parent.kvp['constraint'])
+                LOGGER.exception('Invalid query syntax.  Result: %s', err)
                 return self.exceptionreport('InvalidParameterValue', 'constraint',
                 'Invalid query syntax')
 
@@ -879,8 +881,8 @@ class Csw3(object):
                     nextrecord = str(int(self.parent.kvp['startposition']) + \
                     int(self.parent.kvp['maxrecords']))
 
-        LOGGER.debug('Results: matched: %s, returned: %s, next: %s.' % \
-        (matched, returned, nextrecord))
+        LOGGER.debug('Results: matched: %s, returned: %s, next: %s',
+        matched, returned, nextrecord)
 
         node = etree.Element(util.nspath_eval('csw30:GetRecordsResponse',
         self.parent.context.namespaces),
@@ -913,7 +915,7 @@ class Csw3(object):
 
         #if 'where' not in self.parent.kvp['constraint'] \
         #and self.parent.kvp['resulttype'] is None:
-        #    LOGGER.debug('Empty result set returned.')
+        #    LOGGER.debug('Empty result set returned')
         #    return node
 
         if results is not None:
@@ -921,14 +923,15 @@ class Csw3(object):
                 max1 = len(results)
             else:
                 max1 = int(self.parent.kvp['startposition']) + (int(self.parent.kvp['maxrecords'])-1)
-            LOGGER.debug('Presenting records %s - %s.' %
-            (self.parent.kvp['startposition'], max1))
+            LOGGER.info('Presenting records %s - %s',
+            self.parent.kvp['startposition'], max1)
 
             for res in results:
                 try:
                     if (self.parent.kvp['outputschema'] ==
                         'http://www.opengis.net/cat/csw/3.0' and
-                        'csw:Record' in self.parent.kvp['typenames']):
+                        ('csw:Record' in self.parent.kvp['typenames'] or
+                         'csw30:Record' in self.parent.kvp['typenames'])):
                         # serialize csw:Record inline
                         searchresults.append(self._write_record(
                         res, self.parent.repository.queryables['_all']))
@@ -944,9 +947,11 @@ class Csw3(object):
                                 typename = self.parent.profiles['loaded'][prof].typename
                                 break
 
-                        util.transform_mappings(self.parent.repository.queryables['_all'],
-                        self.parent.context.model['typenames'][typename]\
-                        ['mappings']['csw:Record'], reverse=True)
+                        util.transform_mappings(
+                            self.parent.repository.queryables['_all'],
+                            self.parent.context.model['typenames'][typename][
+                                'mappings']['csw:Record']
+                        )
 
                         searchresults.append(self._write_record(
                         res, self.parent.repository.queryables['_all']))
@@ -969,15 +974,15 @@ class Csw3(object):
             self.parent.kvp['distributedsearch'] and self.parent.kvp['hopcount'] > 0):
             # do distributed search
 
-            LOGGER.debug('DistributedSearch specified (hopCount: %s).' %
+            LOGGER.debug('DistributedSearch specified (hopCount: %s)',
             self.parent.kvp['hopcount'])
 
             from owslib.csw import CatalogueServiceWeb
             from owslib.ows import ExceptionReport
             for fedcat in \
             self.parent.config.get('server', 'federatedcatalogues').split(','):
-                LOGGER.debug('Performing distributed search on federated \
-                catalogue: %s.' % fedcat)
+                LOGGER.info('Performing distributed search on federated \
+                catalogue: %s', fedcat)
                 try:
                     start_time = time()
                     remotecsw = CatalogueServiceWeb(fedcat, skip_caps=True)
@@ -1001,7 +1006,7 @@ class Csw3(object):
                         numberOfRecordsMatched=fedcat.results['matches'],
                         numberOfRecordsReturned=fedcat.results['returned'],
                         nextRecord=fedcat.results['nextrecord'],
-                        elapsedTime=str(util.get_elapsed_time(start_time, time())),
+                        elapsedTime=str(get_elapsed_time(start_time, time())),
                         status=get_resultset_status(
                             fedcat.results['matches'],
                             fedcat.results['nextrecord']))
@@ -1011,12 +1016,12 @@ class Csw3(object):
                     error_string = 'remote CSW %s returned exception: ' % fedcat
                     searchresults.append(etree.Comment(
                     ' %s\n\n%s ' % (error_string, err)))
-                    LOGGER.debug(str(err))
+                    LOGGER.exception(error_string)
                 except Exception as err:
                     error_string = 'remote CSW %s returned error: ' % fedcat
                     searchresults.append(etree.Comment(
                     ' %s\n\n%s ' % (error_string, err)))
-                    LOGGER.debug(str(err))
+                    LOGGER.exception(error_string)
 
 #        if len(dsresults) > 0:  # return DistributedSearch results
 #            for resultset in dsresults:
@@ -1025,7 +1030,7 @@ class Csw3(object):
 #                for rec in resultset:
 #                    searchresults.append(etree.fromstring(resultset[rec].xml, self.parent.context.parser))
 
-        searchresults.attrib['elapsedTime'] = str(util.get_elapsed_time(self.parent.process_time_start, time()))
+        searchresults.attrib['elapsedTime'] = str(get_elapsed_time(self.parent.process_time_start, time()))
 
         if 'responsehandler' in self.parent.kvp:  # process the handler
             self.parent._process_responsehandler(etree.tostring(node,
@@ -1051,7 +1056,7 @@ class Csw3(object):
             if 'outputformat' in self.parent.kvp:
                 LOGGER.debug(self.parent.kvp['outputformat'])
                 for ofmt in self.parent.environ['HTTP_ACCEPT'].split(','):
-                    LOGGER.debug('Comparing %s and %s', ofmt, self.parent.kvp['outputformat'])
+                    LOGGER.info('Comparing %s and %s', ofmt, self.parent.kvp['outputformat'])
                     if ofmt.split('/')[0] in self.parent.kvp['outputformat']:
                         LOGGER.debug('FOUND OUTPUT MATCH')
                         formats_match = True
@@ -1097,7 +1102,7 @@ class Csw3(object):
                 self.parent.kvp['elementsetname'])
 
         # query repository
-        LOGGER.debug('Querying repository with ids: %s.' % self.parent.kvp['id'])
+        LOGGER.info('Querying repository with ids: %s', self.parent.kvp['id'])
         results = self.parent.repository.query_ids([self.parent.kvp['id']])
 
         if raw:  # GetRepositoryItem request
@@ -1126,9 +1131,11 @@ class Csw3(object):
                         break
 
                 if typename is not None:
-                    util.transform_mappings(self.parent.repository.queryables['_all'],
-                    self.parent.context.model['typenames'][typename]\
-                    ['mappings']['csw:Record'], reverse=True)
+                    util.transform_mappings(
+                        self.parent.repository.queryables['_all'],
+                        self.parent.context.model['typenames'][typename][
+                            'mappings']['csw:Record']
+                    )
 
                 node = self._write_record( result, self.parent.repository.queryables['_all'])
             elif self.parent.kvp['outputschema'] in self.parent.outputschemas:  # use outputschema serializer
@@ -1173,7 +1180,7 @@ class Csw3(object):
 
         insertresults = []
 
-        LOGGER.debug('Transaction list: %s' % self.parent.kvp['transactions'])
+        LOGGER.debug('Transaction list: %s', self.parent.kvp['transactions'])
 
         for ttype in self.parent.kvp['transactions']:
             if ttype['type'] == 'insert':
@@ -1181,11 +1188,12 @@ class Csw3(object):
                     record = metadata.parse_record(self.parent.context,
                     ttype['xml'], self.parent.repository)[0]
                 except Exception as err:
+                    LOGGER.exception('Transaction (insert) failed')
                     return self.exceptionreport('NoApplicableCode', 'insert',
                     'Transaction (insert) failed: record parsing failed: %s' \
                     % str(err))
 
-                LOGGER.debug('Transaction operation: %s' % record)
+                LOGGER.debug('Transaction operation: %s', record)
 
                 if not hasattr(record,
                 self.parent.context.md_core_model['mappings']['pycsw:Identifier']):
@@ -1204,6 +1212,7 @@ class Csw3(object):
                     'title': getattr(record,
                     self.parent.context.md_core_model['mappings']['pycsw:Title'])})
                 except Exception as err:
+                    LOGGER.exception('Transaction (insert) failed')
                     return self.exceptionreport('NoApplicableCode',
                     'insert', 'Transaction (insert) failed: %s.' % str(err))
 
@@ -1221,14 +1230,12 @@ class Csw3(object):
                         % str(err))
 
                     # query repository to see if record already exists
-                    LOGGER.debug('checking if record exists (%s)' % \
-                    identifier)
+                    LOGGER.info('checking if record exists (%s)', identifier)
 
                     results = self.parent.repository.query_ids(ids=[identifier])
 
                     if len(results) == 0:
-                        LOGGER.debug('id %s does not exist in repository' % \
-                        identifier)
+                        LOGGER.debug('id %s does not exist in repository', identifier)
                     else:  # existing record, it's an update
                         try:
                             self.parent.repository.update(record)
@@ -1257,13 +1264,13 @@ class Csw3(object):
                             rp['rp']= \
                             self.parent.repository.queryables['_all'][rp['name']]
 
-                    LOGGER.debug('Record Properties: %s.' %
-                    ttype['recordproperty'])
+                    LOGGER.debug('Record Properties: %s', ttype['recordproperty'])
                     try:
                         updated += self.parent.repository.update(record=None,
                         recprops=ttype['recordproperty'],
                         constraint=ttype['constraint'])
                     except Exception as err:
+                        LOGGER.exception('Transaction (update) failed')
                         return self.exceptionreport('NoApplicableCode',
                         'update',
                         'Transaction (update) failed: %s.' % str(err))
@@ -1321,26 +1328,26 @@ class Csw3(object):
         if (self.parent.kvp['resourcetype'].find('opengis.net') == -1 and
             self.parent.kvp['resourcetype'].find('urn:geoss:waf') == -1):
             # fetch content-based resource
-            LOGGER.debug('Fetching resource %s' % self.parent.kvp['source'])
+            LOGGER.info('Fetching resource %s', self.parent.kvp['source'])
             try:
                 content = util.http_request('GET', self.parent.kvp['source'])
             except Exception as err:
                 errortext = 'Error fetching resource %s.\nError: %s.' % \
                 (self.parent.kvp['source'], str(err))
-                LOGGER.debug(errortext)
+                LOGGER.exception(errortext)
                 return self.exceptionreport('InvalidParameterValue', 'source',
                 errortext)
         else:  # it's a service URL
             content = self.parent.kvp['source']
             # query repository to see if service already exists
-            LOGGER.debug('checking if service exists (%s)' % content)
+            LOGGER.info('checking if service exists (%s)', content)
             results = self.parent.repository.query_source(content)
 
             if len(results) > 0:  # exists, keep identifier for update
                 LOGGER.debug('Service already exists, keeping identifier and results')
                 service_identifier = getattr(results[0], self.parent.context.md_core_model['mappings']['pycsw:Identifier'])
                 service_results = results
-                LOGGER.debug('Identifier is %s' % service_identifier)
+                LOGGER.debug('Identifier is %s', service_identifier)
             #    return self.exceptionreport('NoApplicableCode', 'source',
             #    'Insert failed: service %s already in repository' % content)
 
@@ -1352,6 +1359,7 @@ class Csw3(object):
                 ir = self.parent.repository.insert(self.parent.kvp['resourcetype'], self.parent.kvp['source'])
                 inserted = len(ir)
             except Exception as err:
+                LOGGER.exception('Harvest (insert) failed')
                 return self.exceptionreport('NoApplicableCode',
                 'source', 'Harvest (insert) failed: %s.' % str(err))
         else:
@@ -1369,7 +1377,7 @@ class Csw3(object):
             updated = 0
             ir = []
 
-            LOGGER.debug('Total Records parsed: %d' % len(records_parsed))
+            LOGGER.debug('Total Records parsed: %d', len(records_parsed))
             for record in records_parsed:
                 if self.parent.kvp['resourcetype'] == 'urn:geoss:waf':
                     src = record.source
@@ -1396,14 +1404,14 @@ class Csw3(object):
                 record_identifier = getattr(record, self.parent.context.md_core_model['mappings']['pycsw:Identifier'])
 
                 if record_type == 'service' and service_identifier is not None:  # service endpoint
-                    LOGGER.debug('Replacing service identifier from %s to %s' % (record_identifier, service_identifier))
+                    LOGGER.info('Replacing service identifier from %s to %s', record_identifier, service_identifier)
                     old_identifier = record_identifier
                     identifier = record_identifier = service_identifier
                 if (record_type != 'service' and service_identifier is not None
                     and old_identifier is not None):  # service resource
                     if record_identifier.find(old_identifier) != -1:
                         new_identifier = record_identifier.replace(old_identifier, service_identifier)
-                        LOGGER.debug('Replacing service resource identifier from %s to %s' % (record_identifier, new_identifier))
+                        LOGGER.info('Replacing service resource identifier from %s to %s', record_identifier, new_identifier)
                         identifier = record_identifier = new_identifier
 
                 ir.append({'identifier': identifier, 'title': title})
@@ -1411,11 +1419,11 @@ class Csw3(object):
                 results = []
                 if not self.parent.config.has_option('repository', 'source'):
                     # query repository to see if record already exists
-                    LOGGER.debug('checking if record exists (%s)' % identifier)
+                    LOGGER.info('checking if record exists (%s)', identifier)
                     results = self.parent.repository.query_ids(ids=[identifier])
 
                     if len(results) == 0:  # check for service identifier
-                        LOGGER.debug('checking if service id exists (%s)' % service_identifier)
+                        LOGGER.info('checking if service id exists (%s)', service_identifier)
                         results = self.parent.repository.query_ids(ids=[service_identifier])
 
                 LOGGER.debug(str(results))
@@ -1623,12 +1631,13 @@ class Csw3(object):
 
         tmp = element.find(util.nspath_eval('fes20:Filter', self.parent.context.namespaces))
         if tmp is not None:
-            LOGGER.debug('Filter constraint specified.')
+            LOGGER.debug('Filter constraint specified')
             try:
                 query['type'] = 'filter'
                 query['where'], query['values'] = fes2.parse(tmp,
                 self.parent.repository.queryables['_all'], self.parent.repository.dbtype,
                 self.parent.context.namespaces, self.parent.orm, self.parent.language['text'], self.parent.repository.fts)
+                query['_dict'] = xml2dict(etree.tostring(tmp), self.parent.context.namespaces)
             except Exception as err:
                 return 'Invalid Filter request: %s' % err
 
@@ -1636,15 +1645,16 @@ class Csw3(object):
         if tmp is not None:
             LOGGER.debug('CQL specified: %s.', tmp.text)
             try:
-                LOGGER.debug('Transforming CQL into OGC Filter')
+                LOGGER.info('Transforming CQL into OGC Filter')
                 query['type'] = 'filter'
                 cql = cql2fes1(tmp.text, self.parent.context.namespaces)
                 query['where'], query['values'] = fes1.parse(cql,
                 self.parent.repository.queryables['_all'], self.parent.repository.dbtype,
                 self.parent.context.namespaces, self.parent.orm, self.parent.language['text'], self.parent.repository.fts)
+                query['_dict'] = xml2dict(etree.tostring(cql), self.parent.context.namespaces)
             except Exception as err:
-                LOGGER.error('Invalid CQL request: %s', tmp.text)
-                LOGGER.error('Error message: %s', err, exc_info=True)
+                LOGGER.exception('Invalid CQL request: %s', tmp.text)
+                LOGGER.exception('Error message: %s', err)
                 return 'Invalid CQL request'
         return query
 
@@ -1653,27 +1663,26 @@ class Csw3(object):
 
         request = {}
         try:
-            LOGGER.debug('Parsing %s.' % postdata)
+            LOGGER.info('Parsing %s.', postdata)
             doc = etree.fromstring(postdata, self.parent.context.parser)
         except Exception as err:
             errortext = \
             'Exception: document not well-formed.\nError: %s.' % str(err)
-
-            LOGGER.debug(errortext)
+            LOGGER.exception(errortext)
             return errortext
 
         # if this is a SOAP request, get to SOAP-ENV:Body/csw:*
         if (doc.tag == util.nspath_eval('soapenv:Envelope',
             self.parent.context.namespaces)):
 
-            LOGGER.debug('SOAP request specified.')
+            LOGGER.debug('SOAP request specified')
             self.parent.soap = True
 
             doc = doc.find(
             util.nspath_eval('soapenv:Body',
             self.parent.context.namespaces)).xpath('child::*')[0]
 
-        xsd_filename = 'csw%s.xsd' % util.xmltag_split(doc.tag)
+        xsd_filename = 'csw%s.xsd' % etree.QName(doc).localname
         schema = os.path.join(self.parent.config.get('server', 'home'),
         'core', 'schemas', 'ogc', 'csw', '3.0', xsd_filename)
 
@@ -1687,7 +1696,7 @@ class Csw3(object):
             len(doc.xpath('//csw30:Update/child::*',
             namespaces=self.parent.context.namespaces)) == 0:
 
-                LOGGER.debug('Validating %s.' % postdata)
+                LOGGER.info('Validating %s', postdata)
                 schema = etree.XMLSchema(file=schema)
                 parser = etree.XMLParser(schema=schema, resolve_entities=False)
                 if hasattr(self.parent, 'soap') and self.parent.soap:
@@ -1695,17 +1704,17 @@ class Csw3(object):
                     doc = etree.fromstring(etree.tostring(doc), parser)
                 else:  # validate the request normally
                     doc = etree.fromstring(postdata, parser)
-                LOGGER.debug('Request is valid XML.')
+                LOGGER.debug('Request is valid XML')
             else:  # parse Transaction without validation
                 doc = etree.fromstring(postdata, self.parent.context.parser)
         except Exception as err:
             errortext = \
             'Exception: the document is not valid.\nError: %s' % str(err)
-            LOGGER.debug(errortext)
+            LOGGER.exception(errortext)
             return errortext
 
-        request['request'] = util.xmltag_split(doc.tag)
-        LOGGER.debug('Request operation %s specified.' % request['request'])
+        request['request'] = etree.QName(doc).localname
+        LOGGER.debug('Request operation %s specified.', request['request'])
         tmp = doc.find('.').attrib.get('service')
         if tmp is not None:
             request['service'] = tmp
@@ -1817,15 +1826,14 @@ class Csw3(object):
                     return 'Invalid Constraint: %s' % request['constraint']
             else:
                 LOGGER.debug('No csw30:Constraint (fes20:Filter or csw30:CqlText) \
-                specified.')
+                specified')
 
             tmp = doc.find(util.nspath_eval('csw30:Query/fes20:SortBy',
                   self.parent.context.namespaces))
             if tmp is not None:
-                LOGGER.debug('Sorted query specified.')
+                LOGGER.debug('Sorted query specified')
                 request['sortby'] = {}
 
-
                 try:
                     elname = tmp.find(util.nspath_eval(
                     'fes20:SortProperty/fes20:ValueReference',
@@ -1841,7 +1849,7 @@ class Csw3(object):
                 except Exception as err:
                     errortext = \
                     'Invalid fes20:SortProperty/fes20:ValueReference: %s' % str(err)
-                    LOGGER.debug(errortext)
+                    LOGGER.exception(errortext)
                     return errortext
 
                 tmp2 =  tmp.find(util.nspath_eval(
@@ -2162,3 +2170,9 @@ def get_resultset_status(matched, nextrecord):
        status = 'none'
 
     return status
+
+
+def get_elapsed_time(begin, end):
+    """Helper function to calculate elapsed time in milliseconds."""
+
+    return int((end - begin) * 1000)
diff --git a/pycsw/ogc/fes/fes1.py b/pycsw/ogc/fes/fes1.py
index 4b104a7..8091ce1 100644
--- a/pycsw/ogc/fes/fes1.py
+++ b/pycsw/ogc/fes/fes1.py
@@ -31,7 +31,9 @@
 # =================================================================
 
 import logging
+
 from pycsw.core import util
+from pycsw.core.etree import etree
 from pycsw.ogc.gml import gml3
 
 LOGGER = logging.getLogger(__name__)
@@ -79,8 +81,9 @@ def parse(element, queryables, dbtype, nsmap, orm='sqlalchemy', language='englis
 
     tmp = element.xpath('ogc:And|ogc:Or|ogc:Not', namespaces=nsmap)
     if len(tmp) > 0:  # this is binary logic query
-        boq = ' %s ' % util.xmltag_split(tmp[0].tag).lower()
-        LOGGER.debug('Binary logic detected; operator=%s' % boq)
+        element_name = etree.QName(tmp[0]).localname
+        boq = ' %s ' % element_name.lower()
+        LOGGER.debug('Binary logic detected; operator=%s', boq)
         tmp = tmp[0]
     else:
         tmp = element
@@ -146,7 +149,7 @@ def parse(element, queryables, dbtype, nsmap, orm='sqlalchemy', language='englis
                 pval = elem.find(util.nspath_eval('ogc:Literal', nsmap)).text
 
         com_op = _get_comparison_operator(elem)
-        LOGGER.debug('Comparison operator: %s' % com_op)
+        LOGGER.debug('Comparison operator: %s', com_op)
 
         # if this is a case insensitive search
         # then set the DB-specific LIKE comparison operator
@@ -235,20 +238,20 @@ def parse(element, queryables, dbtype, nsmap, orm='sqlalchemy', language='englis
             if child_not.tag in \
                 [util.nspath_eval('ogc:%s' % n, nsmap) for n in
                     MODEL['SpatialOperators']['values']]:
-                LOGGER.debug('ogc:Not / spatial operator detected: %s' % child.tag)
+                LOGGER.debug('ogc:Not / spatial operator detected: %s', child.tag)
                 queries.append("%s = %s" %
                                (_get_spatial_operator(
                                    queryables['pycsw:BoundingBox'],
                                    child.xpath('child::*')[0], dbtype, nsmap),
                                    boolean_false))
             else:
-                LOGGER.debug('ogc:Not / comparison operator detected: %s' % child.tag)
+                LOGGER.debug('ogc:Not / comparison operator detected: %s', child.tag)
                 queries.append('not %s' % _get_comparison_expression(child_not))
 
         elif child.tag in \
             [util.nspath_eval('ogc:%s' % n, nsmap) for n in
                 MODEL['SpatialOperators']['values']]:
-            LOGGER.debug('spatial operator detected: %s' % child.tag)
+            LOGGER.debug('spatial operator detected: %s', child.tag)
             if boq is not None and boq == ' not ':
                 # for ogc:Not spatial queries in PostGIS we must explictly
                 # test that pycsw:BoundingBox is null as well
@@ -277,9 +280,10 @@ def parse(element, queryables, dbtype, nsmap, orm='sqlalchemy', language='englis
             values.append(child.attrib.get('fid'))
         else:  # comparison operator
             LOGGER.debug('Comparison operator processing')
-            tagname = ' %s ' % util.xmltag_split(child.tag).lower()
+            child_tag_name = etree.QName(child).localname
+            tagname = ' %s ' % child_tag_name.lower()
             if tagname in [' or ', ' and ']:  # this is a nested binary logic query
-                LOGGER.debug('Nested binary logic detected; operator=%s' % tagname)
+                LOGGER.debug('Nested binary logic detected; operator=%s', tagname)
                 for child2 in child.xpath('child::*'):
                     queries_nested.append(_get_comparison_expression(child2))
                 queries.append('(%s)' % tagname.join(queries_nested))
@@ -313,9 +317,9 @@ def _get_spatial_operator(geomattr, element, dbtype, nsmap, postgis_geometry_col
     #make decision to apply spatial ranking to results
     set_spatial_ranking(geometry)
 
-    spatial_predicate = util.xmltag_split(element.tag).lower()
+    spatial_predicate = etree.QName(element).localname.lower()
 
-    LOGGER.debug('Spatial predicate: %s' % spatial_predicate)
+    LOGGER.debug('Spatial predicate: %s', spatial_predicate)
 
     if dbtype == 'mysql':  # adjust spatial query for MySQL
         LOGGER.debug('Adjusting spatial query for MySQL')
@@ -382,7 +386,8 @@ def _get_spatial_operator(geomattr, element, dbtype, nsmap, postgis_geometry_col
 def _get_comparison_operator(element):
     """return the SQL operator based on Filter query"""
 
-    return MODEL['ComparisonOperators']['ogc:%s' % util.xmltag_split(element.tag)]['opvalue']
+    element_name = etree.QName(element).localname
+    return MODEL['ComparisonOperators']['ogc:%s' % element_name]['opvalue']
 
 def set_spatial_ranking(geometry):
     """Given that we have a spatial query in ogc:Filter we check the type of geometry
diff --git a/pycsw/ogc/fes/fes2.py b/pycsw/ogc/fes/fes2.py
index ce2271c..9e07296 100644
--- a/pycsw/ogc/fes/fes2.py
+++ b/pycsw/ogc/fes/fes2.py
@@ -31,7 +31,9 @@
 # =================================================================
 
 import logging
+
 from pycsw.core import util
+from pycsw.core.etree import etree
 from pycsw.ogc.gml import gml3
 
 LOGGER = logging.getLogger(__name__)
@@ -98,8 +100,9 @@ def parse(element, queryables, dbtype, nsmap, orm='sqlalchemy', language='englis
 
     tmp = element.xpath('ogc:And|ogc:Or|ogc:Not', namespaces=nsmap)
     if len(tmp) > 0:  # this is binary logic query
-        boq = ' %s ' % util.xmltag_split(tmp[0].tag).lower()
-        LOGGER.debug('Binary logic detected; operator=%s' % boq)
+        element_name = etree.QName(tmp[0]).localname
+        boq = ' %s ' % element_name.lower()
+        LOGGER.debug('Binary logic detected; operator=%s', boq)
         tmp = tmp[0]
     else:
         tmp = element
@@ -165,7 +168,7 @@ def parse(element, queryables, dbtype, nsmap, orm='sqlalchemy', language='englis
                 pval = elem.find(util.nspath_eval('ogc:Literal', nsmap)).text
 
         com_op = _get_comparison_operator(elem)
-        LOGGER.debug('Comparison operator: %s' % com_op)
+        LOGGER.debug('Comparison operator: %s', com_op)
 
         # if this is a case insensitive search
         # then set the DB-specific LIKE comparison operator
@@ -254,20 +257,20 @@ def parse(element, queryables, dbtype, nsmap, orm='sqlalchemy', language='englis
             if child_not.tag in \
                 [util.nspath_eval('ogc:%s' % n, nsmap) for n in
                     MODEL['SpatialOperators']['values']]:
-                LOGGER.debug('ogc:Not / spatial operator detected: %s' % child.tag)
+                LOGGER.debug('ogc:Not / spatial operator detected: %s', child.tag)
                 queries.append("%s = %s" %
                                (_get_spatial_operator(
                                    queryables['pycsw:BoundingBox'],
                                    child.xpath('child::*')[0], dbtype, nsmap),
                                    boolean_false))
             else:
-                LOGGER.debug('ogc:Not / comparison operator detected: %s' % child.tag)
+                LOGGER.debug('ogc:Not / comparison operator detected: %s', child.tag)
                 queries.append('not %s' % _get_comparison_expression(child_not))
 
         elif child.tag in \
             [util.nspath_eval('ogc:%s' % n, nsmap) for n in
                 MODEL['SpatialOperators']['values']]:
-            LOGGER.debug('spatial operator detected: %s' % child.tag)
+            LOGGER.debug('spatial operator detected: %s', child.tag)
             if boq is not None and boq == ' not ':
                 # for ogc:Not spatial queries in PostGIS we must explictly
                 # test that pycsw:BoundingBox is null as well
@@ -296,9 +299,10 @@ def parse(element, queryables, dbtype, nsmap, orm='sqlalchemy', language='englis
             values.append(child.attrib.get('fid'))
         else:  # comparison operator
             LOGGER.debug('Comparison operator processing')
-            tagname = ' %s ' % util.xmltag_split(child.tag).lower()
+            child_tag_name = etree.QName(child).localname
+            tagname = ' %s ' % child_tag_name.lower()
             if tagname in [' or ', ' and ']:  # this is a nested binary logic query
-                LOGGER.debug('Nested binary logic detected; operator=%s' % tagname)
+                LOGGER.debug('Nested binary logic detected; operator=%s', tagname)
                 for child2 in child.xpath('child::*'):
                     queries_nested.append(_get_comparison_expression(child2))
                 queries.append('(%s)' % tagname.join(queries_nested))
@@ -332,9 +336,9 @@ def _get_spatial_operator(geomattr, element, dbtype, nsmap, postgis_geometry_col
     #make decision to apply spatial ranking to results
     set_spatial_ranking(geometry)
 
-    spatial_predicate = util.xmltag_split(element.tag).lower()
+    spatial_predicate = etree.QName(element).localname.lower()
 
-    LOGGER.debug('Spatial predicate: %s' % spatial_predicate)
+    LOGGER.debug('Spatial predicate: %s', spatial_predicate)
 
     if dbtype == 'mysql':  # adjust spatial query for MySQL
         LOGGER.debug('Adjusting spatial query for MySQL')
@@ -401,7 +405,8 @@ def _get_spatial_operator(geomattr, element, dbtype, nsmap, postgis_geometry_col
 def _get_comparison_operator(element):
     """return the SQL operator based on Filter query"""
 
-    return MODEL['ComparisonOperators']['ogc:%s' % util.xmltag_split(element.tag)]['opvalue']
+    element_name = etree.QName(element).localname
+    return MODEL['ComparisonOperators']['ogc:%s' % element_name]['opvalue']
 
 def set_spatial_ranking(geometry):
     """Given that we have a spatial query in ogc:Filter we check the type of geometry
diff --git a/pycsw/ogc/gml/gml3.py b/pycsw/ogc/gml/gml3.py
index 990dca3..a80c454 100644
--- a/pycsw/ogc/gml/gml3.py
+++ b/pycsw/ogc/gml/gml3.py
@@ -31,7 +31,9 @@
 from six.moves import zip
 import logging
 from owslib import crs
+
 from pycsw.core import util
+from pycsw.core.etree import etree
 
 LOGGER = logging.getLogger(__name__)
 
@@ -81,10 +83,10 @@ class Geometry(object):
             LOGGER.debug('geometry srsName detected')
             self.crs = crs.Crs(operand.attrib['srsName'])
         else:
-            LOGGER.debug('setting default geometry srsName %s' % DEFAULT_SRS)
+            LOGGER.debug('setting default geometry srsName %s', DEFAULT_SRS)
             self.crs = DEFAULT_SRS
 
-        self.type = util.xmltag_split(operand.tag)
+        self.type = etree.QName(operand).localname
 
         if self.type == 'Point':
             self._get_point()
@@ -100,12 +102,12 @@ class Geometry(object):
 
         # reproject data if needed
         if self.crs is not None and self.crs.code not in [4326, 'CRS84']:
-            LOGGER.debug('transforming geometry to 4326')
+            LOGGER.info('transforming geometry to 4326')
             try:
                 self.wkt = self.transform(self.crs.code, DEFAULT_SRS.code)
             except Exception as err:
-                raise RuntimeError('Reprojection error: Invalid srsName '
-                                   '"%s": %s' % (self.crs.id, str(err)))
+                LOGGER.exception('Coordinate transformation error')
+                raise RuntimeError('Reprojection error: Invalid srsName')
 
     def _get_point(self):
         """Parse gml:Point"""
@@ -188,7 +190,7 @@ class Geometry(object):
         from shapely.geometry import Point, LineString, Polygon
         from shapely.wkt import loads
 
-        LOGGER.debug('Transforming geometry from %s to %s' % (src, dest))
+        LOGGER.info('Transforming geometry from %s to %s', src, dest)
 
         vertices = []
 
diff --git a/pycsw/opensearch.py b/pycsw/opensearch.py
index b7acf34..9cc39f6 100644
--- a/pycsw/opensearch.py
+++ b/pycsw/opensearch.py
@@ -56,7 +56,7 @@ class OpenSearch(object):
     def response_csw2opensearch(self, element, cfg):
         """transform a CSW response into an OpenSearch response"""
 
-        root_tag = util.xmltag_split(element.tag)
+        root_tag = etree.QName(element).localname
         if root_tag == 'ExceptionReport':
             return element
 
@@ -78,7 +78,8 @@ class OpenSearch(object):
     def _csw2_2_os(self):
         """CSW 2.0.2 Capabilities to OpenSearch Description"""
 
-        if util.xmltag_split(self.exml.tag) == 'GetRecordsResponse':
+        operation_name = etree.QName(self.exml).localname
+        if operation_name == 'GetRecordsResponse':
 
             startindex = int(self.exml.xpath('//@nextRecord')[0]) - int(
                         self.exml.xpath('//@numberOfRecordsReturned')[0])
@@ -107,7 +108,7 @@ class OpenSearch(object):
             for rec in self.exml.xpath('//atom:entry',
                         namespaces=self.context.namespaces):
                 node.append(rec)
-        elif util.xmltag_split(self.exml.tag) == 'Capabilities':
+        elif operation_name == 'Capabilities':
             node = etree.Element(util.nspath_eval('os:OpenSearchDescription', self.namespaces), nsmap=self.namespaces)
             etree.SubElement(node, util.nspath_eval('os:ShortName', self.namespaces)).text = self.exml.xpath('//ows:Title', namespaces=self.context.namespaces)[0].text
             etree.SubElement(node, util.nspath_eval('os:LongName', self.namespaces)).text = self.exml.xpath('//ows:Title', namespaces=self.context.namespaces)[0].text
@@ -128,7 +129,7 @@ class OpenSearch(object):
             etree.SubElement(node, util.nspath_eval('os:Developer', self.namespaces)).text = self.exml.xpath('//ows:IndividualName', namespaces=self.context.namespaces)[0].text
             etree.SubElement(node, util.nspath_eval('os:Context', self.namespaces)).text = self.exml.xpath('//ows:ElectronicMailAddress', namespaces=self.context.namespaces)[0].text
             etree.SubElement(node, util.nspath_eval('os:Attribution', self.namespaces)).text = self.exml.xpath('//ows:ProviderName', namespaces=self.context.namespaces)[0].text
-        elif util.xmltag_split(self.exml.tag) == 'ExceptionReport':
+        elif operation_name == 'ExceptionReport':
             node = self.exml
         else:  # return Description document
             node = etree.Element(util.nspath_eval('os:Description', self.context.namespaces))
@@ -138,7 +139,8 @@ class OpenSearch(object):
     def _csw3_2_os(self):
         """CSW 3.0.0 Capabilities to OpenSearch Description"""
 
-        if util.xmltag_split(self.exml.tag) == 'GetRecordsResponse':
+        response_name = etree.QName(self.exml).localname
+        if response_name == 'GetRecordsResponse':
 
             startindex = int(self.exml.xpath('//@nextRecord')[0]) - int(
                         self.exml.xpath('//@numberOfRecordsReturned')[0])
@@ -177,7 +179,7 @@ class OpenSearch(object):
             for rec in self.exml.xpath('//atom:entry',
                         namespaces=self.context.namespaces):
                 node.append(rec)
-        elif util.xmltag_split(self.exml.tag) == 'Capabilities':
+        elif response_name == 'Capabilities':
             node = etree.Element(util.nspath_eval('os:OpenSearchDescription', self.namespaces), nsmap=self.namespaces)
             etree.SubElement(node, util.nspath_eval('os:ShortName', self.namespaces)).text = self.exml.xpath('//ows20:Title', namespaces=self.context.namespaces)[0].text[:16]
             etree.SubElement(node, util.nspath_eval('os:LongName', self.namespaces)).text = self.exml.xpath('//ows20:Title', namespaces=self.context.namespaces)[0].text
@@ -206,7 +208,7 @@ class OpenSearch(object):
             etree.SubElement(node, util.nspath_eval('os:Developer', self.namespaces)).text = self.exml.xpath('//ows20:IndividualName', namespaces=self.context.namespaces)[0].text
             etree.SubElement(node, util.nspath_eval('os:Contact', self.namespaces)).text = self.exml.xpath('//ows20:ElectronicMailAddress', namespaces=self.context.namespaces)[0].text
             etree.SubElement(node, util.nspath_eval('os:Attribution', self.namespaces)).text = self.exml.xpath('//ows20:ProviderName', namespaces=self.context.namespaces)[0].text
-        elif util.xmltag_split(self.exml.tag) == 'ExceptionReport':
+        elif response_name == 'ExceptionReport':
             node = self.exml
         else:  # GetRecordById output
             node = etree.Element(util.nspath_eval('atom:feed',
@@ -269,16 +271,16 @@ def kvp2filterxml(kvp, context):
         else:
             LOGGER.debug('Assuming 4326')
             env.attrib['srsName'] = 'urn:ogc:def:crs:OGC:1.3:CRS84'
-            if not util.validate_4326(bbox_list):
+            if not validate_4326(bbox_list):
                 msg = '4326 coordinates out of range: %s' % bbox_list
-                LOGGER.debug(msg)
+                LOGGER.error(msg)
                 raise RuntimeError(msg)
 
         try:
             el.text = "%s %s" % (bbox_list[0], bbox_list[1])
         except Exception as err:
             errortext = 'Exception: OpenSearch bbox not valid.\nError: %s.' % str(err)
-            LOGGER.debug(errortext)
+            LOGGER.exception(errortext)
         env.append(el)
         el = etree.Element(util.nspath_eval('gml:upperCorner',
                     context.namespaces))
@@ -286,7 +288,7 @@ def kvp2filterxml(kvp, context):
             el.text = "%s %s" % (bbox_list[2], bbox_list[3])
         except Exception as err:
             errortext = 'Exception: OpenSearch bbox not valid.\nError: %s.' % str(err)
-            LOGGER.debug(errortext)
+            LOGGER.exception(errortext)
         env.append(el)
         bbox_element.append(env)
 
@@ -385,7 +387,7 @@ def kvp2filterxml(kvp, context):
         else:
             # Error
             errortext = 'Exception: OpenSearch time not valid: %s.' % str(kvp['time'])
-            LOGGER.debug(errortext)
+            LOGGER.error(errortext)
 
     if par_count == 0:
         return ''
@@ -417,3 +419,14 @@ def kvp2filterxml(kvp, context):
     # Render etree to string XML
     LOGGER.debug(etree.tostring(root, encoding='unicode'))
     return etree.tostring(root, encoding='unicode')
+
+
+def validate_4326(bbox_list):
+    """Helper function to validate 4326."""
+    is_valid = False
+    if ((-180.0 <= float(bbox_list[0]) <= 180.0) and
+            (-90.0 <= float(bbox_list[1]) <= 90.0) and
+            (-180.0 <= float(bbox_list[2]) <= 180.0) and
+            (-90.0 <= float(bbox_list[3]) <= 90.0)):
+        is_valid = True
+    return is_valid
diff --git a/pycsw/plugins/profiles/apiso/apiso.py b/pycsw/plugins/profiles/apiso/apiso.py
index 4e34e93..0c16d14 100644
--- a/pycsw/plugins/profiles/apiso/apiso.py
+++ b/pycsw/plugins/profiles/apiso/apiso.py
@@ -393,9 +393,6 @@ class APISO(profile.Profile):
             # dump record as is and exit
             return etree.fromstring(xml_blob, self.context.parser)
 
-        if typename == 'csw:Record':  # transform csw:Record -> gmd:MD_Metadata model mappings
-            util.transform_mappings(queryables, self.repository['mappings']['csw:Record'])
-
         node = etree.Element(util.nspath_eval('gmd:MD_Metadata', self.namespaces))
         node.attrib[util.nspath_eval('xsi:schemaLocation', self.context.namespaces)] = \
         '%s %s/csw/2.0.2/profiles/apiso/1.0.0/apiso.xsd' % (self.namespace, self.ogc_schemas_base)
diff --git a/pycsw/plugins/profiles/ebrim/ebrim.py b/pycsw/plugins/profiles/ebrim/ebrim.py
index e801491..c08ff8a 100644
--- a/pycsw/plugins/profiles/ebrim/ebrim.py
+++ b/pycsw/plugins/profiles/ebrim/ebrim.py
@@ -133,9 +133,6 @@ class EBRIM(profile.Profile):
             # dump record as is and exit
             return etree.fromstring(util.getqattr(result, queryables['pycsw:XML']['dbcol']), self.context.parser)
 
-        if typename == 'csw:Record':  # transform csw:Record -> rim:RegistryObject model mappings
-            util.transform_mappings(queryables, self.repository['mappings']['csw:Record'])
-
         node = etree.Element(util.nspath_eval('rim:ExtrinsicObject', self.namespaces))
         node.attrib[util.nspath_eval('xsi:schemaLocation', self.context.namespaces)] = \
         '%s %s/csw/2.0.2/profiles/ebrim/1.0/csw-ebrim.xsd' % (self.namespaces['wrs'], self.ogc_schemas_base)
diff --git a/pycsw/plugins/repository/geonode/geonode_.py b/pycsw/plugins/repository/geonode/geonode_.py
deleted file mode 100644
index 559556a..0000000
--- a/pycsw/plugins/repository/geonode/geonode_.py
+++ /dev/null
@@ -1,150 +0,0 @@
-# -*- coding: utf-8 -*-
-# =================================================================
-#
-# Authors: Tom Kralidis <tomkralidis at gmail.com>
-#
-# Copyright (c) 2015 Tom Kralidis
-#
-# Permission is hereby granted, free of charge, to any person
-# obtaining a copy of this software and associated documentation
-# files (the "Software"), to deal in the Software without
-# restriction, including without limitation the rights to use,
-# copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the
-# Software is furnished to do so, subject to the following
-# conditions:
-#
-# The above copyright notice and this permission notice shall be
-# included in all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
-# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
-# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-# OTHER DEALINGS IN THE SOFTWARE.
-#
-# =================================================================
-
-from django.db import models
-from django.db import connection
-from django.db.models import Avg, Max, Min, Count
-from django.conf import settings
-
-from pycsw.core import util
-from geonode.base.models import ResourceBase
-
-class GeoNodeRepository(object):
-    ''' Class to interact with underlying repository '''
-    def __init__(self, context, repo_filter=None):
-        ''' Initialize repository '''
-
-        self.context = context
-        self.filter = repo_filter
-        self.fts = False
-
-        self.dbtype = settings.DATABASES['default']['ENGINE'].split('.')[-1]
-
-        # GeoNode PostgreSQL installs are PostGIS enabled
-        if self.dbtype == 'postgresql_psycopg2':
-            self.dbtype = 'postgresql+postgis+wkt'
-
-        if self.dbtype in ['sqlite', 'sqlite3']:  # load SQLite query bindings
-            cursor = connection.cursor()
-            connection.connection.create_function(
-            'query_spatial', 4, util.query_spatial)
-            connection.connection.create_function(
-            'get_anytext', 1, util.get_anytext)
-            connection.connection.create_function(
-            'get_geometry_area', 1, util.get_geometry_area)
-
-        # generate core queryables db and obj bindings
-        self.queryables = {}
-
-        for tname in self.context.model['typenames']:
-            for qname in self.context.model['typenames'][tname]['queryables']:
-                self.queryables[qname] = {}
-
-                for qkey, qvalue in \
-                self.context.model['typenames'][tname]['queryables'][qname].items():
-                    self.queryables[qname][qkey] = qvalue
-
-        # flatten all queryables
-        # TODO smarter way of doing this
-        self.queryables['_all'] = {}
-        for qbl in self.queryables:
-            self.queryables['_all'].update(self.queryables[qbl])
-        self.queryables['_all'].update(self.context.md_core_model['mappings'])
-
-    def query_ids(self, ids):
-        ''' Query by list of identifiers '''
-        return self._get_repo_filter(ResourceBase.objects).filter(uuid__in=ids).all()
-
-    def query_domain(self, domain, typenames, domainquerytype='list',
-        count=False):
-        ''' Query by property domain values '''
-
-        objects = self._get_repo_filter(ResourceBase.objects)
-
-        if domainquerytype == 'range':
-            return [tuple(objects.aggregate(
-            Min(domain), Max(domain)).values())]
-        else:
-            if count:
-                return [(d[domain], d['%s__count' % domain]) \
-                for d in objects.values(domain).annotate(Count(domain))]
-            else:
-                return objects.values_list(domain).distinct()
-
-
-    def query_insert(self, direction='max'):
-        ''' Query to get latest (default) or earliest update to repository '''
-        from datetime import datetime
-        if direction=='min':
-            return ResourceBase.objects.aggregate(
-                Min('date'))['date__min'].strftime('%Y-%m-%dT%H:%M:%SZ')
-        return self._get_repo_filter(ResourceBase.objects).aggregate(
-            Max('date'))['date__max'].strftime('%Y-%m-%dT%H:%M:%SZ')
-
-    def query_source(self, source):
-        ''' Query by source '''
-        return self._get_repo_filter(ResourceBase.objects).filter(source=source)
-
-    def query(self, constraint, sortby=None, typenames=None,
-        maxrecords=10, startposition=0):
-        ''' Query records from underlying repository '''
-
-        # run the raw query and get total
-        if 'where' in constraint:  # GetRecords with constraint
-            query = self._get_repo_filter(ResourceBase.objects).extra(where=[constraint['where']], params=constraint['values'])
-
-        else:  # GetRecords sans constraint
-            query = self._get_repo_filter(ResourceBase.objects)
-
-        total = query.count()
-
-        # apply sorting, limit and offset
-        if sortby is not None:
-            if 'spatial' in sortby and sortby['spatial']:  # spatial sort
-                desc = False
-                if sortby['order'] == 'DESC':
-                    desc = True
-                query = query.all()
-                return [str(total), sorted(query, key=lambda x: float(util.get_geometry_area(getattr(x, sortby['propertyname']))), reverse=desc)[startposition:startposition+int(maxrecords)]]
-            else:
-                if sortby['order'] == 'DESC':
-                    pname = '-%s' % sortby['propertyname']
-                else:
-                    pname = sortby['propertyname']
-                return [str(total), \
-                query.order_by(pname)[startposition:startposition+int(maxrecords)]]
-        else:  # no sort
-            return [str(total), query.all()[startposition:startposition+int(maxrecords)]]
-
-    def _get_repo_filter(self, query):
-        ''' Apply repository wide side filter / mask query '''
-        if self.filter is not None:
-            return query.extra(where=[self.filter])
-        return query
diff --git a/pycsw/plugins/repository/hhypermap/__init__.py b/pycsw/plugins/repository/hhypermap/__init__.py
deleted file mode 100644
index 1cc40dc..0000000
--- a/pycsw/plugins/repository/hhypermap/__init__.py
+++ /dev/null
@@ -1,29 +0,0 @@
-# -*- coding: ISO-8859-15 -*-
-# =================================================================
-#
-# Authors: Tom Kralidis <tomkralidis at gmail.com>
-#
-# Copyright (c) 2016 Tom Kralidis
-#
-# Permission is hereby granted, free of charge, to any person
-# obtaining a copy of this software and associated documentation
-# files (the "Software"), to deal in the Software without
-# restriction, including without limitation the rights to use,
-# copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the
-# Software is furnished to do so, subject to the following
-# conditions:
-#
-# The above copyright notice and this permission notice shall be
-# included in all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
-# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
-# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-# OTHER DEALINGS IN THE SOFTWARE.
-#
-# =================================================================
diff --git a/pycsw/plugins/repository/hhypermap/hhypermap.py b/pycsw/plugins/repository/hhypermap/hhypermap.py
deleted file mode 100644
index c4cf9ba..0000000
--- a/pycsw/plugins/repository/hhypermap/hhypermap.py
+++ /dev/null
@@ -1,251 +0,0 @@
-# -*- coding: iso-8859-15 -*-
-# =================================================================
-#
-# Authors: Tom Kralidis <tomkralidis at gmail.com>
-#
-# Copyright (c) 2016 Tom Kralidis
-#
-# Permission is hereby granted, free of charge, to any person
-# obtaining a copy of this software and associated documentation
-# files (the "Software"), to deal in the Software without
-# restriction, including without limitation the rights to use,
-# copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the
-# Software is furnished to do so, subject to the following
-# conditions:
-#
-# The above copyright notice and this permission notice shall be
-# included in all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
-# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
-# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-# OTHER DEALINGS IN THE SOFTWARE.
-#
-# =================================================================
-
-import inspect
-
-from django.db import models
-from django.db import connection
-from django.db.models import Avg, Max, Min, Count
-from django.conf import settings
-
-from pycsw.core import util
-from hypermap.aggregator.models import Catalog, Layer, Service, Endpoint
-from hypermap.aggregator.utils import create_layer_from_metadata_xml
-
-HYPERMAP_SERVICE_TYPES = {
-    # 'HHypermap enum': 'CSW enum'
-    'http://www.opengis.net/cat/csw/2.0.2': 'OGC:CSW',
-    'http://www.opengis.net/wms': 'OGC:WMS',
-    'http://www.opengis.net/wmts/1.0': 'OGC:WMTS',
-    'https://wiki.osgeo.org/wiki/TMS': 'OSGeo:TMS',
-    'urn:x-esri:serviceType:ArcGIS:MapServer': 'ESRI:ArcGIS:MapServer',
-    'urn:x-esri:serviceType:ArcGIS:ImageServer': 'ESRI:ArcGIS:ImageServer'
-}
-
-class HHypermapRepository(object):
-    ''' Class to interact with underlying repository '''
-    def __init__(self, context, repo_filter=None):
-        ''' Initialize repository '''
-
-        self.context = context
-        self.filter = repo_filter
-        self.fts = False
-        self.label = 'HHypermap'
-        self.local_ingest = True
-
-        self.dbtype = settings.DATABASES['default']['ENGINE'].split('.')[-1]
-
-        # HHypermap PostgreSQL installs are PostGIS enabled
-        if self.dbtype == 'postgresql_psycopg2':
-            self.dbtype = 'postgresql+postgis+wkt'
-
-        if self.dbtype in ['sqlite', 'sqlite3']:  # load SQLite query bindings
-            cursor = connection.cursor()
-            connection.connection.create_function(
-            'query_spatial', 4, util.query_spatial)
-            connection.connection.create_function(
-            'get_anytext', 1, util.get_anytext)
-            connection.connection.create_function(
-            'get_geometry_area', 1, util.get_geometry_area)
-
-        # generate core queryables db and obj bindings
-        self.queryables = {}
-
-        for tname in self.context.model['typenames']:
-            for qname in self.context.model['typenames'][tname]['queryables']:
-                self.queryables[qname] = {}
-
-                for qkey, qvalue in \
-                self.context.model['typenames'][tname]['queryables'][qname].items():
-                    self.queryables[qname][qkey] = qvalue
-
-        # flatten all queryables
-        # TODO smarter way of doing this
-        self.queryables['_all'] = {}
-        for qbl in self.queryables:
-            self.queryables['_all'].update(self.queryables[qbl])
-        self.queryables['_all'].update(self.context.md_core_model['mappings'])
-
-        if 'Harvest' in self.context.model['operations'] and 'Transaction' in self.context.model['operations']:
-            self.context.model['operations']['Harvest']['parameters']['ResourceType']['values'] = HYPERMAP_SERVICE_TYPES.keys()
-            self.context.model['operations']['Transaction']['parameters']['TransactionSchemas']['values'] = HYPERMAP_SERVICE_TYPES.keys()
-
-    def dataset(self):
-        ''' Stub to mock a pycsw dataset object for Transactions'''
-        return type('Service', (object,), {})
-
-    def query_ids(self, ids):
-        ''' Query by list of identifiers '''
-        return self._get_repo_filter(Layer.objects).filter(id__in=ids).all()
-
-    def query_domain(self, domain, typenames, domainquerytype='list',
-        count=False):
-        ''' Query by property domain values '''
-
-        objects = self._get_repo_filter(Layer.objects)
-
-        if domainquerytype == 'range':
-            return [tuple(objects.aggregate(
-            Min(domain), Max(domain)).values())]
-        else:
-            if count:
-                return [(d[domain], d['%s__count' % domain]) \
-                for d in objects.values(domain).annotate(Count(domain))]
-            else:
-                return objects.values_list(domain).distinct()
-
-    def query_insert(self, direction='max'):
-        ''' Query to get latest (default) or earliest update to repository '''
-        from datetime import datetime
-        if direction=='min':
-            return Layer.objects.aggregate(
-                Min('last_updated'))['last_updated__min'].strftime('%Y-%m-%dT%H:%M:%SZ')
-        return self._get_repo_filter(Layer.objects).aggregate(
-            Max('last_updated'))['last_updated__max'].strftime('%Y-%m-%dT%H:%M:%SZ')
-
-    def query_source(self, source):
-        ''' Query by source '''
-        return self._get_repo_filter(Layer.objects).filter(url=source)
-
-    def query(self, constraint, sortby=None, typenames=None,
-        maxrecords=10, startposition=0):
-        ''' Query records from underlying repository '''
-
-        # run the raw query and get total
-        if 'where' in constraint:  # GetRecords with constraint
-            query = self._get_repo_filter(Layer.objects).extra(where=[constraint['where']], params=constraint['values'])
-
-        else:  # GetRecords sans constraint
-            query = self._get_repo_filter(Layer.objects)
-
-        total = query.count()
-
-        # apply sorting, limit and offset
-        if sortby is not None:
-            if 'spatial' in sortby and sortby['spatial']:  # spatial sort
-                desc = False
-                if sortby['order'] == 'DESC':
-                    desc = True
-                query = query.all()
-                return [str(total), sorted(query, key=lambda x: float(util.get_geometry_area(getattr(x, sortby['propertyname']))), reverse=desc)[startposition:startposition+int(maxrecords)]]
-            else:
-                if sortby['order'] == 'DESC':
-                    pname = '-%s' % sortby['propertyname']
-                else:
-                    pname = sortby['propertyname']
-                return [str(total), \
-                query.order_by(pname)[startposition:startposition+int(maxrecords)]]
-        else:  # no sort
-            return [str(total), query.all()[startposition:startposition+int(maxrecords)]]
-
-    def insert(self, resourcetype, source, insert_date=None):
-        ''' Insert a record into the repository '''
-
-        caller = inspect.stack()[1][3]
-
-        if caller == 'transaction':  # insert of Layer
-            hhclass = 'Layer'
-            source = resourcetype
-            resourcetype = resourcetype.csw_schema
-        else:  # insert of service
-            hhclass = 'Service'
-            if resourcetype not in HYPERMAP_SERVICE_TYPES.keys():
-                raise RuntimeError('Unsupported Service Type')
-
-        return self._insert_or_update(resourcetype, source, mode='insert', hhclass=hhclass)
-
-    def _insert_or_update(self, resourcetype, source, mode='insert', hhclass='Service'):
-        ''' Insert or update a record in the repository '''
-
-        keywords = []
-        try:
-            if hhclass == 'Layer':
-                # TODO: better way of figuring out duplicates
-                match = Layer.objects.filter(name=source.name, title=source.title, abstract=source.abstract, is_monitored=False)
-                matches = match.all()
-                if matches:
-                    if mode == 'insert':
-                        raise RuntimeError('HHypermap error: Layer %d \'%s\' already exists' % (matches[0].id, source.title))
-                    elif mode == 'update':
-                        match.update(
-                            name=source.name,
-                            title=source.title,
-                            abstract=source.abstract,
-                            is_monitored=False,
-                            xml=source.xml,
-                            wkt_geometry=source.wkt_geometry,
-                            anytext=util.get_anytext([source.title, source.abstract, source.keywords_csv])
-                        )
-
-                res, keywords = create_layer_from_metadata_xml(resourcetype, source.xml, monitor=False)
-            else:
-                if resourcetype == 'http://www.opengis.net/cat/csw/2.0.2':
-                    res = Endpoint(url=source)
-                else:
-                    res = Service(type=HYPERMAP_SERVICE_TYPES[resourcetype], url=source)
-
-            if self.filter is not None:
-                res.catalog = Catalog.objects.get(id=int(self.filter.split()[-1]))                    
-            res.save()
-            if keywords:
-                for kw in keywords:
-                    res.keywords.add(kw)
-        except Exception as err:
-           raise RuntimeError('HHypermap error: %s' % err)
-
-        # return a list of ids that were inserted or updated
-        ids = []
-
-        if hhclass == 'Layer':
-            ids.append({'identifier': res.uuid, 'title': res.title })
-        else:
-            if resourcetype == 'http://www.opengis.net/cat/csw/2.0.2':
-                for res in Endpoint.objects.filter(url=source).all():
-                    ids.append({'identifier': res.uuid, 'title': res.url})
-            else:
-                for res in Service.objects.filter(url=source).all():
-                    ids.append({'identifier': res.uuid, 'title': res.title})
-
-        return ids
-
-    def delete(self, constraint):
-        ''' Delete a record from the repository '''
-
-        results = self._get_repo_filter(Service.objects).extra(where=[constraint['where']],
-                                                               params=constraint['values']).all()
-        deleted = len(results)
-        results.delete()
-        return deleted
-
-    def _get_repo_filter(self, query):
-        ''' Apply repository wide side filter / mask query '''
-        if self.filter is not None:
-            return query.extra(where=[self.filter])
-        return query
diff --git a/pycsw/plugins/repository/odc/odc.py b/pycsw/plugins/repository/odc/odc.py
index c336b5f..c3d6a95 100644
--- a/pycsw/plugins/repository/odc/odc.py
+++ b/pycsw/plugins/repository/odc/odc.py
@@ -35,7 +35,7 @@ from django.db import connection
 from django.db.models import Avg, Max, Min, Count
 from django.conf import settings
 
-from pycsw.core import util
+from pycsw.core import repository, util
 from OpenDataCatalog.opendata.models import Resource
 
 class OpenDataCatalogRepository(object):
@@ -58,7 +58,7 @@ class OpenDataCatalogRepository(object):
             connection.connection.create_function(
             'query_spatial', 4, util.query_spatial)
             connection.connection.create_function(
-            'get_anytext', 1, util.get_anytext)
+            'get_anytext', 1, repository.get_anytext)
             connection.connection.create_function(
             'get_geometry_area', 1, util.get_geometry_area)
 
diff --git a/pycsw/server.py b/pycsw/server.py
index 10eec51..050f732 100644
--- a/pycsw/server.py
+++ b/pycsw/server.py
@@ -101,6 +101,7 @@ class Csw(object):
 
         # load user configuration
         try:
+            LOGGER.info('Loading user configuration')
             if isinstance(rtconfig, SafeConfigParser):  # serialized already
                 self.config = rtconfig
             else:
@@ -114,11 +115,11 @@ class Csw(object):
                     import codecs
                     with codecs.open(rtconfig, encoding='utf-8') as scp:
                         self.config.readfp(scp)
-        except Exception:
+        except Exception as err:
+            msg = 'Could not load configuration'
+            LOGGER.exception('%s %s: %s', msg, rtconfig, err)
             self.response = self.iface.exceptionreport(
-                'NoApplicableCode', 'service',
-                'Error opening configuration %s' % rtconfig
-            )
+                'NoApplicableCode', 'service', msg)
             return
 
         # set server.home safely
@@ -133,8 +134,8 @@ class Csw(object):
 
         log.setup_logger(self.config)
 
-        LOGGER.debug('running configuration %s' % rtconfig)
-        LOGGER.debug(str(self.environ['QUERY_STRING']))
+        LOGGER.info('running configuration %s', rtconfig)
+        LOGGER.debug('QUERY_STRING: %s', self.environ['QUERY_STRING'])
 
         # set OGC schemas location
         if not self.config.has_option('server', 'ogc_schemas_base'):
@@ -170,11 +171,12 @@ class Csw(object):
                 lang_code = self.config.get('server', 'language').split('-')[0]
                 self.language['639_code'] = lang_code
                 self.language['text'] = self.context.languages[lang_code]
-            except:
+            except Exception as err:
+                LOGGER.exception('Could not set language: %s', err)
                 pass
 
-        LOGGER.debug('Configuration: %s.' % self.config)
-        LOGGER.debug('Model: %s.' % self.context.model)
+        LOGGER.debug('Configuration: %s.', self.config)
+        LOGGER.debug('Model: %s.', self.context.model)
 
         # load user-defined mappings if they exist
         if self.config.has_option('repository', 'mappings'):
@@ -182,21 +184,24 @@ class Csw(object):
             try:
                 import imp
                 module = self.config.get('repository', 'mappings')
-                modulename = '%s' % os.path.splitext(module)[0].replace(
-                    os.sep, '.')
-                LOGGER.debug('Loading custom repository mappings '
-                             'from %s.' % module)
-                mappings = imp.load_source(modulename, module)
+                if '/' in module:  # filepath
+                    modulename = '%s' % os.path.splitext(module)[0].replace(
+                        os.sep, '.')
+                    mappings = imp.load_source(modulename, module)
+                else:  # dotted name
+                    mappings = __import__(module, fromlist=[''])
+                LOGGER.info('Loading custom repository mappings '
+                             'from %s', module)
                 self.context.md_core_model = mappings.MD_CORE_MODEL
                 self.context.refresh_dc(mappings.MD_CORE_MODEL)
             except Exception as err:
+                LOGGER.exception('Could not load custom mappings: %s', err)
                 self.response = self.iface.exceptionreport(
                     'NoApplicableCode', 'service',
-                    'Could not load repository.mappings %s' % str(err)
-                )
+                    'Could not load repository.mappings')
 
         # load outputschemas
-        LOGGER.debug('Loading outputschemas.')
+        LOGGER.info('Loading outputschemas')
 
         for osch in pycsw.plugins.outputschemas.__all__:
             output_schema_module = __import__(
@@ -204,8 +209,8 @@ class Csw(object):
             mod = getattr(output_schema_module.plugins.outputschemas, osch)
             self.outputschemas[mod.NAMESPACE] = mod
 
-        LOGGER.debug('Outputschemas loaded: %s.' % self.outputschemas)
-        LOGGER.debug('Namespaces: %s' % self.context.namespaces)
+        LOGGER.debug('Outputschemas loaded: %s.', self.outputschemas)
+        LOGGER.debug('Namespaces: %s', self.context.namespaces)
 
     def expand_path(self, path):
         """ return safe path for WSGI environments """
@@ -238,10 +243,10 @@ class Csw(object):
             try:
                 query_part = splitquery(self.request)[-1]
                 self.kvp = dict(parse_qsl(query_part, keep_blank_values=True))
-            except AttributeError:
+            except AttributeError as err:
+                LOGGER.exception('Could not parse query string')
                 self.kvp = {}
             LOGGER.debug('Request type: GET.  Request:\n%s\n', self.request)
-
         return self.dispatch()
 
     def opensearch(self):
@@ -267,6 +272,7 @@ class Csw(object):
     def dispatch(self, writer=sys.stdout, write_headers=True):
         """ Handle incoming HTTP request """
 
+        error = 0
         if self.requesttype == 'GET':
             self.kvp = self.normalize_kvp(self.kvp)
             version_202 = ('version' in self.kvp and
@@ -276,21 +282,23 @@ class Csw(object):
             if version_202 or accept_version_202:
                 self.request_version = '2.0.2'
         elif self.requesttype == 'POST':
-            if self.request.find(b'2.0.2') != -1:
+            if self.request.find(b'cat/csw/2.0.2') != -1:
                 self.request_version = '2.0.2'
+            elif self.request.find(b'cat/csw/3.0') != -1:
+                self.request_version = '3.0.0'
 
         if (not isinstance(self.kvp, str) and 'mode' in self.kvp and
                 self.kvp['mode'] == 'sru'):
             self.mode = 'sru'
             self.request_version = '2.0.2'
-            LOGGER.debug('SRU mode detected; processing request.')
+            LOGGER.info('SRU mode detected; processing request')
             self.kvp = self.sru().request_sru2csw(self.kvp)
 
         if (not isinstance(self.kvp, str) and 'mode' in self.kvp and
                 self.kvp['mode'] == 'oaipmh'):
             self.mode = 'oaipmh'
             self.request_version = '2.0.2'
-            LOGGER.debug('OAI-PMH mode detected; processing request.')
+            LOGGER.info('OAI-PMH mode detected; processing request.')
             self.oaiargs = dict((k, v) for k, v in self.kvp.items() if k)
             self.kvp = self.oaipmh().request(self.kvp)
 
@@ -311,12 +319,13 @@ class Csw(object):
 
         # generate distributed search model, if specified in config
         if self.config.has_option('server', 'federatedcatalogues'):
-            LOGGER.debug('Configuring distributed search.')
+            LOGGER.info('Configuring distributed search')
 
             constraints['FederatedCatalogues'] = {'values': []}
 
             for fedcat in self.config.get('server',
                                           'federatedcatalogues').split(','):
+                LOGGER.debug('federated catalogue: %s', fedcat)
                 constraints['FederatedCatalogues']['values'].append(fedcat)
 
         for key, value in self.outputschemas.items():
@@ -331,7 +340,7 @@ class Csw(object):
                 harvest_params['ResourceType']['values'].append(
                     value.NAMESPACE)
 
-        LOGGER.debug('Setting MaxRecordDefault')
+        LOGGER.info('Setting MaxRecordDefault')
         if self.config.has_option('server', 'maxrecords'):
             constraints['MaxRecordDefault']['values'] = [
                 self.config.get('server', 'maxrecords')]
@@ -355,8 +364,7 @@ class Csw(object):
                                                          namespaces,
                                                          self.config)
 
-            LOGGER.debug('Profiles loaded: %s.' %
-            list(self.profiles['loaded'].keys()))
+            LOGGER.debug('Profiles loaded: %s' % list(self.profiles['loaded'].keys()))
 
         # init repository
         # look for tablename, set 'records' as default
@@ -367,61 +375,29 @@ class Csw(object):
         if self.config.has_option('repository', 'filter'):
             repo_filter = self.config.get('repository', 'filter')
 
-        if (self.config.has_option('repository', 'source') and
-                self.config.get('repository', 'source') == 'geonode'):
+        if self.config.has_option('repository', 'source'):  # load custom repository
+            rs = self.config.get('repository', 'source')
+            rs_modname, rs_clsname = rs.rsplit('.', 1)
 
-            # load geonode repository
-            from pycsw.plugins.repository.geonode import geonode_
+            rs_mod = __import__(rs_modname, globals(), locals(), [rs_clsname])
+            rs_cls = getattr(rs_mod, rs_clsname)
 
             try:
-                self.repository = geonode_.GeoNodeRepository(self.context,
-                                                             repo_filter)
-                LOGGER.debug('GeoNode repository loaded '
-                             '(geonode): %s.' % self.repository.dbtype)
+                self.repository = rs_cls(self.context, repo_filter)
+                LOGGER.debug('Custom repository %s loaded (%s)', rs, self.repository.dbtype)
             except Exception as err:
-                self.response = self.iface.exceptionreport(
-                    'NoApplicableCode', 'service',
-                    'Could not load repository (geonode): %s' % str(err)
-                )
-
-        elif (self.config.has_option('repository', 'source') and
-                self.config.get('repository', 'source') == 'HHypermap'):
-
-            # load HHypermap repository
-            from pycsw.plugins.repository.hhypermap import hhypermap
-
-            try:
-                self.repository = hhypermap.HHypermapRepository(self.context,
-                                                                repo_filter)
-                LOGGER.debug('HHypermap repository loaded '
-                             '(hhypermap): %s.' % self.repository.dbtype)
-            except Exception as err:
-                self.response = self.iface.exceptionreport(
-                    'NoApplicableCode', 'service',
-                    'Could not load repository (hhypermap): %s' % str(err)
-                )
-
-        elif (self.config.has_option('repository', 'source') and
-                self.config.get('repository', 'source') == 'odc'):
-
-            # load odc repository
-            from pycsw.plugins.repository.odc import odc
-
-            try:
-                self.repository = odc.OpenDataCatalogRepository(self.context,
-                                                                repo_filter)
-                LOGGER.debug('OpenDataCatalog repository loaded '
-                             '(geonode): %s.' % self.repository.dbtype)
-            except Exception as err:
-                self.response = self.iface.exceptionreport(
-                    'NoApplicableCode', 'service',
-                    'Could not load repository (odc): %s' % str(err)
-                )
+                msg = 'Could not load custom repository %s: %s' % (rs, err)
+                LOGGER.exception(msg)
+                error = 1
+                code = 'NoApplicableCode'
+                locator = 'service'
+                text = 'Could not initialize repository. Check server logs'
 
         else:  # load default repository
             self.orm = 'sqlalchemy'
             from pycsw.core import repository
             try:
+                LOGGER.info('Loading default repository')
                 self.repository = repository.Repository(
                     self.config.get('repository', 'database'),
                     self.context,
@@ -432,17 +408,18 @@ class Csw(object):
                 LOGGER.debug(
                     'Repository loaded (local): %s.' % self.repository.dbtype)
             except Exception as err:
-                self.response = self.iface.exceptionreport(
-                    'NoApplicableCode', 'service',
-                    'Could not load repository (local): %s' % str(err)
-                )
+                msg = 'Could not load repository (local): %s' % err
+                LOGGER.exception(msg)
+                error = 1
+                code = 'NoApplicableCode'
+                locator = 'service'
+                text = 'Could not initialize repository. Check server logs'
 
         if self.requesttype == 'POST':
-            LOGGER.debug(self.iface.version)
+            LOGGER.debug('HTTP POST request')
+            LOGGER.debug('CSW version: %s', self.iface.version)
             self.kvp = self.iface.parse_postdata(self.request)
 
-        error = 0
-
         if isinstance(self.kvp, str):  # it's an exception
             error = 1
             locator = 'service'
@@ -453,18 +430,18 @@ class Csw(object):
             else:
                 code = 'InvalidParameterValue'
 
-        LOGGER.debug('HTTP Headers:\n%s.' % self.environ)
-        LOGGER.debug('Parsed request parameters: %s' % self.kvp)
+        LOGGER.debug('HTTP Headers:\n%s.', self.environ)
+        LOGGER.debug('Parsed request parameters: %s', self.kvp)
 
         if (not isinstance(self.kvp, str) and 'mode' in self.kvp and
                 self.kvp['mode'] == 'opensearch'):
             self.mode = 'opensearch'
-            LOGGER.debug('OpenSearch mode detected; processing request.')
+            LOGGER.info('OpenSearch mode detected; processing request.')
             self.kvp['outputschema'] = 'http://www.w3.org/2005/Atom'
 
         if ((len(self.kvp) == 0 and self.request_version == '3.0.0') or
                 (len(self.kvp) == 1 and 'config' in self.kvp)):
-            LOGGER.debug('Turning on default csw30:Capabilities for base URL')
+            LOGGER.info('Turning on default csw30:Capabilities for base URL')
             self.kvp = {
                 'service': 'CSW',
                 'acceptversions': '3.0.0',
@@ -483,6 +460,12 @@ class Csw(object):
                 self.request_version)
             if self.request_version == '2.0.2':
                 basic_options.append('version')
+            if self.request_version == '3.0.0' and 'version' not in self.kvp and self.requesttype == 'POST':
+                if 'service' not in self.kvp:
+                    self.kvp['service'] = 'CSW'
+                    basic_options.append('service')
+                self.kvp['version'] = self.request_version
+                basic_options.append('version')
 
             for k in basic_options:
                 if k not in self.kvp:
@@ -548,6 +531,7 @@ class Csw(object):
                         text = 'Invalid value for request: %s' % request
 
         if error == 1:  # return an ExceptionReport
+            LOGGER.error('basic service options error: %s, %s, %s', code, locator, text)
             self.response = self.iface.exceptionreport(code, locator, text)
 
         else:  # process per the request value
@@ -591,17 +575,18 @@ class Csw(object):
                     'Invalid request parameter: %s' % self.kvp['request']
                 )
 
+        LOGGER.info('Request processed')
         if self.mode == 'sru':
-            LOGGER.debug('SRU mode detected; processing response.')
+            LOGGER.info('SRU mode detected; processing response.')
             self.response = self.sru().response_csw2sru(self.response,
                                                         self.environ)
         elif self.mode == 'opensearch':
-            LOGGER.debug('OpenSearch mode detected; processing response.')
+            LOGGER.info('OpenSearch mode detected; processing response.')
             self.response = self.opensearch().response_csw2opensearch(
                 self.response, self.config)
 
         elif self.mode == 'oaipmh':
-            LOGGER.debug('OAI-PMH mode detected; processing response.')
+            LOGGER.info('OAI-PMH mode detected; processing response.')
             self.response = self.oaipmh().response(
                 self.response, self.oaiargs, self.repository,
                 self.config.get('server', 'url')
@@ -648,7 +633,7 @@ class Csw(object):
         xmldecl = ''
         appinfo = ''
 
-        LOGGER.debug('Writing response.')
+        LOGGER.info('Writing response.')
 
         if hasattr(self, 'soap') and self.soap:
             self._gen_soap_wrapper()
@@ -689,7 +674,7 @@ class Csw(object):
 
     def _gen_soap_wrapper(self):
         """ Generate SOAP wrapper """
-        LOGGER.debug('Writing SOAP wrapper.')
+        LOGGER.info('Writing SOAP wrapper.')
         node = etree.Element(
             util.nspath_eval('soapenv:Envelope', self.context.namespaces),
             nsmap=self.context.namespaces
@@ -760,6 +745,7 @@ class Csw(object):
                 'http://www.opengis.net/wms',
                 'http://www.opengis.net/wmts/1.0',
                 'http://www.opengis.net/wfs',
+                'http://www.opengis.net/wfs/2.0',
                 'http://www.opengis.net/wcs',
                 'http://www.opengis.net/wps/1.0.0',
                 'http://www.opengis.net/sos/1.0',
@@ -795,7 +781,11 @@ class Csw(object):
         if self.config.get('manager', 'transactions') != 'true':
             raise RuntimeError('CSW-T interface is disabled')
 
-        ipaddress = self.environ['REMOTE_ADDR']
+        """ get the client first forwarded ip """
+        if 'HTTP_X_FORWARDED_FOR' in self.environ:
+            ipaddress = self.environ['HTTP_X_FORWARDED_FOR'].split(',')[0].strip()
+        else:
+            ipaddress = self.environ['REMOTE_ADDR']
 
         if not self.config.has_option('manager', 'allowed_ips') or \
         (self.config.has_option('manager', 'allowed_ips') and not
@@ -806,7 +796,7 @@ class Csw(object):
 
     def _cql_update_queryables_mappings(self, cql, mappings):
         """ Transform CQL query's properties to underlying DB columns """
-        LOGGER.debug('Raw CQL text = %s.' % cql)
+        LOGGER.debug('Raw CQL text = %s', cql)
         LOGGER.debug(str(list(mappings.keys())))
         if cql is not None:
             for key in mappings.keys():
@@ -814,14 +804,14 @@ class Csw(object):
                     cql = cql.replace(key, mappings[key]['dbcol'])
                 except:
                     cql = cql.replace(key, mappings[key])
-            LOGGER.debug('Interpolated CQL text = %s.' % cql)
+            LOGGER.debug('Interpolated CQL text = %s.', cql)
             return cql
 
     def _process_responsehandler(self, xml):
         """ Process response handler """
 
         if self.kvp['responsehandler'] is not None:
-            LOGGER.debug('Processing responsehandler %s.' %
+            LOGGER.info('Processing responsehandler %s' %
                          self.kvp['responsehandler'])
 
             uprh = urlparse(self.kvp['responsehandler'])
@@ -829,7 +819,7 @@ class Csw(object):
             if uprh.scheme == 'mailto':  # email
                 import smtplib
 
-                LOGGER.debug('Email detected.')
+                LOGGER.debug('Email detected')
 
                 smtp_host = 'localhost'
                 if self.config.has_option('server', 'smtp_host'):
@@ -839,7 +829,7 @@ class Csw(object):
                         (self.kvp['request'], xml))
 
                 try:
-                    LOGGER.debug('Sending email.')
+                    LOGGER.info('Sending email')
                     msg = smtplib.SMTP(smtp_host)
                     msg.sendmail(
                         self.config.get('metadata:main', 'contact_email'),
@@ -848,7 +838,7 @@ class Csw(object):
                     msg.quit()
                     LOGGER.debug('Email sent successfully.')
                 except Exception as err:
-                    LOGGER.debug('Error processing email: %s.' % str(err))
+                    LOGGER.exception('Error processing email')
 
             elif uprh.scheme == 'ftp':
                 import ftplib
@@ -856,7 +846,7 @@ class Csw(object):
                 LOGGER.debug('FTP detected.')
 
                 try:
-                    LOGGER.debug('Sending to FTP server.')
+                    LOGGER.info('Sending to FTP server.')
                     ftp = ftplib.FTP(uprh.hostname)
                     if uprh.username is not None:
                         ftp.login(uprh.username, uprh.password)
@@ -864,7 +854,7 @@ class Csw(object):
                     ftp.quit()
                     LOGGER.debug('FTP sent successfully.')
                 except Exception as err:
-                    LOGGER.debug('Error processing FTP: %s.' % str(err))
+                    LOGGER.exception('Error processing FTP')
 
     @staticmethod
     def normalize_kvp(kvp):
diff --git a/pycsw/sru.py b/pycsw/sru.py
index 6240f49..e881513 100644
--- a/pycsw/sru.py
+++ b/pycsw/sru.py
@@ -123,7 +123,8 @@ class Sru(object):
     def response_csw2sru(self, element, environ):
         """transform a CSW response into an SRU response"""
 
-        if util.xmltag_split(element.tag) == 'Capabilities':  # explain
+        response_name = etree.QName(element).localname
+        if response_name == 'Capabilities':  # explain
             node = etree.Element(util.nspath_eval('sru:explainResponse', self.namespaces), nsmap=self.namespaces)
 
             etree.SubElement(node, util.nspath_eval('sru:version', self.namespaces)).text = self.sru_version
@@ -168,7 +169,7 @@ class Sru(object):
             configinfo = etree.SubElement(explain, util.nspath_eval('zr:configInfo', self.namespaces))
             etree.SubElement(configinfo, util.nspath_eval('zr:default', self.namespaces), type='numberOfRecords').text = '0'
 
-        elif util.xmltag_split(element.tag) == 'GetRecordsResponse':
+        elif response_name == 'GetRecordsResponse':
 
             recpos = int(element.xpath('//@nextRecord')[0]) - int(element.xpath('//@numberOfRecordsReturned')[0])
 
@@ -188,7 +189,7 @@ class Sru(object):
                 etree.SubElement(record, util.nspath_eval('zs:recordPosition', self.namespaces)).text = str(recpos)
                 recpos += 1
 
-        elif util.xmltag_split(element.tag) == 'ExceptionReport':
+        elif response_name == 'ExceptionReport':
             node = self.exceptionreport2diagnostic(element)
         return node
 
diff --git a/pycsw/wsgi.py b/pycsw/wsgi.py
index 8a20f28..92accf6 100644
--- a/pycsw/wsgi.py
+++ b/pycsw/wsgi.py
@@ -2,8 +2,10 @@
 # =================================================================
 #
 # Authors: Adam Hinz <hinz.adam at gmail.com>
+#          Ricardo Garcia Silva <ricardo.garcia.silva at gmail.com>
 #
 # Copyright (c) 2015 Adam Hinz
+# Copyright (c) 2017 Ricardo Garcia Silva
 #
 # Permission is hereby granted, free of charge, to any person
 # obtaining a copy of this software and associated documentation
@@ -52,79 +54,166 @@
 # http://localhost:8000/
 #
 
+import gzip
 import os
 import sys
+
 import six
+from six.moves import configparser
 from six.moves.urllib.parse import unquote
 
 from pycsw import server
 
 
-PYCSW_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
-
-
 def application(env, start_response):
     """WSGI wrapper"""
-    config = 'default.cfg'
-
-    if 'PYCSW_CONFIG' in env:
-        config = env['PYCSW_CONFIG']
-
-    root = PYCSW_ROOT
-
-    if 'PYCSW_ROOT' in env:
-        root = env['PYCSW_ROOT']
-
-    if env['QUERY_STRING'].lower().find('config') != -1:
-        for kvp in env['QUERY_STRING'].split('&'):
-            if kvp.lower().find('config') != -1:
-                config = unquote(kvp.split('=')[1])
-
-    if not os.path.isabs(config):
-        config = os.path.join(root, config)
 
+    pycsw_root = get_pycsw_root_path(os.environ, env)
+    configuration_path = get_configuration_path(os.environ, env, pycsw_root)
+    env['local.app_root'] = pycsw_root
     if 'HTTP_HOST' in env and ':' in env['HTTP_HOST']:
         env['HTTP_HOST'] = env['HTTP_HOST'].split(':')[0]
-
-    env['local.app_root'] = root
-
-    csw = server.Csw(config, env)
-
-    gzip = False
-    if ('HTTP_ACCEPT_ENCODING' in env and
-            env['HTTP_ACCEPT_ENCODING'].find('gzip') != -1):
-        # set for gzip compressed response
-        gzip = True
-
-    # set compression level
-    if csw.config.has_option('server', 'gzip_compresslevel'):
-        gzip_compresslevel = \
-            int(csw.config.get('server', 'gzip_compresslevel'))
-    else:
-        gzip_compresslevel = 0
-
+    csw = server.Csw(configuration_path, env)
     status, contents = csw.dispatch_wsgi()
+    headers = {
+        'Content-Length': str(len(contents)),
+        'Content-Type': str(csw.contenttype)
+    }
+    if "gzip" in env.get("HTTP_ACCEPT_ENCODING", ""):
+        try:
+            compression_level = int(
+                csw.config.get("server", "gzip_compresslevel"))
+            contents, compress_headers = compress_response(
+                contents, compression_level)
+            headers.update(compress_headers)
+        except configparser.NoOptionError:
+            print(
+                "The client requested a gzip compressed response. However, "
+                "the server does not specify the 'gzip_compresslevel' option. "
+                "Returning an uncompressed response..."
+            )
+        except configparser.NoSectionError:
+            print('Could not load user configuration %s' % configuration_path)
 
-    headers = {}
-
-    if gzip and gzip_compresslevel > 0:
-        import gzip
-
-        buf = six.BytesIO()
-        gzipfile = gzip.GzipFile(mode='wb', fileobj=buf,
-                                 compresslevel=gzip_compresslevel)
-        gzipfile.write(contents)
-        gzipfile.close()
-
-        contents = buf.getvalue()
+    start_response(status, list(headers.items()))
+    return [contents]
 
-        headers['Content-Encoding'] = 'gzip'
 
-    headers['Content-Length'] = str(len(contents))
-    headers['Content-Type'] = str(csw.contenttype)
-    start_response(status, list(headers.items()))
+def compress_response(response, compression_level):
+    """Compress pycsw's response with gzip
+
+    Parameters
+    ----------
+    response: str
+        The already processed CSW request
+    compression_level: int
+        Level of compression to use in gzip algorithm
+
+    Returns
+    -------
+    bytes
+        The full binary contents of the compressed response
+    dict
+        Extra HTTP headers that are useful for the response
+
+    """
+
+    buf = six.BytesIO()
+    gzipfile = gzip.GzipFile(mode='wb', fileobj=buf,
+                             compresslevel=compression_level)
+    gzipfile.write(response)
+    gzipfile.close()
+    compressed_response = buf.getvalue()
+    compression_headers = {'Content-Encoding': 'gzip'}
+    return compressed_response, compression_headers
+
+
+def get_pycsw_root_path(process_environment, request_environment=None,
+                        root_path_key="PYCSW_ROOT"):
+    """Get pycsw's root path.
+
+    The root path will be searched in the ``process_environment`` first, then
+    in the ``request_environment``. If it cannot be found then it is determined
+    based on the location on disk.
+
+    Parameters
+    ----------
+    process_environment: dict
+        A mapping with the process environment.
+    request_environment: dict, optional
+        A mapping with the request environment. Typically the WSGI's
+        environment
+    root_path_key: str
+        Name of the key in both the ``process_environment`` and the
+        ``request_environment`` parameters that specifies the path to pycsw's
+        root path.
+
+    Returns
+    -------
+    str
+        Path to pycsw's root path, as read from the supplied configuration.
+
+    """
+
+    req_env = (
+        dict(request_environment) if request_environment is not None else {})
+    app_root = process_environment.get(
+        root_path_key,
+        req_env.get(
+            root_path_key,
+            os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+        )
+    )
+    return app_root
+
+def get_configuration_path(process_environment, request_environment,
+                           pycsw_root, config_path_key="PYCSW_CONFIG"):
+    """Get the path for pycsw configuration file.
+
+    The configuration file path is searched in the following:
+    * The presence of a ``config`` parameter in the request's query string;
+    * A ``PYCSW_CONFIG`` environment variable;
+    * A ``PYCSW_CONFIG`` WSGI variable.
+
+    Parameters
+    ----------
+    process_environment: dict
+        A mapping with the process environment.
+    request_environment: dict
+        A mapping with the request's environment. Typically the WSGI's
+        environment
+    pycsw_root: str
+        pycsw's default root path
+    config_path_key: str, optional
+        Name of the variable that specifies the path to pycsw's configuration
+        file.
+
+    Returns
+    -------
+    str
+        Path where pycsw expects to find its own configuration file
+
+    """
+
+    # scan from config= or PYCSW_CONFIG environment variable
+    query_string = request_environment.get("QUERY_STRING", "").lower()
+
+    for kvp in query_string.split('&'):
+        if "config" in kvp:
+            configuration_path = unquote(kvp.split('=')[1])
+            break
+    else:
+        # did not find any `config` parameter in the request
+        # lets try the process env, request env and fallback to
+        # <pycsw_root>/default.cfg
+        configuration_path = process_environment.get(
+            config_path_key,
+            request_environment.get(
+                config_path_key, os.path.join(pycsw_root, "default.cfg")
+            )
+        )
+    return configuration_path
 
-    return [contents]
 
 if __name__ == '__main__':  # run inline using WSGI reference implementation
     from wsgiref.simple_server import make_server
@@ -132,5 +221,5 @@ if __name__ == '__main__':  # run inline using WSGI reference implementation
     if len(sys.argv) > 1:
         port = int(sys.argv[1])
     httpd = make_server('', port, application)
-    print('Serving on port %d...' % port)
+    print('Serving on port {}...'.format(port))
     httpd.serve_forever()
diff --git a/requirements-dev.txt b/requirements-dev.txt
index 6eeb2fb..6940ce6 100644
--- a/requirements-dev.txt
+++ b/requirements-dev.txt
@@ -1,2 +1,11 @@
-Paver==1.2.2
+-r requirements.txt
+-r requirements-standalone.txt
+
+apipkg==1.4
+mock==2.0.0
+Paver==1.2.4
+pytest==3.0.3
+pytest-cov==2.4.0
+pytest-flake8==0.8.1
+pytest-timeout==1.2.0
 sphinx
diff --git a/requirements.txt b/requirements.txt
index b2e7090..e79ac8c 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,7 +1,7 @@
 geolinks==0.2.0
 lxml==3.6.2
-OWSLib==0.10.3
-pyproj==1.9.3
-Shapely==1.3.1
+OWSLib==0.16.0
+pyproj==1.9.5.1
+Shapely==1.5.17
 six==1.10.0
-xmltodict==0.9.2
+xmltodict==0.10.2
diff --git a/setup.py b/setup.py
index 9c08d13..9ff85e1 100644
--- a/setup.py
+++ b/setup.py
@@ -2,8 +2,10 @@
 # =================================================================
 #
 # Authors: Tom Kralidis <tomkralidis at gmail.com>
+#          Ricardo Garcia Silva <ricardo.garcia.silva at gmail.com>
 #
 # Copyright (c) 2016 Tom Kralidis
+# Copyright (c) 2017 Ricardo Garcia Silva
 #
 # Permission is hereby granted, free of charge, to any person
 # obtaining a copy of this software and associated documentation
@@ -28,123 +30,54 @@
 #
 # =================================================================
 
+import io
 import os
-from distutils.core import setup
-import pycsw
 
+from setuptools import find_packages, setup
 
-def is_package(path):
-    """Decipher whether a filepath is a Python package"""
-    return (
-        os.path.isdir(path) and
-        os.path.isfile(os.path.join(path, '__init__.py'))
-    )
 
+def read(filename, encoding="utf-8"):
+    full_path = os.path.join(os.path.dirname(__file__), filename)
+    with io.open(full_path, encoding=encoding) as fh:
+        contents = fh.read().strip()
+    return contents
 
-def find_packages(path, base=''):
-    """Find all packages in path"""
-    packages = {}
-    for item in os.listdir(path):
-        directory = os.path.join(path, item)
-        if is_package(directory):
-            if base:
-                module_name = "%(base)s.%(item)s" % vars()
-            else:
-                module_name = item
-            packages[module_name] = directory
-            packages.update(find_packages(directory, module_name))
-    return packages
-
-
-def find_packages_xsd(location='.'):
-    """
-    Figure out which packages need to be specified as package_data
-    keys (the ones with XML Schema documents
-    """
-    packages = []
-    for root, dirs, files in os.walk(location):
-        if 'schemas' in dirs:  # include as a package_data key
-            packages.append(root.replace(os.sep, '.').replace('..', ''))
-    return packages
-
-
-def get_package_data(location='.', forced_dir=None):
-    """Generate package_data dict"""
-    package_data = {}
-    for ploc in location:
-        # turn package identifier into filepath
-        filepath = ploc.replace('.', os.sep)
-        if forced_dir is not None:  # force os.walk to traverse subdir
-            filepath = '%s%sschemas' % (filepath, os.sep)
-        for root, dirs, files in os.walk(filepath):
-            if len(files) > 0:
-                # find all the XML Schema documents
-                xsds = [x for x in files if x.find('.xsd') != -1]
-                catalog_xml = [x for x in files if x.find('catalog.xml') != -1]
-                xsds.extend(catalog_xml)
-                if len(xsds) > 0:
-                    if ploc not in package_data:  # set key
-                        package_data[ploc] = []
-                    for xsd in xsds:  # add filename to list
-                        root2 = root.replace(filepath, '').split(os.sep)[1:]
-                        pathstr = '%s%s%s' % (os.sep.join(root2), os.sep, xsd)
-                        if forced_dir is not None:
-                            filename = 'schemas%s%s' % (os.sep, pathstr)
-                        else:
-                            filename = pathstr
-                        package_data[ploc].append(filename)
-    return package_data
 
 # ensure a fresh MANIFEST file is generated
 if (os.path.exists('MANIFEST')):
     os.unlink('MANIFEST')
 
-# set setup.packages
-PACKAGES = list(find_packages('.').keys())
-
-# get package_data.keys()
-PACKAGE_DATA_XSD = find_packages_xsd('pycsw')
-
-# Because package 'pycsw' contains all other packages,
-# process it last, so that it doesn't set it's package_data
-# files to one already set in other packages
-ROOT_PACKAGE = PACKAGE_DATA_XSD.pop(0)
-
-# set package_data
-PACKAGE_DATA = get_package_data(PACKAGE_DATA_XSD)
-
-# update package_data for pycsw package
-PACKAGE_DATA.update(get_package_data([ROOT_PACKAGE], 'schemas'))
-
-# set the dependencies
-# GeoNode, HHypermap and OpenDataCatalog do not require SQLAlchemy
-with open('requirements.txt') as f:
-    INSTALL_REQUIRES = f.read().splitlines()
-
-KEYWORDS = ('pycsw csw catalogue catalog metadata discovery search'
-            ' ogc iso fgdc dif ebrim inspire')
-
-DESCRIPTION = 'pycsw is an OGC CSW server implementation written in Python'
-
-with open('README.txt') as f:
-    LONG_DESCRIPTION = f.read()
-
 setup(
     name='pycsw',
-    version=pycsw.__version__,
-    description=DESCRIPTION,
-    long_description=LONG_DESCRIPTION,
+    version=read("VERSION.txt"),
+    description='pycsw is an OGC CSW server implementation written in Python',
+    long_description=read("README.rst"),
     license='MIT',
     platforms='all',
-    keywords=KEYWORDS,
+    keywords=" ".join([
+        'pycsw',
+        'csw',
+        'catalogue',
+        'catalog',
+        'metadata',
+        'discovery',
+        'search',
+        'ogc',
+        'iso',
+        'fgdc',
+        'dif',
+        'ebrim',
+        'inspire',
+    ]),
     author='Tom Kralidis',
     author_email='tomkralidis at gmail.com',
     maintainer='Tom Kralidis',
     maintainer_email='tomkralidis at gmail.com',
     url='http://pycsw.org/',
-    install_requires=INSTALL_REQUIRES,
-    packages=PACKAGES,
-    package_data=PACKAGE_DATA,
+    install_requires=read("requirements.txt").splitlines(),
+    packages=find_packages(),
+    include_package_data=True,
+    # TODO: replace scripts with entry_points (needs a refactoring of pycsw-admin first)
     scripts=[os.path.join('bin', 'pycsw-admin.py')],
     classifiers=[
         'Development Status :: 5 - Production/Stable',
@@ -154,9 +87,9 @@ setup(
         'License :: OSI Approved :: MIT License',
         'Operating System :: OS Independent',
         'Programming Language :: Python',
-        'Programming Language :: Python :: 2.6',
         'Programming Language :: Python :: 2.7',
         'Programming Language :: Python :: 3.4',
+        'Programming Language :: Python :: 3.5',
         'Topic :: Scientific/Engineering :: GIS',
     ]
 )
diff --git a/tests/conftest.py b/tests/conftest.py
new file mode 100644
index 0000000..19cb0b0
--- /dev/null
+++ b/tests/conftest.py
@@ -0,0 +1,115 @@
+# =================================================================
+#
+# Authors: Ricardo Garcia Silva <ricardo.garcia.silva at gmail.com>
+#
+# Copyright (c) 2016 Ricardo Garcia Silva
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation
+# files (the "Software"), to deal in the Software without
+# restriction, including without limitation the rights to use,
+# copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following
+# conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+#
+# =================================================================
+"""pytest configuration file"""
+
+import pytest
+
+
+def pytest_configure(config):
+    """Configure pytest.
+
+    This function adds additional markers to pytest.
+
+    """
+
+    config.addinivalue_line(
+        "markers",
+        "functional: Run only functional tests"
+    )
+    config.addinivalue_line(
+        "markers",
+        "unit: Run only unit tests"
+    )
+
+
+def pytest_addoption(parser):
+    """Add additional command-line parameters to pytest."""
+    parser.addoption(
+        "--database-backend",
+        choices=["sqlite", "postgresql"],
+        default="sqlite",
+        help="Database backend to use when performing functional tests"
+    )
+    parser.addoption(
+        "--database-user-postgresql",
+        default="postgres",
+        help="Username to use for creating and accessing local postgres "
+             "databases used for functional tests."
+    )
+    parser.addoption(
+        "--database-password-postgresql",
+        default="",
+        help="Password to use for creating and accessing local postgres "
+             "databases used for functional tests."
+    )
+    parser.addoption(
+        "--database-name-postgresql",
+        default="test_pycsw",
+        help="Name of the postgres database that is to be used for testing."
+    )
+    parser.addoption(
+        "--database-host-postgresql",
+        default="127.0.0.1",
+        help="hostname or ip of the host that is running the postgres "
+             "database server to use in testing."
+    )
+    parser.addoption(
+        "--database-port-postgresql",
+        default="5432",
+        help="Port where the postgres server is listening for connections."
+    )
+    parser.addoption(
+        "--pycsw-loglevel",
+        default="warning",
+        help="Log level for the pycsw server."
+    )
+    parser.addoption(
+        "--functional-prefer-diffs",
+        action="store_true",
+        help="When running functional tests, compare results with their "
+             "expected values by using diffs instead of XML canonicalisation "
+             "(the default)."
+    )
+    parser.addoption(
+        "--functional-save-results-directory",
+        help="When running functional tests, save each test's result under "
+             "the input directory path."
+    )
+
+
+ at pytest.fixture(scope="session")
+def log_level(request):
+    """Log level to use when instantiating a new pycsw server.
+
+    The value for this fixture is retrieved from the `--pycsw.loglevel`
+    command-line parameter.
+
+    """
+
+    return request.config.getoption("pycsw_loglevel").upper()
diff --git a/tests/expected/suites_cite_get_f4692ec5-9547-4a05-88ab-e6154af2640a.xml b/tests/expected/suites_cite_get_f4692ec5-9547-4a05-88ab-e6154af2640a.xml
deleted file mode 100644
index b3c13e3..0000000
--- a/tests/expected/suites_cite_get_f4692ec5-9547-4a05-88ab-e6154af2640a.xml
+++ /dev/null
@@ -1,310 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- PYCSW_VERSION -->
-<csw:Capabilities xmlns:csw="http://www.opengis.net/cat/csw/2.0.2" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dct="http://purl.org/dc/terms/" xmlns:gmd="http://www.isotc211.org/2005/gmd" xmlns:gml="http://www.opengis.net/gml" xmlns:ogc="http://www.opengis.net/ogc" xmlns:ows="http://www.opengis.net/ows" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" updateSequence="PYCSW_UPDATESEQUENCE" ve [...]
-  <ows:ServiceIdentification>
-    <ows:Title>pycsw Geospatial Catalogue</ows:Title>
-    <ows:Abstract>pycsw is an OGC CSW server implementation written in Python</ows:Abstract>
-    <ows:Keywords>
-      <ows:Keyword>catalogue</ows:Keyword>
-      <ows:Keyword>discovery</ows:Keyword>
-      <ows:Type codeSpace="ISOTC211/19115">theme</ows:Type>
-    </ows:Keywords>
-    <ows:ServiceType codeSpace="OGC">CSW</ows:ServiceType>
-    <ows:ServiceTypeVersion>2.0.2</ows:ServiceTypeVersion>
-    <ows:ServiceTypeVersion>3.0.0</ows:ServiceTypeVersion>
-    <ows:Fees>None</ows:Fees>
-    <ows:AccessConstraints>None</ows:AccessConstraints>
-  </ows:ServiceIdentification>
-  <ows:ServiceProvider>
-    <ows:ProviderName>pycsw</ows:ProviderName>
-    <ows:ProviderSite xlink:type="simple" xlink:href="http://pycsw.org/"/>
-    <ows:ServiceContact>
-      <ows:IndividualName>Kralidis, Tom</ows:IndividualName>
-      <ows:PositionName>Senior Systems Scientist</ows:PositionName>
-      <ows:ContactInfo>
-        <ows:Phone>
-          <ows:Voice>+01-416-xxx-xxxx</ows:Voice>
-          <ows:Facsimile>+01-416-xxx-xxxx</ows:Facsimile>
-        </ows:Phone>
-        <ows:Address>
-          <ows:DeliveryPoint>TBA</ows:DeliveryPoint>
-          <ows:City>Toronto</ows:City>
-          <ows:AdministrativeArea>Ontario</ows:AdministrativeArea>
-          <ows:PostalCode>M9C 3Z9</ows:PostalCode>
-          <ows:Country>Canada</ows:Country>
-          <ows:ElectronicMailAddress>tomkralidis at gmail.com</ows:ElectronicMailAddress>
-        </ows:Address>
-        <ows:OnlineResource xlink:type="simple" xlink:href="http://kralidis.ca/"/>
-        <ows:HoursOfService>0800h - 1600h EST</ows:HoursOfService>
-        <ows:ContactInstructions>During hours of service.  Off on weekends.</ows:ContactInstructions>
-      </ows:ContactInfo>
-      <ows:Role codeSpace="ISOTC211/19115">pointOfContact</ows:Role>
-    </ows:ServiceContact>
-  </ows:ServiceProvider>
-  <ows:OperationsMetadata>
-    <ows:Operation name="GetCapabilities">
-      <ows:DCP>
-        <ows:HTTP>
-          <ows:Get xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/cite/default.cfg"/>
-          <ows:Post xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/cite/default.cfg"/>
-        </ows:HTTP>
-      </ows:DCP>
-      <ows:Parameter name="sections">
-        <ows:Value>Filter_Capabilities</ows:Value>
-        <ows:Value>OperationsMetadata</ows:Value>
-        <ows:Value>ServiceIdentification</ows:Value>
-        <ows:Value>ServiceProvider</ows:Value>
-      </ows:Parameter>
-    </ows:Operation>
-    <ows:Operation name="DescribeRecord">
-      <ows:DCP>
-        <ows:HTTP>
-          <ows:Get xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/cite/default.cfg"/>
-          <ows:Post xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/cite/default.cfg"/>
-        </ows:HTTP>
-      </ows:DCP>
-      <ows:Parameter name="outputFormat">
-        <ows:Value>application/json</ows:Value>
-        <ows:Value>application/xml</ows:Value>
-      </ows:Parameter>
-      <ows:Parameter name="schemaLanguage">
-        <ows:Value>http://www.w3.org/2001/XMLSchema</ows:Value>
-        <ows:Value>http://www.w3.org/TR/xmlschema-1/</ows:Value>
-        <ows:Value>http://www.w3.org/XML/Schema</ows:Value>
-      </ows:Parameter>
-      <ows:Parameter name="typeName">
-        <ows:Value>csw:Record</ows:Value>
-      </ows:Parameter>
-    </ows:Operation>
-    <ows:Operation name="GetDomain">
-      <ows:DCP>
-        <ows:HTTP>
-          <ows:Get xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/cite/default.cfg"/>
-          <ows:Post xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/cite/default.cfg"/>
-        </ows:HTTP>
-      </ows:DCP>
-      <ows:Parameter name="ParameterName">
-        <ows:Value>DescribeRecord.outputFormat</ows:Value>
-        <ows:Value>DescribeRecord.schemaLanguage</ows:Value>
-        <ows:Value>DescribeRecord.typeName</ows:Value>
-        <ows:Value>GetCapabilities.sections</ows:Value>
-        <ows:Value>GetRecordById.ElementSetName</ows:Value>
-        <ows:Value>GetRecordById.outputFormat</ows:Value>
-        <ows:Value>GetRecordById.outputSchema</ows:Value>
-        <ows:Value>GetRecords.CONSTRAINTLANGUAGE</ows:Value>
-        <ows:Value>GetRecords.ElementSetName</ows:Value>
-        <ows:Value>GetRecords.outputFormat</ows:Value>
-        <ows:Value>GetRecords.outputSchema</ows:Value>
-        <ows:Value>GetRecords.resultType</ows:Value>
-        <ows:Value>GetRecords.typeNames</ows:Value>
-        <ows:Value>Harvest.ResourceType</ows:Value>
-        <ows:Value>Transaction.TransactionSchemas</ows:Value>
-      </ows:Parameter>
-    </ows:Operation>
-    <ows:Operation name="GetRecords">
-      <ows:DCP>
-        <ows:HTTP>
-          <ows:Get xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/cite/default.cfg"/>
-          <ows:Post xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/cite/default.cfg"/>
-        </ows:HTTP>
-      </ows:DCP>
-      <ows:Parameter name="CONSTRAINTLANGUAGE">
-        <ows:Value>CQL_TEXT</ows:Value>
-        <ows:Value>FILTER</ows:Value>
-      </ows:Parameter>
-      <ows:Parameter name="ElementSetName">
-        <ows:Value>brief</ows:Value>
-        <ows:Value>full</ows:Value>
-        <ows:Value>summary</ows:Value>
-      </ows:Parameter>
-      <ows:Parameter name="outputFormat">
-        <ows:Value>application/json</ows:Value>
-        <ows:Value>application/xml</ows:Value>
-      </ows:Parameter>
-      <ows:Parameter name="outputSchema">
-        <ows:Value>http://gcmd.gsfc.nasa.gov/Aboutus/xml/dif/</ows:Value>
-        <ows:Value>http://www.interlis.ch/INTERLIS2.3</ows:Value>
-        <ows:Value>http://www.opengis.net/cat/csw/2.0.2</ows:Value>
-        <ows:Value>http://www.opengis.net/cat/csw/csdgm</ows:Value>
-        <ows:Value>http://www.w3.org/2005/Atom</ows:Value>
-      </ows:Parameter>
-      <ows:Parameter name="resultType">
-        <ows:Value>hits</ows:Value>
-        <ows:Value>results</ows:Value>
-        <ows:Value>validate</ows:Value>
-      </ows:Parameter>
-      <ows:Parameter name="typeNames">
-        <ows:Value>csw:Record</ows:Value>
-      </ows:Parameter>
-      <ows:Constraint name="SupportedDublinCoreQueryables">
-        <ows:Value>csw:AnyText</ows:Value>
-        <ows:Value>dc:contributor</ows:Value>
-        <ows:Value>dc:creator</ows:Value>
-        <ows:Value>dc:date</ows:Value>
-        <ows:Value>dc:format</ows:Value>
-        <ows:Value>dc:identifier</ows:Value>
-        <ows:Value>dc:language</ows:Value>
-        <ows:Value>dc:publisher</ows:Value>
-        <ows:Value>dc:relation</ows:Value>
-        <ows:Value>dc:rights</ows:Value>
-        <ows:Value>dc:source</ows:Value>
-        <ows:Value>dc:subject</ows:Value>
-        <ows:Value>dc:title</ows:Value>
-        <ows:Value>dc:type</ows:Value>
-        <ows:Value>dct:abstract</ows:Value>
-        <ows:Value>dct:alternative</ows:Value>
-        <ows:Value>dct:modified</ows:Value>
-        <ows:Value>dct:spatial</ows:Value>
-        <ows:Value>ows:BoundingBox</ows:Value>
-      </ows:Constraint>
-    </ows:Operation>
-    <ows:Operation name="GetRecordById">
-      <ows:DCP>
-        <ows:HTTP>
-          <ows:Get xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/cite/default.cfg"/>
-          <ows:Post xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/cite/default.cfg"/>
-        </ows:HTTP>
-      </ows:DCP>
-      <ows:Parameter name="ElementSetName">
-        <ows:Value>brief</ows:Value>
-        <ows:Value>full</ows:Value>
-        <ows:Value>summary</ows:Value>
-      </ows:Parameter>
-      <ows:Parameter name="outputFormat">
-        <ows:Value>application/json</ows:Value>
-        <ows:Value>application/xml</ows:Value>
-      </ows:Parameter>
-      <ows:Parameter name="outputSchema">
-        <ows:Value>http://gcmd.gsfc.nasa.gov/Aboutus/xml/dif/</ows:Value>
-        <ows:Value>http://www.interlis.ch/INTERLIS2.3</ows:Value>
-        <ows:Value>http://www.opengis.net/cat/csw/2.0.2</ows:Value>
-        <ows:Value>http://www.opengis.net/cat/csw/csdgm</ows:Value>
-        <ows:Value>http://www.w3.org/2005/Atom</ows:Value>
-      </ows:Parameter>
-    </ows:Operation>
-    <ows:Operation name="GetRepositoryItem">
-      <ows:DCP>
-        <ows:HTTP>
-          <ows:Get xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/cite/default.cfg"/>
-        </ows:HTTP>
-      </ows:DCP>
-    </ows:Operation>
-    <ows:Operation name="Transaction">
-      <ows:DCP>
-        <ows:HTTP>
-          <ows:Post xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/cite/default.cfg"/>
-        </ows:HTTP>
-      </ows:DCP>
-      <ows:Parameter name="TransactionSchemas">
-        <ows:Value>http://www.isotc211.org/2005/gmi</ows:Value>
-        <ows:Value>http://www.opengis.net/cat/csw/2.0.2</ows:Value>
-        <ows:Value>http://www.opengis.net/cat/csw/3.0</ows:Value>
-        <ows:Value>http://www.opengis.net/sos/1.0</ows:Value>
-        <ows:Value>http://www.opengis.net/sos/2.0</ows:Value>
-        <ows:Value>http://www.opengis.net/wcs</ows:Value>
-        <ows:Value>http://www.opengis.net/wfs</ows:Value>
-        <ows:Value>http://www.opengis.net/wms</ows:Value>
-        <ows:Value>http://www.opengis.net/wmts/1.0</ows:Value>
-        <ows:Value>http://www.opengis.net/wps/1.0.0</ows:Value>
-        <ows:Value>urn:geoss:waf</ows:Value>
-      </ows:Parameter>
-    </ows:Operation>
-    <ows:Operation name="Harvest">
-      <ows:DCP>
-        <ows:HTTP>
-          <ows:Post xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/cite/default.cfg"/>
-        </ows:HTTP>
-      </ows:DCP>
-      <ows:Parameter name="ResourceType">
-        <ows:Value>http://gcmd.gsfc.nasa.gov/Aboutus/xml/dif/</ows:Value>
-        <ows:Value>http://www.interlis.ch/INTERLIS2.3</ows:Value>
-        <ows:Value>http://www.isotc211.org/2005/gmi</ows:Value>
-        <ows:Value>http://www.opengis.net/cat/csw/2.0.2</ows:Value>
-        <ows:Value>http://www.opengis.net/cat/csw/3.0</ows:Value>
-        <ows:Value>http://www.opengis.net/cat/csw/csdgm</ows:Value>
-        <ows:Value>http://www.opengis.net/sos/1.0</ows:Value>
-        <ows:Value>http://www.opengis.net/sos/2.0</ows:Value>
-        <ows:Value>http://www.opengis.net/wcs</ows:Value>
-        <ows:Value>http://www.opengis.net/wfs</ows:Value>
-        <ows:Value>http://www.opengis.net/wms</ows:Value>
-        <ows:Value>http://www.opengis.net/wmts/1.0</ows:Value>
-        <ows:Value>http://www.opengis.net/wps/1.0.0</ows:Value>
-        <ows:Value>http://www.w3.org/2005/Atom</ows:Value>
-        <ows:Value>urn:geoss:waf</ows:Value>
-      </ows:Parameter>
-    </ows:Operation>
-    <ows:Parameter name="service">
-      <ows:Value>CSW</ows:Value>
-    </ows:Parameter>
-    <ows:Parameter name="version">
-      <ows:Value>2.0.2</ows:Value>
-      <ows:Value>3.0.0</ows:Value>
-    </ows:Parameter>
-    <ows:Constraint name="FederatedCatalogues">
-      <ows:Value>http://geo.data.gov/geoportal/csw/discovery</ows:Value>
-    </ows:Constraint>
-    <ows:Constraint name="MaxRecordDefault">
-      <ows:Value>10</ows:Value>
-    </ows:Constraint>
-    <ows:Constraint name="PostEncoding">
-      <ows:Value>XML</ows:Value>
-      <ows:Value>SOAP</ows:Value>
-    </ows:Constraint>
-    <ows:Constraint name="XPathQueryables">
-      <ows:Value>allowed</ows:Value>
-    </ows:Constraint>
-  </ows:OperationsMetadata>
-  <ogc:Filter_Capabilities>
-    <ogc:Spatial_Capabilities>
-      <ogc:GeometryOperands>
-        <ogc:GeometryOperand>gml:Point</ogc:GeometryOperand>
-        <ogc:GeometryOperand>gml:LineString</ogc:GeometryOperand>
-        <ogc:GeometryOperand>gml:Polygon</ogc:GeometryOperand>
-        <ogc:GeometryOperand>gml:Envelope</ogc:GeometryOperand>
-      </ogc:GeometryOperands>
-      <ogc:SpatialOperators>
-        <ogc:SpatialOperator name="BBOX"/>
-        <ogc:SpatialOperator name="Beyond"/>
-        <ogc:SpatialOperator name="Contains"/>
-        <ogc:SpatialOperator name="Crosses"/>
-        <ogc:SpatialOperator name="Disjoint"/>
-        <ogc:SpatialOperator name="DWithin"/>
-        <ogc:SpatialOperator name="Equals"/>
-        <ogc:SpatialOperator name="Intersects"/>
-        <ogc:SpatialOperator name="Overlaps"/>
-        <ogc:SpatialOperator name="Touches"/>
-        <ogc:SpatialOperator name="Within"/>
-      </ogc:SpatialOperators>
-    </ogc:Spatial_Capabilities>
-    <ogc:Scalar_Capabilities>
-      <ogc:LogicalOperators/>
-      <ogc:ComparisonOperators>
-        <ogc:ComparisonOperator>Between</ogc:ComparisonOperator>
-        <ogc:ComparisonOperator>EqualTo</ogc:ComparisonOperator>
-        <ogc:ComparisonOperator>GreaterThan</ogc:ComparisonOperator>
-        <ogc:ComparisonOperator>GreaterThanEqualTo</ogc:ComparisonOperator>
-        <ogc:ComparisonOperator>LessThan</ogc:ComparisonOperator>
-        <ogc:ComparisonOperator>LessThanEqualTo</ogc:ComparisonOperator>
-        <ogc:ComparisonOperator>Like</ogc:ComparisonOperator>
-        <ogc:ComparisonOperator>NotEqualTo</ogc:ComparisonOperator>
-        <ogc:ComparisonOperator>NullCheck</ogc:ComparisonOperator>
-      </ogc:ComparisonOperators>
-      <ogc:ArithmeticOperators>
-        <ogc:Functions>
-          <ogc:FunctionNames>
-            <ogc:FunctionName nArgs="1">length</ogc:FunctionName>
-            <ogc:FunctionName nArgs="1">lower</ogc:FunctionName>
-            <ogc:FunctionName nArgs="1">ltrim</ogc:FunctionName>
-            <ogc:FunctionName nArgs="1">rtrim</ogc:FunctionName>
-            <ogc:FunctionName nArgs="1">trim</ogc:FunctionName>
-            <ogc:FunctionName nArgs="1">upper</ogc:FunctionName>
-          </ogc:FunctionNames>
-        </ogc:Functions>
-      </ogc:ArithmeticOperators>
-    </ogc:Scalar_Capabilities>
-    <ogc:Id_Capabilities>
-      <ogc:EID/>
-      <ogc:FID/>
-    </ogc:Id_Capabilities>
-  </ogc:Filter_Capabilities>
-</csw:Capabilities>
diff --git a/tests/expected/suites_csw30_get_2b06a5c8-0df2-4af1-8d2e-a425de11c845.xml b/tests/expected/suites_csw30_get_2b06a5c8-0df2-4af1-8d2e-a425de11c845.xml
deleted file mode 100644
index c5cb70e..0000000
--- a/tests/expected/suites_csw30_get_2b06a5c8-0df2-4af1-8d2e-a425de11c845.xml
+++ /dev/null
@@ -1,493 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- PYCSW_VERSION -->
-<csw30:Capabilities xmlns:csw="http://www.opengis.net/cat/csw/2.0.2" xmlns:csw30="http://www.opengis.net/cat/csw/3.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dct="http://purl.org/dc/terms/" xmlns:fes20="http://www.opengis.net/fes/2.0" xmlns:gmd="http://www.isotc211.org/2005/gmd" xmlns:gml="http://www.opengis.net/gml" xmlns:ows="http://www.opengis.net/ows" xmlns:ows11="http://www.opengis.net/ows/1.1" xmlns:ows20="http://www.opengis.net/ows/2.0" xmlns:xlink="http://www.w3.org/199 [...]
-  <ows20:ServiceIdentification>
-    <ows20:Title>pycsw Geospatial Catalogue</ows20:Title>
-    <ows20:Abstract>pycsw is an OGC CSW server implementation written in Python</ows20:Abstract>
-    <ows20:Keywords>
-      <ows20:Keyword>catalogue</ows20:Keyword>
-      <ows20:Keyword>discovery</ows20:Keyword>
-      <ows20:Type codeSpace="ISOTC211/19115">theme</ows20:Type>
-    </ows20:Keywords>
-    <ows20:ServiceType codeSpace="OGC">CSW</ows20:ServiceType>
-    <ows20:ServiceTypeVersion>2.0.2</ows20:ServiceTypeVersion>
-    <ows20:ServiceTypeVersion>3.0.0</ows20:ServiceTypeVersion>
-    <ows20:Fees>None</ows20:Fees>
-    <ows20:AccessConstraints>None</ows20:AccessConstraints>
-  </ows20:ServiceIdentification>
-  <ows20:ServiceProvider>
-    <ows20:ProviderName>pycsw</ows20:ProviderName>
-    <ows20:ProviderSite xlink:type="simple" xlink:href="http://pycsw.org/"/>
-    <ows20:ServiceContact>
-      <ows20:IndividualName>Kralidis, Tom</ows20:IndividualName>
-      <ows20:PositionName>Senior Systems Scientist</ows20:PositionName>
-      <ows20:ContactInfo>
-        <ows20:Phone>
-          <ows20:Voice>+01-416-xxx-xxxx</ows20:Voice>
-          <ows20:Facsimile>+01-416-xxx-xxxx</ows20:Facsimile>
-        </ows20:Phone>
-        <ows20:Address>
-          <ows20:DeliveryPoint>TBA</ows20:DeliveryPoint>
-          <ows20:City>Toronto</ows20:City>
-          <ows20:AdministrativeArea>Ontario</ows20:AdministrativeArea>
-          <ows20:PostalCode>M9C 3Z9</ows20:PostalCode>
-          <ows20:Country>Canada</ows20:Country>
-          <ows20:ElectronicMailAddress>tomkralidis at gmail.com</ows20:ElectronicMailAddress>
-        </ows20:Address>
-        <ows20:OnlineResource xlink:type="simple" xlink:href="http://kralidis.ca/"/>
-        <ows20:HoursOfService>0800h - 1600h EST</ows20:HoursOfService>
-        <ows20:ContactInstructions>During hours of service.  Off on weekends.</ows20:ContactInstructions>
-      </ows20:ContactInfo>
-      <ows20:Role codeSpace="ISOTC211/19115">pointOfContact</ows20:Role>
-    </ows20:ServiceContact>
-  </ows20:ServiceProvider>
-  <ows20:OperationsMetadata>
-    <ows20:Operation name="GetCapabilities">
-      <ows20:DCP>
-        <ows20:HTTP>
-          <ows20:Get xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-          <ows20:Post xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-        </ows20:HTTP>
-      </ows20:DCP>
-      <ows20:Parameter name="acceptFormats">
-        <ows20:AllowedValues>
-          <ows20:Value>application/xml</ows20:Value>
-          <ows20:Value>text/xml</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="acceptVersions">
-        <ows20:AllowedValues>
-          <ows20:Value>2.0.2</ows20:Value>
-          <ows20:Value>3.0.0</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="sections">
-        <ows20:AllowedValues>
-          <ows20:Value>All</ows20:Value>
-          <ows20:Value>Filter_Capabilities</ows20:Value>
-          <ows20:Value>OperationsMetadata</ows20:Value>
-          <ows20:Value>ServiceIdentification</ows20:Value>
-          <ows20:Value>ServiceProvider</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-    </ows20:Operation>
-    <ows20:Operation name="GetDomain">
-      <ows20:DCP>
-        <ows20:HTTP>
-          <ows20:Get xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-          <ows20:Post xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-        </ows20:HTTP>
-      </ows20:DCP>
-      <ows20:Parameter name="ParameterName">
-        <ows20:AllowedValues>
-          <ows20:Value>GetCapabilities.acceptFormats</ows20:Value>
-          <ows20:Value>GetCapabilities.acceptVersions</ows20:Value>
-          <ows20:Value>GetCapabilities.sections</ows20:Value>
-          <ows20:Value>GetRecordById.ElementSetName</ows20:Value>
-          <ows20:Value>GetRecordById.outputFormat</ows20:Value>
-          <ows20:Value>GetRecordById.outputSchema</ows20:Value>
-          <ows20:Value>GetRecords.CONSTRAINTLANGUAGE</ows20:Value>
-          <ows20:Value>GetRecords.ElementSetName</ows20:Value>
-          <ows20:Value>GetRecords.outputFormat</ows20:Value>
-          <ows20:Value>GetRecords.outputSchema</ows20:Value>
-          <ows20:Value>GetRecords.typeNames</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-    </ows20:Operation>
-    <ows20:Operation name="GetRecords">
-      <ows20:DCP>
-        <ows20:HTTP>
-          <ows20:Get xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-          <ows20:Post xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-        </ows20:HTTP>
-      </ows20:DCP>
-      <ows20:Parameter name="CONSTRAINTLANGUAGE">
-        <ows20:AllowedValues>
-          <ows20:Value>CQL_TEXT</ows20:Value>
-          <ows20:Value>FILTER</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="ElementSetName">
-        <ows20:AllowedValues>
-          <ows20:Value>brief</ows20:Value>
-          <ows20:Value>full</ows20:Value>
-          <ows20:Value>summary</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="outputFormat">
-        <ows20:AllowedValues>
-          <ows20:Value>application/atom+xml</ows20:Value>
-          <ows20:Value>application/json</ows20:Value>
-          <ows20:Value>application/xml</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="outputSchema">
-        <ows20:AllowedValues>
-          <ows20:Value>http://gcmd.gsfc.nasa.gov/Aboutus/xml/dif/</ows20:Value>
-          <ows20:Value>http://www.interlis.ch/INTERLIS2.3</ows20:Value>
-          <ows20:Value>http://www.opengis.net/cat/csw/3.0</ows20:Value>
-          <ows20:Value>http://www.opengis.net/cat/csw/csdgm</ows20:Value>
-          <ows20:Value>http://www.w3.org/2005/Atom</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="typeNames">
-        <ows20:AllowedValues>
-          <ows20:Value>csw:Record</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Constraint name="MaxRecordDefault">
-        <ows20:AllowedValues>
-          <ows20:Value>10</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Constraint>
-      <ows20:Constraint name="OpenSearchDescriptionDocument">
-        <ows20:AllowedValues>
-          <ows20:Value>http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg?mode=opensearch&service=CSW&version=3.0.0&request=GetCapabilities</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Constraint>
-      <ows20:Constraint name="FederatedCatalogues">
-        <ows20:AllowedValues>
-          <ows20:Value>http://demo.pycsw.org/gisdata/csw</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Constraint>
-    </ows20:Operation>
-    <ows20:Operation name="GetRecordById">
-      <ows20:DCP>
-        <ows20:HTTP>
-          <ows20:Get xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-          <ows20:Post xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-        </ows20:HTTP>
-      </ows20:DCP>
-      <ows20:Parameter name="ElementSetName">
-        <ows20:AllowedValues>
-          <ows20:Value>brief</ows20:Value>
-          <ows20:Value>full</ows20:Value>
-          <ows20:Value>summary</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="outputFormat">
-        <ows20:AllowedValues>
-          <ows20:Value>application/atom+xml</ows20:Value>
-          <ows20:Value>application/json</ows20:Value>
-          <ows20:Value>application/xml</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="outputSchema">
-        <ows20:AllowedValues>
-          <ows20:Value>http://gcmd.gsfc.nasa.gov/Aboutus/xml/dif/</ows20:Value>
-          <ows20:Value>http://www.interlis.ch/INTERLIS2.3</ows20:Value>
-          <ows20:Value>http://www.opengis.net/cat/csw/3.0</ows20:Value>
-          <ows20:Value>http://www.opengis.net/cat/csw/csdgm</ows20:Value>
-          <ows20:Value>http://www.w3.org/2005/Atom</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-    </ows20:Operation>
-    <ows20:Operation name="GetRepositoryItem">
-      <ows20:DCP>
-        <ows20:HTTP>
-          <ows20:Get xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-        </ows20:HTTP>
-      </ows20:DCP>
-    </ows20:Operation>
-    <ows20:Parameter name="service">
-      <ows20:AllowedValues>
-        <ows20:Value>CSW</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Parameter>
-    <ows20:Parameter name="version">
-      <ows20:AllowedValues>
-        <ows20:Value>2.0.2</ows20:Value>
-        <ows20:Value>3.0.0</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Parameter>
-    <ows20:Constraint name="CoreQueryables">
-      <ows20:AllowedValues>
-        <ows20:Value>csw:AnyText</ows20:Value>
-        <ows20:Value>dc:contributor</ows20:Value>
-        <ows20:Value>dc:creator</ows20:Value>
-        <ows20:Value>dc:date</ows20:Value>
-        <ows20:Value>dc:format</ows20:Value>
-        <ows20:Value>dc:identifier</ows20:Value>
-        <ows20:Value>dc:language</ows20:Value>
-        <ows20:Value>dc:publisher</ows20:Value>
-        <ows20:Value>dc:relation</ows20:Value>
-        <ows20:Value>dc:rights</ows20:Value>
-        <ows20:Value>dc:source</ows20:Value>
-        <ows20:Value>dc:subject</ows20:Value>
-        <ows20:Value>dc:title</ows20:Value>
-        <ows20:Value>dc:type</ows20:Value>
-        <ows20:Value>dct:abstract</ows20:Value>
-        <ows20:Value>dct:alternative</ows20:Value>
-        <ows20:Value>dct:modified</ows20:Value>
-        <ows20:Value>dct:spatial</ows20:Value>
-        <ows20:Value>ows:BoundingBox</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="FederatedCatalogues">
-      <ows20:AllowedValues>
-        <ows20:Value>http://demo.pycsw.org/gisdata/csw</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="MaxRecordDefault">
-      <ows20:AllowedValues>
-        <ows20:Value>10</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="PostEncoding">
-      <ows20:AllowedValues>
-        <ows20:Value>SOAP</ows20:Value>
-        <ows20:Value>XML</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="XPathQueryables">
-      <ows20:AllowedValues>
-        <ows20:Value>allowed</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/CoreQueryables">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/CoreSortables">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/DefaultSortingAlgorithm">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Filter-CQL">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Filter-FES-KVP-Advanced">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Filter-FES-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetCapabilities-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetDomain-KVP">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetDomain-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetRecordById-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetRecords-Async-KVP">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetRecords-Async-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetRecords-Basic-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetRecords-Distributed-KVP">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetRecords-Distributed-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Harvest-Async-KVP">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Harvest-Async-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Harvest-Basic-KVP">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Harvest-Basic-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Harvest-Periodic-KVP">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Harvest-Periodic-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/OpenSearch">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/SupportedGMLVersions">
-      <ows20:AllowedValues>
-        <ows20:Value>http://www.opengis.net/gml</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Transaction">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-  </ows20:OperationsMetadata>
-  <ows20:Languages>
-    <ows20:Language>en</ows20:Language>
-  </ows20:Languages>
-  <fes20:Filter_Capabilities>
-    <fes20:Conformance>
-      <fes20:Constraint name="ImplementsQuery">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsAdHocQuery">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsFunctions">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsResourceld">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsMinStandardFilter">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsStandardFilter">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsMinSpatialFilter">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsSpatialFilter">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsMinTemporalFilter">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsTemporalFilter">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsVersionNav">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsSorting">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsExtendedOperators">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsMinimumXPath">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsSchemaElementFunc">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-    </fes20:Conformance>
-    <fes20:Id_Capabilities>
-      <fes20:ResourceIdentifier name="csw30:id"/>
-    </fes20:Id_Capabilities>
-    <fes20:Scalar_Capabilities>
-      <fes20:LogicalOperators/>
-      <fes20:ComparisonOperators>
-        <fes20:ComparisonOperator name="PropertyIsBetween"/>
-        <fes20:ComparisonOperator name="PropertyIsEqualTo"/>
-        <fes20:ComparisonOperator name="PropertyIsGreaterThan"/>
-        <fes20:ComparisonOperator name="PropertyIsGreaterThanOrEqualTo"/>
-        <fes20:ComparisonOperator name="PropertyIsLessThan"/>
-        <fes20:ComparisonOperator name="PropertyIsLessThanOrEqualTo"/>
-        <fes20:ComparisonOperator name="PropertyIsLike"/>
-        <fes20:ComparisonOperator name="PropertyIsNotEqualTo"/>
-        <fes20:ComparisonOperator name="PropertyIsNull"/>
-      </fes20:ComparisonOperators>
-    </fes20:Scalar_Capabilities>
-    <fes20:Spatial_Capabilities>
-      <fes20:GeometryOperands>
-        <fes20:GeometryOperand name="gml:Point"/>
-        <fes20:GeometryOperand name="gml:LineString"/>
-        <fes20:GeometryOperand name="gml:Polygon"/>
-        <fes20:GeometryOperand name="gml:Envelope"/>
-      </fes20:GeometryOperands>
-      <fes20:SpatialOperators>
-        <fes20:SpatialOperator name="BBOX"/>
-        <fes20:SpatialOperator name="Beyond"/>
-        <fes20:SpatialOperator name="Contains"/>
-        <fes20:SpatialOperator name="Crosses"/>
-        <fes20:SpatialOperator name="Disjoint"/>
-        <fes20:SpatialOperator name="DWithin"/>
-        <fes20:SpatialOperator name="Equals"/>
-        <fes20:SpatialOperator name="Intersects"/>
-        <fes20:SpatialOperator name="Overlaps"/>
-        <fes20:SpatialOperator name="Touches"/>
-        <fes20:SpatialOperator name="Within"/>
-      </fes20:SpatialOperators>
-    </fes20:Spatial_Capabilities>
-    <fes20:Functions>
-      <fes20:Function name="length">
-        <fes20:Returns>xs:string</fes20:Returns>
-      </fes20:Function>
-      <fes20:Function name="lower">
-        <fes20:Returns>xs:string</fes20:Returns>
-      </fes20:Function>
-      <fes20:Function name="ltrim">
-        <fes20:Returns>xs:string</fes20:Returns>
-      </fes20:Function>
-      <fes20:Function name="rtrim">
-        <fes20:Returns>xs:string</fes20:Returns>
-      </fes20:Function>
-      <fes20:Function name="trim">
-        <fes20:Returns>xs:string</fes20:Returns>
-      </fes20:Function>
-      <fes20:Function name="upper">
-        <fes20:Returns>xs:string</fes20:Returns>
-      </fes20:Function>
-    </fes20:Functions>
-  </fes20:Filter_Capabilities>
-</csw30:Capabilities>
diff --git a/tests/expected/suites_csw30_get_43cd6471-6ac7-45bd-8ff9-148cb2de9a52.xml b/tests/expected/suites_csw30_get_43cd6471-6ac7-45bd-8ff9-148cb2de9a52.xml
deleted file mode 100644
index c5cb70e..0000000
--- a/tests/expected/suites_csw30_get_43cd6471-6ac7-45bd-8ff9-148cb2de9a52.xml
+++ /dev/null
@@ -1,493 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- PYCSW_VERSION -->
-<csw30:Capabilities xmlns:csw="http://www.opengis.net/cat/csw/2.0.2" xmlns:csw30="http://www.opengis.net/cat/csw/3.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dct="http://purl.org/dc/terms/" xmlns:fes20="http://www.opengis.net/fes/2.0" xmlns:gmd="http://www.isotc211.org/2005/gmd" xmlns:gml="http://www.opengis.net/gml" xmlns:ows="http://www.opengis.net/ows" xmlns:ows11="http://www.opengis.net/ows/1.1" xmlns:ows20="http://www.opengis.net/ows/2.0" xmlns:xlink="http://www.w3.org/199 [...]
-  <ows20:ServiceIdentification>
-    <ows20:Title>pycsw Geospatial Catalogue</ows20:Title>
-    <ows20:Abstract>pycsw is an OGC CSW server implementation written in Python</ows20:Abstract>
-    <ows20:Keywords>
-      <ows20:Keyword>catalogue</ows20:Keyword>
-      <ows20:Keyword>discovery</ows20:Keyword>
-      <ows20:Type codeSpace="ISOTC211/19115">theme</ows20:Type>
-    </ows20:Keywords>
-    <ows20:ServiceType codeSpace="OGC">CSW</ows20:ServiceType>
-    <ows20:ServiceTypeVersion>2.0.2</ows20:ServiceTypeVersion>
-    <ows20:ServiceTypeVersion>3.0.0</ows20:ServiceTypeVersion>
-    <ows20:Fees>None</ows20:Fees>
-    <ows20:AccessConstraints>None</ows20:AccessConstraints>
-  </ows20:ServiceIdentification>
-  <ows20:ServiceProvider>
-    <ows20:ProviderName>pycsw</ows20:ProviderName>
-    <ows20:ProviderSite xlink:type="simple" xlink:href="http://pycsw.org/"/>
-    <ows20:ServiceContact>
-      <ows20:IndividualName>Kralidis, Tom</ows20:IndividualName>
-      <ows20:PositionName>Senior Systems Scientist</ows20:PositionName>
-      <ows20:ContactInfo>
-        <ows20:Phone>
-          <ows20:Voice>+01-416-xxx-xxxx</ows20:Voice>
-          <ows20:Facsimile>+01-416-xxx-xxxx</ows20:Facsimile>
-        </ows20:Phone>
-        <ows20:Address>
-          <ows20:DeliveryPoint>TBA</ows20:DeliveryPoint>
-          <ows20:City>Toronto</ows20:City>
-          <ows20:AdministrativeArea>Ontario</ows20:AdministrativeArea>
-          <ows20:PostalCode>M9C 3Z9</ows20:PostalCode>
-          <ows20:Country>Canada</ows20:Country>
-          <ows20:ElectronicMailAddress>tomkralidis at gmail.com</ows20:ElectronicMailAddress>
-        </ows20:Address>
-        <ows20:OnlineResource xlink:type="simple" xlink:href="http://kralidis.ca/"/>
-        <ows20:HoursOfService>0800h - 1600h EST</ows20:HoursOfService>
-        <ows20:ContactInstructions>During hours of service.  Off on weekends.</ows20:ContactInstructions>
-      </ows20:ContactInfo>
-      <ows20:Role codeSpace="ISOTC211/19115">pointOfContact</ows20:Role>
-    </ows20:ServiceContact>
-  </ows20:ServiceProvider>
-  <ows20:OperationsMetadata>
-    <ows20:Operation name="GetCapabilities">
-      <ows20:DCP>
-        <ows20:HTTP>
-          <ows20:Get xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-          <ows20:Post xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-        </ows20:HTTP>
-      </ows20:DCP>
-      <ows20:Parameter name="acceptFormats">
-        <ows20:AllowedValues>
-          <ows20:Value>application/xml</ows20:Value>
-          <ows20:Value>text/xml</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="acceptVersions">
-        <ows20:AllowedValues>
-          <ows20:Value>2.0.2</ows20:Value>
-          <ows20:Value>3.0.0</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="sections">
-        <ows20:AllowedValues>
-          <ows20:Value>All</ows20:Value>
-          <ows20:Value>Filter_Capabilities</ows20:Value>
-          <ows20:Value>OperationsMetadata</ows20:Value>
-          <ows20:Value>ServiceIdentification</ows20:Value>
-          <ows20:Value>ServiceProvider</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-    </ows20:Operation>
-    <ows20:Operation name="GetDomain">
-      <ows20:DCP>
-        <ows20:HTTP>
-          <ows20:Get xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-          <ows20:Post xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-        </ows20:HTTP>
-      </ows20:DCP>
-      <ows20:Parameter name="ParameterName">
-        <ows20:AllowedValues>
-          <ows20:Value>GetCapabilities.acceptFormats</ows20:Value>
-          <ows20:Value>GetCapabilities.acceptVersions</ows20:Value>
-          <ows20:Value>GetCapabilities.sections</ows20:Value>
-          <ows20:Value>GetRecordById.ElementSetName</ows20:Value>
-          <ows20:Value>GetRecordById.outputFormat</ows20:Value>
-          <ows20:Value>GetRecordById.outputSchema</ows20:Value>
-          <ows20:Value>GetRecords.CONSTRAINTLANGUAGE</ows20:Value>
-          <ows20:Value>GetRecords.ElementSetName</ows20:Value>
-          <ows20:Value>GetRecords.outputFormat</ows20:Value>
-          <ows20:Value>GetRecords.outputSchema</ows20:Value>
-          <ows20:Value>GetRecords.typeNames</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-    </ows20:Operation>
-    <ows20:Operation name="GetRecords">
-      <ows20:DCP>
-        <ows20:HTTP>
-          <ows20:Get xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-          <ows20:Post xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-        </ows20:HTTP>
-      </ows20:DCP>
-      <ows20:Parameter name="CONSTRAINTLANGUAGE">
-        <ows20:AllowedValues>
-          <ows20:Value>CQL_TEXT</ows20:Value>
-          <ows20:Value>FILTER</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="ElementSetName">
-        <ows20:AllowedValues>
-          <ows20:Value>brief</ows20:Value>
-          <ows20:Value>full</ows20:Value>
-          <ows20:Value>summary</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="outputFormat">
-        <ows20:AllowedValues>
-          <ows20:Value>application/atom+xml</ows20:Value>
-          <ows20:Value>application/json</ows20:Value>
-          <ows20:Value>application/xml</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="outputSchema">
-        <ows20:AllowedValues>
-          <ows20:Value>http://gcmd.gsfc.nasa.gov/Aboutus/xml/dif/</ows20:Value>
-          <ows20:Value>http://www.interlis.ch/INTERLIS2.3</ows20:Value>
-          <ows20:Value>http://www.opengis.net/cat/csw/3.0</ows20:Value>
-          <ows20:Value>http://www.opengis.net/cat/csw/csdgm</ows20:Value>
-          <ows20:Value>http://www.w3.org/2005/Atom</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="typeNames">
-        <ows20:AllowedValues>
-          <ows20:Value>csw:Record</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Constraint name="MaxRecordDefault">
-        <ows20:AllowedValues>
-          <ows20:Value>10</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Constraint>
-      <ows20:Constraint name="OpenSearchDescriptionDocument">
-        <ows20:AllowedValues>
-          <ows20:Value>http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg?mode=opensearch&service=CSW&version=3.0.0&request=GetCapabilities</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Constraint>
-      <ows20:Constraint name="FederatedCatalogues">
-        <ows20:AllowedValues>
-          <ows20:Value>http://demo.pycsw.org/gisdata/csw</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Constraint>
-    </ows20:Operation>
-    <ows20:Operation name="GetRecordById">
-      <ows20:DCP>
-        <ows20:HTTP>
-          <ows20:Get xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-          <ows20:Post xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-        </ows20:HTTP>
-      </ows20:DCP>
-      <ows20:Parameter name="ElementSetName">
-        <ows20:AllowedValues>
-          <ows20:Value>brief</ows20:Value>
-          <ows20:Value>full</ows20:Value>
-          <ows20:Value>summary</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="outputFormat">
-        <ows20:AllowedValues>
-          <ows20:Value>application/atom+xml</ows20:Value>
-          <ows20:Value>application/json</ows20:Value>
-          <ows20:Value>application/xml</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="outputSchema">
-        <ows20:AllowedValues>
-          <ows20:Value>http://gcmd.gsfc.nasa.gov/Aboutus/xml/dif/</ows20:Value>
-          <ows20:Value>http://www.interlis.ch/INTERLIS2.3</ows20:Value>
-          <ows20:Value>http://www.opengis.net/cat/csw/3.0</ows20:Value>
-          <ows20:Value>http://www.opengis.net/cat/csw/csdgm</ows20:Value>
-          <ows20:Value>http://www.w3.org/2005/Atom</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-    </ows20:Operation>
-    <ows20:Operation name="GetRepositoryItem">
-      <ows20:DCP>
-        <ows20:HTTP>
-          <ows20:Get xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-        </ows20:HTTP>
-      </ows20:DCP>
-    </ows20:Operation>
-    <ows20:Parameter name="service">
-      <ows20:AllowedValues>
-        <ows20:Value>CSW</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Parameter>
-    <ows20:Parameter name="version">
-      <ows20:AllowedValues>
-        <ows20:Value>2.0.2</ows20:Value>
-        <ows20:Value>3.0.0</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Parameter>
-    <ows20:Constraint name="CoreQueryables">
-      <ows20:AllowedValues>
-        <ows20:Value>csw:AnyText</ows20:Value>
-        <ows20:Value>dc:contributor</ows20:Value>
-        <ows20:Value>dc:creator</ows20:Value>
-        <ows20:Value>dc:date</ows20:Value>
-        <ows20:Value>dc:format</ows20:Value>
-        <ows20:Value>dc:identifier</ows20:Value>
-        <ows20:Value>dc:language</ows20:Value>
-        <ows20:Value>dc:publisher</ows20:Value>
-        <ows20:Value>dc:relation</ows20:Value>
-        <ows20:Value>dc:rights</ows20:Value>
-        <ows20:Value>dc:source</ows20:Value>
-        <ows20:Value>dc:subject</ows20:Value>
-        <ows20:Value>dc:title</ows20:Value>
-        <ows20:Value>dc:type</ows20:Value>
-        <ows20:Value>dct:abstract</ows20:Value>
-        <ows20:Value>dct:alternative</ows20:Value>
-        <ows20:Value>dct:modified</ows20:Value>
-        <ows20:Value>dct:spatial</ows20:Value>
-        <ows20:Value>ows:BoundingBox</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="FederatedCatalogues">
-      <ows20:AllowedValues>
-        <ows20:Value>http://demo.pycsw.org/gisdata/csw</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="MaxRecordDefault">
-      <ows20:AllowedValues>
-        <ows20:Value>10</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="PostEncoding">
-      <ows20:AllowedValues>
-        <ows20:Value>SOAP</ows20:Value>
-        <ows20:Value>XML</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="XPathQueryables">
-      <ows20:AllowedValues>
-        <ows20:Value>allowed</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/CoreQueryables">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/CoreSortables">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/DefaultSortingAlgorithm">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Filter-CQL">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Filter-FES-KVP-Advanced">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Filter-FES-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetCapabilities-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetDomain-KVP">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetDomain-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetRecordById-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetRecords-Async-KVP">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetRecords-Async-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetRecords-Basic-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetRecords-Distributed-KVP">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetRecords-Distributed-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Harvest-Async-KVP">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Harvest-Async-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Harvest-Basic-KVP">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Harvest-Basic-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Harvest-Periodic-KVP">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Harvest-Periodic-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/OpenSearch">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/SupportedGMLVersions">
-      <ows20:AllowedValues>
-        <ows20:Value>http://www.opengis.net/gml</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Transaction">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-  </ows20:OperationsMetadata>
-  <ows20:Languages>
-    <ows20:Language>en</ows20:Language>
-  </ows20:Languages>
-  <fes20:Filter_Capabilities>
-    <fes20:Conformance>
-      <fes20:Constraint name="ImplementsQuery">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsAdHocQuery">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsFunctions">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsResourceld">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsMinStandardFilter">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsStandardFilter">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsMinSpatialFilter">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsSpatialFilter">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsMinTemporalFilter">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsTemporalFilter">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsVersionNav">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsSorting">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsExtendedOperators">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsMinimumXPath">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsSchemaElementFunc">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-    </fes20:Conformance>
-    <fes20:Id_Capabilities>
-      <fes20:ResourceIdentifier name="csw30:id"/>
-    </fes20:Id_Capabilities>
-    <fes20:Scalar_Capabilities>
-      <fes20:LogicalOperators/>
-      <fes20:ComparisonOperators>
-        <fes20:ComparisonOperator name="PropertyIsBetween"/>
-        <fes20:ComparisonOperator name="PropertyIsEqualTo"/>
-        <fes20:ComparisonOperator name="PropertyIsGreaterThan"/>
-        <fes20:ComparisonOperator name="PropertyIsGreaterThanOrEqualTo"/>
-        <fes20:ComparisonOperator name="PropertyIsLessThan"/>
-        <fes20:ComparisonOperator name="PropertyIsLessThanOrEqualTo"/>
-        <fes20:ComparisonOperator name="PropertyIsLike"/>
-        <fes20:ComparisonOperator name="PropertyIsNotEqualTo"/>
-        <fes20:ComparisonOperator name="PropertyIsNull"/>
-      </fes20:ComparisonOperators>
-    </fes20:Scalar_Capabilities>
-    <fes20:Spatial_Capabilities>
-      <fes20:GeometryOperands>
-        <fes20:GeometryOperand name="gml:Point"/>
-        <fes20:GeometryOperand name="gml:LineString"/>
-        <fes20:GeometryOperand name="gml:Polygon"/>
-        <fes20:GeometryOperand name="gml:Envelope"/>
-      </fes20:GeometryOperands>
-      <fes20:SpatialOperators>
-        <fes20:SpatialOperator name="BBOX"/>
-        <fes20:SpatialOperator name="Beyond"/>
-        <fes20:SpatialOperator name="Contains"/>
-        <fes20:SpatialOperator name="Crosses"/>
-        <fes20:SpatialOperator name="Disjoint"/>
-        <fes20:SpatialOperator name="DWithin"/>
-        <fes20:SpatialOperator name="Equals"/>
-        <fes20:SpatialOperator name="Intersects"/>
-        <fes20:SpatialOperator name="Overlaps"/>
-        <fes20:SpatialOperator name="Touches"/>
-        <fes20:SpatialOperator name="Within"/>
-      </fes20:SpatialOperators>
-    </fes20:Spatial_Capabilities>
-    <fes20:Functions>
-      <fes20:Function name="length">
-        <fes20:Returns>xs:string</fes20:Returns>
-      </fes20:Function>
-      <fes20:Function name="lower">
-        <fes20:Returns>xs:string</fes20:Returns>
-      </fes20:Function>
-      <fes20:Function name="ltrim">
-        <fes20:Returns>xs:string</fes20:Returns>
-      </fes20:Function>
-      <fes20:Function name="rtrim">
-        <fes20:Returns>xs:string</fes20:Returns>
-      </fes20:Function>
-      <fes20:Function name="trim">
-        <fes20:Returns>xs:string</fes20:Returns>
-      </fes20:Function>
-      <fes20:Function name="upper">
-        <fes20:Returns>xs:string</fes20:Returns>
-      </fes20:Function>
-    </fes20:Functions>
-  </fes20:Filter_Capabilities>
-</csw30:Capabilities>
diff --git a/tests/expected/suites_csw30_get_6a9d0558-9d87-495b-b999-b49a3ef1cf99.xml b/tests/expected/suites_csw30_get_6a9d0558-9d87-495b-b999-b49a3ef1cf99.xml
deleted file mode 100644
index c5cb70e..0000000
--- a/tests/expected/suites_csw30_get_6a9d0558-9d87-495b-b999-b49a3ef1cf99.xml
+++ /dev/null
@@ -1,493 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- PYCSW_VERSION -->
-<csw30:Capabilities xmlns:csw="http://www.opengis.net/cat/csw/2.0.2" xmlns:csw30="http://www.opengis.net/cat/csw/3.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dct="http://purl.org/dc/terms/" xmlns:fes20="http://www.opengis.net/fes/2.0" xmlns:gmd="http://www.isotc211.org/2005/gmd" xmlns:gml="http://www.opengis.net/gml" xmlns:ows="http://www.opengis.net/ows" xmlns:ows11="http://www.opengis.net/ows/1.1" xmlns:ows20="http://www.opengis.net/ows/2.0" xmlns:xlink="http://www.w3.org/199 [...]
-  <ows20:ServiceIdentification>
-    <ows20:Title>pycsw Geospatial Catalogue</ows20:Title>
-    <ows20:Abstract>pycsw is an OGC CSW server implementation written in Python</ows20:Abstract>
-    <ows20:Keywords>
-      <ows20:Keyword>catalogue</ows20:Keyword>
-      <ows20:Keyword>discovery</ows20:Keyword>
-      <ows20:Type codeSpace="ISOTC211/19115">theme</ows20:Type>
-    </ows20:Keywords>
-    <ows20:ServiceType codeSpace="OGC">CSW</ows20:ServiceType>
-    <ows20:ServiceTypeVersion>2.0.2</ows20:ServiceTypeVersion>
-    <ows20:ServiceTypeVersion>3.0.0</ows20:ServiceTypeVersion>
-    <ows20:Fees>None</ows20:Fees>
-    <ows20:AccessConstraints>None</ows20:AccessConstraints>
-  </ows20:ServiceIdentification>
-  <ows20:ServiceProvider>
-    <ows20:ProviderName>pycsw</ows20:ProviderName>
-    <ows20:ProviderSite xlink:type="simple" xlink:href="http://pycsw.org/"/>
-    <ows20:ServiceContact>
-      <ows20:IndividualName>Kralidis, Tom</ows20:IndividualName>
-      <ows20:PositionName>Senior Systems Scientist</ows20:PositionName>
-      <ows20:ContactInfo>
-        <ows20:Phone>
-          <ows20:Voice>+01-416-xxx-xxxx</ows20:Voice>
-          <ows20:Facsimile>+01-416-xxx-xxxx</ows20:Facsimile>
-        </ows20:Phone>
-        <ows20:Address>
-          <ows20:DeliveryPoint>TBA</ows20:DeliveryPoint>
-          <ows20:City>Toronto</ows20:City>
-          <ows20:AdministrativeArea>Ontario</ows20:AdministrativeArea>
-          <ows20:PostalCode>M9C 3Z9</ows20:PostalCode>
-          <ows20:Country>Canada</ows20:Country>
-          <ows20:ElectronicMailAddress>tomkralidis at gmail.com</ows20:ElectronicMailAddress>
-        </ows20:Address>
-        <ows20:OnlineResource xlink:type="simple" xlink:href="http://kralidis.ca/"/>
-        <ows20:HoursOfService>0800h - 1600h EST</ows20:HoursOfService>
-        <ows20:ContactInstructions>During hours of service.  Off on weekends.</ows20:ContactInstructions>
-      </ows20:ContactInfo>
-      <ows20:Role codeSpace="ISOTC211/19115">pointOfContact</ows20:Role>
-    </ows20:ServiceContact>
-  </ows20:ServiceProvider>
-  <ows20:OperationsMetadata>
-    <ows20:Operation name="GetCapabilities">
-      <ows20:DCP>
-        <ows20:HTTP>
-          <ows20:Get xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-          <ows20:Post xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-        </ows20:HTTP>
-      </ows20:DCP>
-      <ows20:Parameter name="acceptFormats">
-        <ows20:AllowedValues>
-          <ows20:Value>application/xml</ows20:Value>
-          <ows20:Value>text/xml</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="acceptVersions">
-        <ows20:AllowedValues>
-          <ows20:Value>2.0.2</ows20:Value>
-          <ows20:Value>3.0.0</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="sections">
-        <ows20:AllowedValues>
-          <ows20:Value>All</ows20:Value>
-          <ows20:Value>Filter_Capabilities</ows20:Value>
-          <ows20:Value>OperationsMetadata</ows20:Value>
-          <ows20:Value>ServiceIdentification</ows20:Value>
-          <ows20:Value>ServiceProvider</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-    </ows20:Operation>
-    <ows20:Operation name="GetDomain">
-      <ows20:DCP>
-        <ows20:HTTP>
-          <ows20:Get xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-          <ows20:Post xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-        </ows20:HTTP>
-      </ows20:DCP>
-      <ows20:Parameter name="ParameterName">
-        <ows20:AllowedValues>
-          <ows20:Value>GetCapabilities.acceptFormats</ows20:Value>
-          <ows20:Value>GetCapabilities.acceptVersions</ows20:Value>
-          <ows20:Value>GetCapabilities.sections</ows20:Value>
-          <ows20:Value>GetRecordById.ElementSetName</ows20:Value>
-          <ows20:Value>GetRecordById.outputFormat</ows20:Value>
-          <ows20:Value>GetRecordById.outputSchema</ows20:Value>
-          <ows20:Value>GetRecords.CONSTRAINTLANGUAGE</ows20:Value>
-          <ows20:Value>GetRecords.ElementSetName</ows20:Value>
-          <ows20:Value>GetRecords.outputFormat</ows20:Value>
-          <ows20:Value>GetRecords.outputSchema</ows20:Value>
-          <ows20:Value>GetRecords.typeNames</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-    </ows20:Operation>
-    <ows20:Operation name="GetRecords">
-      <ows20:DCP>
-        <ows20:HTTP>
-          <ows20:Get xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-          <ows20:Post xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-        </ows20:HTTP>
-      </ows20:DCP>
-      <ows20:Parameter name="CONSTRAINTLANGUAGE">
-        <ows20:AllowedValues>
-          <ows20:Value>CQL_TEXT</ows20:Value>
-          <ows20:Value>FILTER</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="ElementSetName">
-        <ows20:AllowedValues>
-          <ows20:Value>brief</ows20:Value>
-          <ows20:Value>full</ows20:Value>
-          <ows20:Value>summary</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="outputFormat">
-        <ows20:AllowedValues>
-          <ows20:Value>application/atom+xml</ows20:Value>
-          <ows20:Value>application/json</ows20:Value>
-          <ows20:Value>application/xml</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="outputSchema">
-        <ows20:AllowedValues>
-          <ows20:Value>http://gcmd.gsfc.nasa.gov/Aboutus/xml/dif/</ows20:Value>
-          <ows20:Value>http://www.interlis.ch/INTERLIS2.3</ows20:Value>
-          <ows20:Value>http://www.opengis.net/cat/csw/3.0</ows20:Value>
-          <ows20:Value>http://www.opengis.net/cat/csw/csdgm</ows20:Value>
-          <ows20:Value>http://www.w3.org/2005/Atom</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="typeNames">
-        <ows20:AllowedValues>
-          <ows20:Value>csw:Record</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Constraint name="MaxRecordDefault">
-        <ows20:AllowedValues>
-          <ows20:Value>10</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Constraint>
-      <ows20:Constraint name="OpenSearchDescriptionDocument">
-        <ows20:AllowedValues>
-          <ows20:Value>http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg?mode=opensearch&service=CSW&version=3.0.0&request=GetCapabilities</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Constraint>
-      <ows20:Constraint name="FederatedCatalogues">
-        <ows20:AllowedValues>
-          <ows20:Value>http://demo.pycsw.org/gisdata/csw</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Constraint>
-    </ows20:Operation>
-    <ows20:Operation name="GetRecordById">
-      <ows20:DCP>
-        <ows20:HTTP>
-          <ows20:Get xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-          <ows20:Post xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-        </ows20:HTTP>
-      </ows20:DCP>
-      <ows20:Parameter name="ElementSetName">
-        <ows20:AllowedValues>
-          <ows20:Value>brief</ows20:Value>
-          <ows20:Value>full</ows20:Value>
-          <ows20:Value>summary</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="outputFormat">
-        <ows20:AllowedValues>
-          <ows20:Value>application/atom+xml</ows20:Value>
-          <ows20:Value>application/json</ows20:Value>
-          <ows20:Value>application/xml</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="outputSchema">
-        <ows20:AllowedValues>
-          <ows20:Value>http://gcmd.gsfc.nasa.gov/Aboutus/xml/dif/</ows20:Value>
-          <ows20:Value>http://www.interlis.ch/INTERLIS2.3</ows20:Value>
-          <ows20:Value>http://www.opengis.net/cat/csw/3.0</ows20:Value>
-          <ows20:Value>http://www.opengis.net/cat/csw/csdgm</ows20:Value>
-          <ows20:Value>http://www.w3.org/2005/Atom</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-    </ows20:Operation>
-    <ows20:Operation name="GetRepositoryItem">
-      <ows20:DCP>
-        <ows20:HTTP>
-          <ows20:Get xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-        </ows20:HTTP>
-      </ows20:DCP>
-    </ows20:Operation>
-    <ows20:Parameter name="service">
-      <ows20:AllowedValues>
-        <ows20:Value>CSW</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Parameter>
-    <ows20:Parameter name="version">
-      <ows20:AllowedValues>
-        <ows20:Value>2.0.2</ows20:Value>
-        <ows20:Value>3.0.0</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Parameter>
-    <ows20:Constraint name="CoreQueryables">
-      <ows20:AllowedValues>
-        <ows20:Value>csw:AnyText</ows20:Value>
-        <ows20:Value>dc:contributor</ows20:Value>
-        <ows20:Value>dc:creator</ows20:Value>
-        <ows20:Value>dc:date</ows20:Value>
-        <ows20:Value>dc:format</ows20:Value>
-        <ows20:Value>dc:identifier</ows20:Value>
-        <ows20:Value>dc:language</ows20:Value>
-        <ows20:Value>dc:publisher</ows20:Value>
-        <ows20:Value>dc:relation</ows20:Value>
-        <ows20:Value>dc:rights</ows20:Value>
-        <ows20:Value>dc:source</ows20:Value>
-        <ows20:Value>dc:subject</ows20:Value>
-        <ows20:Value>dc:title</ows20:Value>
-        <ows20:Value>dc:type</ows20:Value>
-        <ows20:Value>dct:abstract</ows20:Value>
-        <ows20:Value>dct:alternative</ows20:Value>
-        <ows20:Value>dct:modified</ows20:Value>
-        <ows20:Value>dct:spatial</ows20:Value>
-        <ows20:Value>ows:BoundingBox</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="FederatedCatalogues">
-      <ows20:AllowedValues>
-        <ows20:Value>http://demo.pycsw.org/gisdata/csw</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="MaxRecordDefault">
-      <ows20:AllowedValues>
-        <ows20:Value>10</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="PostEncoding">
-      <ows20:AllowedValues>
-        <ows20:Value>SOAP</ows20:Value>
-        <ows20:Value>XML</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="XPathQueryables">
-      <ows20:AllowedValues>
-        <ows20:Value>allowed</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/CoreQueryables">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/CoreSortables">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/DefaultSortingAlgorithm">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Filter-CQL">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Filter-FES-KVP-Advanced">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Filter-FES-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetCapabilities-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetDomain-KVP">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetDomain-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetRecordById-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetRecords-Async-KVP">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetRecords-Async-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetRecords-Basic-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetRecords-Distributed-KVP">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetRecords-Distributed-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Harvest-Async-KVP">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Harvest-Async-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Harvest-Basic-KVP">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Harvest-Basic-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Harvest-Periodic-KVP">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Harvest-Periodic-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/OpenSearch">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/SupportedGMLVersions">
-      <ows20:AllowedValues>
-        <ows20:Value>http://www.opengis.net/gml</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Transaction">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-  </ows20:OperationsMetadata>
-  <ows20:Languages>
-    <ows20:Language>en</ows20:Language>
-  </ows20:Languages>
-  <fes20:Filter_Capabilities>
-    <fes20:Conformance>
-      <fes20:Constraint name="ImplementsQuery">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsAdHocQuery">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsFunctions">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsResourceld">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsMinStandardFilter">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsStandardFilter">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsMinSpatialFilter">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsSpatialFilter">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsMinTemporalFilter">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsTemporalFilter">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsVersionNav">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsSorting">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsExtendedOperators">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsMinimumXPath">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsSchemaElementFunc">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-    </fes20:Conformance>
-    <fes20:Id_Capabilities>
-      <fes20:ResourceIdentifier name="csw30:id"/>
-    </fes20:Id_Capabilities>
-    <fes20:Scalar_Capabilities>
-      <fes20:LogicalOperators/>
-      <fes20:ComparisonOperators>
-        <fes20:ComparisonOperator name="PropertyIsBetween"/>
-        <fes20:ComparisonOperator name="PropertyIsEqualTo"/>
-        <fes20:ComparisonOperator name="PropertyIsGreaterThan"/>
-        <fes20:ComparisonOperator name="PropertyIsGreaterThanOrEqualTo"/>
-        <fes20:ComparisonOperator name="PropertyIsLessThan"/>
-        <fes20:ComparisonOperator name="PropertyIsLessThanOrEqualTo"/>
-        <fes20:ComparisonOperator name="PropertyIsLike"/>
-        <fes20:ComparisonOperator name="PropertyIsNotEqualTo"/>
-        <fes20:ComparisonOperator name="PropertyIsNull"/>
-      </fes20:ComparisonOperators>
-    </fes20:Scalar_Capabilities>
-    <fes20:Spatial_Capabilities>
-      <fes20:GeometryOperands>
-        <fes20:GeometryOperand name="gml:Point"/>
-        <fes20:GeometryOperand name="gml:LineString"/>
-        <fes20:GeometryOperand name="gml:Polygon"/>
-        <fes20:GeometryOperand name="gml:Envelope"/>
-      </fes20:GeometryOperands>
-      <fes20:SpatialOperators>
-        <fes20:SpatialOperator name="BBOX"/>
-        <fes20:SpatialOperator name="Beyond"/>
-        <fes20:SpatialOperator name="Contains"/>
-        <fes20:SpatialOperator name="Crosses"/>
-        <fes20:SpatialOperator name="Disjoint"/>
-        <fes20:SpatialOperator name="DWithin"/>
-        <fes20:SpatialOperator name="Equals"/>
-        <fes20:SpatialOperator name="Intersects"/>
-        <fes20:SpatialOperator name="Overlaps"/>
-        <fes20:SpatialOperator name="Touches"/>
-        <fes20:SpatialOperator name="Within"/>
-      </fes20:SpatialOperators>
-    </fes20:Spatial_Capabilities>
-    <fes20:Functions>
-      <fes20:Function name="length">
-        <fes20:Returns>xs:string</fes20:Returns>
-      </fes20:Function>
-      <fes20:Function name="lower">
-        <fes20:Returns>xs:string</fes20:Returns>
-      </fes20:Function>
-      <fes20:Function name="ltrim">
-        <fes20:Returns>xs:string</fes20:Returns>
-      </fes20:Function>
-      <fes20:Function name="rtrim">
-        <fes20:Returns>xs:string</fes20:Returns>
-      </fes20:Function>
-      <fes20:Function name="trim">
-        <fes20:Returns>xs:string</fes20:Returns>
-      </fes20:Function>
-      <fes20:Function name="upper">
-        <fes20:Returns>xs:string</fes20:Returns>
-      </fes20:Function>
-    </fes20:Functions>
-  </fes20:Filter_Capabilities>
-</csw30:Capabilities>
diff --git a/tests/expected/suites_csw30_get_6e9cba43-5e27-415d-adbd-a92851c2c173.xml b/tests/expected/suites_csw30_get_6e9cba43-5e27-415d-adbd-a92851c2c173.xml
deleted file mode 100644
index c5cb70e..0000000
--- a/tests/expected/suites_csw30_get_6e9cba43-5e27-415d-adbd-a92851c2c173.xml
+++ /dev/null
@@ -1,493 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- PYCSW_VERSION -->
-<csw30:Capabilities xmlns:csw="http://www.opengis.net/cat/csw/2.0.2" xmlns:csw30="http://www.opengis.net/cat/csw/3.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dct="http://purl.org/dc/terms/" xmlns:fes20="http://www.opengis.net/fes/2.0" xmlns:gmd="http://www.isotc211.org/2005/gmd" xmlns:gml="http://www.opengis.net/gml" xmlns:ows="http://www.opengis.net/ows" xmlns:ows11="http://www.opengis.net/ows/1.1" xmlns:ows20="http://www.opengis.net/ows/2.0" xmlns:xlink="http://www.w3.org/199 [...]
-  <ows20:ServiceIdentification>
-    <ows20:Title>pycsw Geospatial Catalogue</ows20:Title>
-    <ows20:Abstract>pycsw is an OGC CSW server implementation written in Python</ows20:Abstract>
-    <ows20:Keywords>
-      <ows20:Keyword>catalogue</ows20:Keyword>
-      <ows20:Keyword>discovery</ows20:Keyword>
-      <ows20:Type codeSpace="ISOTC211/19115">theme</ows20:Type>
-    </ows20:Keywords>
-    <ows20:ServiceType codeSpace="OGC">CSW</ows20:ServiceType>
-    <ows20:ServiceTypeVersion>2.0.2</ows20:ServiceTypeVersion>
-    <ows20:ServiceTypeVersion>3.0.0</ows20:ServiceTypeVersion>
-    <ows20:Fees>None</ows20:Fees>
-    <ows20:AccessConstraints>None</ows20:AccessConstraints>
-  </ows20:ServiceIdentification>
-  <ows20:ServiceProvider>
-    <ows20:ProviderName>pycsw</ows20:ProviderName>
-    <ows20:ProviderSite xlink:type="simple" xlink:href="http://pycsw.org/"/>
-    <ows20:ServiceContact>
-      <ows20:IndividualName>Kralidis, Tom</ows20:IndividualName>
-      <ows20:PositionName>Senior Systems Scientist</ows20:PositionName>
-      <ows20:ContactInfo>
-        <ows20:Phone>
-          <ows20:Voice>+01-416-xxx-xxxx</ows20:Voice>
-          <ows20:Facsimile>+01-416-xxx-xxxx</ows20:Facsimile>
-        </ows20:Phone>
-        <ows20:Address>
-          <ows20:DeliveryPoint>TBA</ows20:DeliveryPoint>
-          <ows20:City>Toronto</ows20:City>
-          <ows20:AdministrativeArea>Ontario</ows20:AdministrativeArea>
-          <ows20:PostalCode>M9C 3Z9</ows20:PostalCode>
-          <ows20:Country>Canada</ows20:Country>
-          <ows20:ElectronicMailAddress>tomkralidis at gmail.com</ows20:ElectronicMailAddress>
-        </ows20:Address>
-        <ows20:OnlineResource xlink:type="simple" xlink:href="http://kralidis.ca/"/>
-        <ows20:HoursOfService>0800h - 1600h EST</ows20:HoursOfService>
-        <ows20:ContactInstructions>During hours of service.  Off on weekends.</ows20:ContactInstructions>
-      </ows20:ContactInfo>
-      <ows20:Role codeSpace="ISOTC211/19115">pointOfContact</ows20:Role>
-    </ows20:ServiceContact>
-  </ows20:ServiceProvider>
-  <ows20:OperationsMetadata>
-    <ows20:Operation name="GetCapabilities">
-      <ows20:DCP>
-        <ows20:HTTP>
-          <ows20:Get xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-          <ows20:Post xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-        </ows20:HTTP>
-      </ows20:DCP>
-      <ows20:Parameter name="acceptFormats">
-        <ows20:AllowedValues>
-          <ows20:Value>application/xml</ows20:Value>
-          <ows20:Value>text/xml</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="acceptVersions">
-        <ows20:AllowedValues>
-          <ows20:Value>2.0.2</ows20:Value>
-          <ows20:Value>3.0.0</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="sections">
-        <ows20:AllowedValues>
-          <ows20:Value>All</ows20:Value>
-          <ows20:Value>Filter_Capabilities</ows20:Value>
-          <ows20:Value>OperationsMetadata</ows20:Value>
-          <ows20:Value>ServiceIdentification</ows20:Value>
-          <ows20:Value>ServiceProvider</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-    </ows20:Operation>
-    <ows20:Operation name="GetDomain">
-      <ows20:DCP>
-        <ows20:HTTP>
-          <ows20:Get xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-          <ows20:Post xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-        </ows20:HTTP>
-      </ows20:DCP>
-      <ows20:Parameter name="ParameterName">
-        <ows20:AllowedValues>
-          <ows20:Value>GetCapabilities.acceptFormats</ows20:Value>
-          <ows20:Value>GetCapabilities.acceptVersions</ows20:Value>
-          <ows20:Value>GetCapabilities.sections</ows20:Value>
-          <ows20:Value>GetRecordById.ElementSetName</ows20:Value>
-          <ows20:Value>GetRecordById.outputFormat</ows20:Value>
-          <ows20:Value>GetRecordById.outputSchema</ows20:Value>
-          <ows20:Value>GetRecords.CONSTRAINTLANGUAGE</ows20:Value>
-          <ows20:Value>GetRecords.ElementSetName</ows20:Value>
-          <ows20:Value>GetRecords.outputFormat</ows20:Value>
-          <ows20:Value>GetRecords.outputSchema</ows20:Value>
-          <ows20:Value>GetRecords.typeNames</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-    </ows20:Operation>
-    <ows20:Operation name="GetRecords">
-      <ows20:DCP>
-        <ows20:HTTP>
-          <ows20:Get xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-          <ows20:Post xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-        </ows20:HTTP>
-      </ows20:DCP>
-      <ows20:Parameter name="CONSTRAINTLANGUAGE">
-        <ows20:AllowedValues>
-          <ows20:Value>CQL_TEXT</ows20:Value>
-          <ows20:Value>FILTER</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="ElementSetName">
-        <ows20:AllowedValues>
-          <ows20:Value>brief</ows20:Value>
-          <ows20:Value>full</ows20:Value>
-          <ows20:Value>summary</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="outputFormat">
-        <ows20:AllowedValues>
-          <ows20:Value>application/atom+xml</ows20:Value>
-          <ows20:Value>application/json</ows20:Value>
-          <ows20:Value>application/xml</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="outputSchema">
-        <ows20:AllowedValues>
-          <ows20:Value>http://gcmd.gsfc.nasa.gov/Aboutus/xml/dif/</ows20:Value>
-          <ows20:Value>http://www.interlis.ch/INTERLIS2.3</ows20:Value>
-          <ows20:Value>http://www.opengis.net/cat/csw/3.0</ows20:Value>
-          <ows20:Value>http://www.opengis.net/cat/csw/csdgm</ows20:Value>
-          <ows20:Value>http://www.w3.org/2005/Atom</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="typeNames">
-        <ows20:AllowedValues>
-          <ows20:Value>csw:Record</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Constraint name="MaxRecordDefault">
-        <ows20:AllowedValues>
-          <ows20:Value>10</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Constraint>
-      <ows20:Constraint name="OpenSearchDescriptionDocument">
-        <ows20:AllowedValues>
-          <ows20:Value>http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg?mode=opensearch&service=CSW&version=3.0.0&request=GetCapabilities</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Constraint>
-      <ows20:Constraint name="FederatedCatalogues">
-        <ows20:AllowedValues>
-          <ows20:Value>http://demo.pycsw.org/gisdata/csw</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Constraint>
-    </ows20:Operation>
-    <ows20:Operation name="GetRecordById">
-      <ows20:DCP>
-        <ows20:HTTP>
-          <ows20:Get xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-          <ows20:Post xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-        </ows20:HTTP>
-      </ows20:DCP>
-      <ows20:Parameter name="ElementSetName">
-        <ows20:AllowedValues>
-          <ows20:Value>brief</ows20:Value>
-          <ows20:Value>full</ows20:Value>
-          <ows20:Value>summary</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="outputFormat">
-        <ows20:AllowedValues>
-          <ows20:Value>application/atom+xml</ows20:Value>
-          <ows20:Value>application/json</ows20:Value>
-          <ows20:Value>application/xml</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="outputSchema">
-        <ows20:AllowedValues>
-          <ows20:Value>http://gcmd.gsfc.nasa.gov/Aboutus/xml/dif/</ows20:Value>
-          <ows20:Value>http://www.interlis.ch/INTERLIS2.3</ows20:Value>
-          <ows20:Value>http://www.opengis.net/cat/csw/3.0</ows20:Value>
-          <ows20:Value>http://www.opengis.net/cat/csw/csdgm</ows20:Value>
-          <ows20:Value>http://www.w3.org/2005/Atom</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-    </ows20:Operation>
-    <ows20:Operation name="GetRepositoryItem">
-      <ows20:DCP>
-        <ows20:HTTP>
-          <ows20:Get xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-        </ows20:HTTP>
-      </ows20:DCP>
-    </ows20:Operation>
-    <ows20:Parameter name="service">
-      <ows20:AllowedValues>
-        <ows20:Value>CSW</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Parameter>
-    <ows20:Parameter name="version">
-      <ows20:AllowedValues>
-        <ows20:Value>2.0.2</ows20:Value>
-        <ows20:Value>3.0.0</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Parameter>
-    <ows20:Constraint name="CoreQueryables">
-      <ows20:AllowedValues>
-        <ows20:Value>csw:AnyText</ows20:Value>
-        <ows20:Value>dc:contributor</ows20:Value>
-        <ows20:Value>dc:creator</ows20:Value>
-        <ows20:Value>dc:date</ows20:Value>
-        <ows20:Value>dc:format</ows20:Value>
-        <ows20:Value>dc:identifier</ows20:Value>
-        <ows20:Value>dc:language</ows20:Value>
-        <ows20:Value>dc:publisher</ows20:Value>
-        <ows20:Value>dc:relation</ows20:Value>
-        <ows20:Value>dc:rights</ows20:Value>
-        <ows20:Value>dc:source</ows20:Value>
-        <ows20:Value>dc:subject</ows20:Value>
-        <ows20:Value>dc:title</ows20:Value>
-        <ows20:Value>dc:type</ows20:Value>
-        <ows20:Value>dct:abstract</ows20:Value>
-        <ows20:Value>dct:alternative</ows20:Value>
-        <ows20:Value>dct:modified</ows20:Value>
-        <ows20:Value>dct:spatial</ows20:Value>
-        <ows20:Value>ows:BoundingBox</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="FederatedCatalogues">
-      <ows20:AllowedValues>
-        <ows20:Value>http://demo.pycsw.org/gisdata/csw</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="MaxRecordDefault">
-      <ows20:AllowedValues>
-        <ows20:Value>10</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="PostEncoding">
-      <ows20:AllowedValues>
-        <ows20:Value>SOAP</ows20:Value>
-        <ows20:Value>XML</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="XPathQueryables">
-      <ows20:AllowedValues>
-        <ows20:Value>allowed</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/CoreQueryables">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/CoreSortables">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/DefaultSortingAlgorithm">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Filter-CQL">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Filter-FES-KVP-Advanced">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Filter-FES-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetCapabilities-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetDomain-KVP">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetDomain-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetRecordById-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetRecords-Async-KVP">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetRecords-Async-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetRecords-Basic-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetRecords-Distributed-KVP">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetRecords-Distributed-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Harvest-Async-KVP">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Harvest-Async-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Harvest-Basic-KVP">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Harvest-Basic-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Harvest-Periodic-KVP">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Harvest-Periodic-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/OpenSearch">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/SupportedGMLVersions">
-      <ows20:AllowedValues>
-        <ows20:Value>http://www.opengis.net/gml</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Transaction">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-  </ows20:OperationsMetadata>
-  <ows20:Languages>
-    <ows20:Language>en</ows20:Language>
-  </ows20:Languages>
-  <fes20:Filter_Capabilities>
-    <fes20:Conformance>
-      <fes20:Constraint name="ImplementsQuery">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsAdHocQuery">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsFunctions">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsResourceld">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsMinStandardFilter">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsStandardFilter">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsMinSpatialFilter">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsSpatialFilter">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsMinTemporalFilter">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsTemporalFilter">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsVersionNav">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsSorting">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsExtendedOperators">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsMinimumXPath">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsSchemaElementFunc">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-    </fes20:Conformance>
-    <fes20:Id_Capabilities>
-      <fes20:ResourceIdentifier name="csw30:id"/>
-    </fes20:Id_Capabilities>
-    <fes20:Scalar_Capabilities>
-      <fes20:LogicalOperators/>
-      <fes20:ComparisonOperators>
-        <fes20:ComparisonOperator name="PropertyIsBetween"/>
-        <fes20:ComparisonOperator name="PropertyIsEqualTo"/>
-        <fes20:ComparisonOperator name="PropertyIsGreaterThan"/>
-        <fes20:ComparisonOperator name="PropertyIsGreaterThanOrEqualTo"/>
-        <fes20:ComparisonOperator name="PropertyIsLessThan"/>
-        <fes20:ComparisonOperator name="PropertyIsLessThanOrEqualTo"/>
-        <fes20:ComparisonOperator name="PropertyIsLike"/>
-        <fes20:ComparisonOperator name="PropertyIsNotEqualTo"/>
-        <fes20:ComparisonOperator name="PropertyIsNull"/>
-      </fes20:ComparisonOperators>
-    </fes20:Scalar_Capabilities>
-    <fes20:Spatial_Capabilities>
-      <fes20:GeometryOperands>
-        <fes20:GeometryOperand name="gml:Point"/>
-        <fes20:GeometryOperand name="gml:LineString"/>
-        <fes20:GeometryOperand name="gml:Polygon"/>
-        <fes20:GeometryOperand name="gml:Envelope"/>
-      </fes20:GeometryOperands>
-      <fes20:SpatialOperators>
-        <fes20:SpatialOperator name="BBOX"/>
-        <fes20:SpatialOperator name="Beyond"/>
-        <fes20:SpatialOperator name="Contains"/>
-        <fes20:SpatialOperator name="Crosses"/>
-        <fes20:SpatialOperator name="Disjoint"/>
-        <fes20:SpatialOperator name="DWithin"/>
-        <fes20:SpatialOperator name="Equals"/>
-        <fes20:SpatialOperator name="Intersects"/>
-        <fes20:SpatialOperator name="Overlaps"/>
-        <fes20:SpatialOperator name="Touches"/>
-        <fes20:SpatialOperator name="Within"/>
-      </fes20:SpatialOperators>
-    </fes20:Spatial_Capabilities>
-    <fes20:Functions>
-      <fes20:Function name="length">
-        <fes20:Returns>xs:string</fes20:Returns>
-      </fes20:Function>
-      <fes20:Function name="lower">
-        <fes20:Returns>xs:string</fes20:Returns>
-      </fes20:Function>
-      <fes20:Function name="ltrim">
-        <fes20:Returns>xs:string</fes20:Returns>
-      </fes20:Function>
-      <fes20:Function name="rtrim">
-        <fes20:Returns>xs:string</fes20:Returns>
-      </fes20:Function>
-      <fes20:Function name="trim">
-        <fes20:Returns>xs:string</fes20:Returns>
-      </fes20:Function>
-      <fes20:Function name="upper">
-        <fes20:Returns>xs:string</fes20:Returns>
-      </fes20:Function>
-    </fes20:Functions>
-  </fes20:Filter_Capabilities>
-</csw30:Capabilities>
diff --git a/tests/expected/suites_csw30_get_7e82446a-b5dc-43fe-9a73-4cc1f2f2f0bf.xml b/tests/expected/suites_csw30_get_7e82446a-b5dc-43fe-9a73-4cc1f2f2f0bf.xml
deleted file mode 100644
index c5cb70e..0000000
--- a/tests/expected/suites_csw30_get_7e82446a-b5dc-43fe-9a73-4cc1f2f2f0bf.xml
+++ /dev/null
@@ -1,493 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- PYCSW_VERSION -->
-<csw30:Capabilities xmlns:csw="http://www.opengis.net/cat/csw/2.0.2" xmlns:csw30="http://www.opengis.net/cat/csw/3.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dct="http://purl.org/dc/terms/" xmlns:fes20="http://www.opengis.net/fes/2.0" xmlns:gmd="http://www.isotc211.org/2005/gmd" xmlns:gml="http://www.opengis.net/gml" xmlns:ows="http://www.opengis.net/ows" xmlns:ows11="http://www.opengis.net/ows/1.1" xmlns:ows20="http://www.opengis.net/ows/2.0" xmlns:xlink="http://www.w3.org/199 [...]
-  <ows20:ServiceIdentification>
-    <ows20:Title>pycsw Geospatial Catalogue</ows20:Title>
-    <ows20:Abstract>pycsw is an OGC CSW server implementation written in Python</ows20:Abstract>
-    <ows20:Keywords>
-      <ows20:Keyword>catalogue</ows20:Keyword>
-      <ows20:Keyword>discovery</ows20:Keyword>
-      <ows20:Type codeSpace="ISOTC211/19115">theme</ows20:Type>
-    </ows20:Keywords>
-    <ows20:ServiceType codeSpace="OGC">CSW</ows20:ServiceType>
-    <ows20:ServiceTypeVersion>2.0.2</ows20:ServiceTypeVersion>
-    <ows20:ServiceTypeVersion>3.0.0</ows20:ServiceTypeVersion>
-    <ows20:Fees>None</ows20:Fees>
-    <ows20:AccessConstraints>None</ows20:AccessConstraints>
-  </ows20:ServiceIdentification>
-  <ows20:ServiceProvider>
-    <ows20:ProviderName>pycsw</ows20:ProviderName>
-    <ows20:ProviderSite xlink:type="simple" xlink:href="http://pycsw.org/"/>
-    <ows20:ServiceContact>
-      <ows20:IndividualName>Kralidis, Tom</ows20:IndividualName>
-      <ows20:PositionName>Senior Systems Scientist</ows20:PositionName>
-      <ows20:ContactInfo>
-        <ows20:Phone>
-          <ows20:Voice>+01-416-xxx-xxxx</ows20:Voice>
-          <ows20:Facsimile>+01-416-xxx-xxxx</ows20:Facsimile>
-        </ows20:Phone>
-        <ows20:Address>
-          <ows20:DeliveryPoint>TBA</ows20:DeliveryPoint>
-          <ows20:City>Toronto</ows20:City>
-          <ows20:AdministrativeArea>Ontario</ows20:AdministrativeArea>
-          <ows20:PostalCode>M9C 3Z9</ows20:PostalCode>
-          <ows20:Country>Canada</ows20:Country>
-          <ows20:ElectronicMailAddress>tomkralidis at gmail.com</ows20:ElectronicMailAddress>
-        </ows20:Address>
-        <ows20:OnlineResource xlink:type="simple" xlink:href="http://kralidis.ca/"/>
-        <ows20:HoursOfService>0800h - 1600h EST</ows20:HoursOfService>
-        <ows20:ContactInstructions>During hours of service.  Off on weekends.</ows20:ContactInstructions>
-      </ows20:ContactInfo>
-      <ows20:Role codeSpace="ISOTC211/19115">pointOfContact</ows20:Role>
-    </ows20:ServiceContact>
-  </ows20:ServiceProvider>
-  <ows20:OperationsMetadata>
-    <ows20:Operation name="GetCapabilities">
-      <ows20:DCP>
-        <ows20:HTTP>
-          <ows20:Get xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-          <ows20:Post xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-        </ows20:HTTP>
-      </ows20:DCP>
-      <ows20:Parameter name="acceptFormats">
-        <ows20:AllowedValues>
-          <ows20:Value>application/xml</ows20:Value>
-          <ows20:Value>text/xml</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="acceptVersions">
-        <ows20:AllowedValues>
-          <ows20:Value>2.0.2</ows20:Value>
-          <ows20:Value>3.0.0</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="sections">
-        <ows20:AllowedValues>
-          <ows20:Value>All</ows20:Value>
-          <ows20:Value>Filter_Capabilities</ows20:Value>
-          <ows20:Value>OperationsMetadata</ows20:Value>
-          <ows20:Value>ServiceIdentification</ows20:Value>
-          <ows20:Value>ServiceProvider</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-    </ows20:Operation>
-    <ows20:Operation name="GetDomain">
-      <ows20:DCP>
-        <ows20:HTTP>
-          <ows20:Get xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-          <ows20:Post xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-        </ows20:HTTP>
-      </ows20:DCP>
-      <ows20:Parameter name="ParameterName">
-        <ows20:AllowedValues>
-          <ows20:Value>GetCapabilities.acceptFormats</ows20:Value>
-          <ows20:Value>GetCapabilities.acceptVersions</ows20:Value>
-          <ows20:Value>GetCapabilities.sections</ows20:Value>
-          <ows20:Value>GetRecordById.ElementSetName</ows20:Value>
-          <ows20:Value>GetRecordById.outputFormat</ows20:Value>
-          <ows20:Value>GetRecordById.outputSchema</ows20:Value>
-          <ows20:Value>GetRecords.CONSTRAINTLANGUAGE</ows20:Value>
-          <ows20:Value>GetRecords.ElementSetName</ows20:Value>
-          <ows20:Value>GetRecords.outputFormat</ows20:Value>
-          <ows20:Value>GetRecords.outputSchema</ows20:Value>
-          <ows20:Value>GetRecords.typeNames</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-    </ows20:Operation>
-    <ows20:Operation name="GetRecords">
-      <ows20:DCP>
-        <ows20:HTTP>
-          <ows20:Get xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-          <ows20:Post xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-        </ows20:HTTP>
-      </ows20:DCP>
-      <ows20:Parameter name="CONSTRAINTLANGUAGE">
-        <ows20:AllowedValues>
-          <ows20:Value>CQL_TEXT</ows20:Value>
-          <ows20:Value>FILTER</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="ElementSetName">
-        <ows20:AllowedValues>
-          <ows20:Value>brief</ows20:Value>
-          <ows20:Value>full</ows20:Value>
-          <ows20:Value>summary</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="outputFormat">
-        <ows20:AllowedValues>
-          <ows20:Value>application/atom+xml</ows20:Value>
-          <ows20:Value>application/json</ows20:Value>
-          <ows20:Value>application/xml</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="outputSchema">
-        <ows20:AllowedValues>
-          <ows20:Value>http://gcmd.gsfc.nasa.gov/Aboutus/xml/dif/</ows20:Value>
-          <ows20:Value>http://www.interlis.ch/INTERLIS2.3</ows20:Value>
-          <ows20:Value>http://www.opengis.net/cat/csw/3.0</ows20:Value>
-          <ows20:Value>http://www.opengis.net/cat/csw/csdgm</ows20:Value>
-          <ows20:Value>http://www.w3.org/2005/Atom</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="typeNames">
-        <ows20:AllowedValues>
-          <ows20:Value>csw:Record</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Constraint name="MaxRecordDefault">
-        <ows20:AllowedValues>
-          <ows20:Value>10</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Constraint>
-      <ows20:Constraint name="OpenSearchDescriptionDocument">
-        <ows20:AllowedValues>
-          <ows20:Value>http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg?mode=opensearch&service=CSW&version=3.0.0&request=GetCapabilities</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Constraint>
-      <ows20:Constraint name="FederatedCatalogues">
-        <ows20:AllowedValues>
-          <ows20:Value>http://demo.pycsw.org/gisdata/csw</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Constraint>
-    </ows20:Operation>
-    <ows20:Operation name="GetRecordById">
-      <ows20:DCP>
-        <ows20:HTTP>
-          <ows20:Get xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-          <ows20:Post xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-        </ows20:HTTP>
-      </ows20:DCP>
-      <ows20:Parameter name="ElementSetName">
-        <ows20:AllowedValues>
-          <ows20:Value>brief</ows20:Value>
-          <ows20:Value>full</ows20:Value>
-          <ows20:Value>summary</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="outputFormat">
-        <ows20:AllowedValues>
-          <ows20:Value>application/atom+xml</ows20:Value>
-          <ows20:Value>application/json</ows20:Value>
-          <ows20:Value>application/xml</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="outputSchema">
-        <ows20:AllowedValues>
-          <ows20:Value>http://gcmd.gsfc.nasa.gov/Aboutus/xml/dif/</ows20:Value>
-          <ows20:Value>http://www.interlis.ch/INTERLIS2.3</ows20:Value>
-          <ows20:Value>http://www.opengis.net/cat/csw/3.0</ows20:Value>
-          <ows20:Value>http://www.opengis.net/cat/csw/csdgm</ows20:Value>
-          <ows20:Value>http://www.w3.org/2005/Atom</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-    </ows20:Operation>
-    <ows20:Operation name="GetRepositoryItem">
-      <ows20:DCP>
-        <ows20:HTTP>
-          <ows20:Get xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-        </ows20:HTTP>
-      </ows20:DCP>
-    </ows20:Operation>
-    <ows20:Parameter name="service">
-      <ows20:AllowedValues>
-        <ows20:Value>CSW</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Parameter>
-    <ows20:Parameter name="version">
-      <ows20:AllowedValues>
-        <ows20:Value>2.0.2</ows20:Value>
-        <ows20:Value>3.0.0</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Parameter>
-    <ows20:Constraint name="CoreQueryables">
-      <ows20:AllowedValues>
-        <ows20:Value>csw:AnyText</ows20:Value>
-        <ows20:Value>dc:contributor</ows20:Value>
-        <ows20:Value>dc:creator</ows20:Value>
-        <ows20:Value>dc:date</ows20:Value>
-        <ows20:Value>dc:format</ows20:Value>
-        <ows20:Value>dc:identifier</ows20:Value>
-        <ows20:Value>dc:language</ows20:Value>
-        <ows20:Value>dc:publisher</ows20:Value>
-        <ows20:Value>dc:relation</ows20:Value>
-        <ows20:Value>dc:rights</ows20:Value>
-        <ows20:Value>dc:source</ows20:Value>
-        <ows20:Value>dc:subject</ows20:Value>
-        <ows20:Value>dc:title</ows20:Value>
-        <ows20:Value>dc:type</ows20:Value>
-        <ows20:Value>dct:abstract</ows20:Value>
-        <ows20:Value>dct:alternative</ows20:Value>
-        <ows20:Value>dct:modified</ows20:Value>
-        <ows20:Value>dct:spatial</ows20:Value>
-        <ows20:Value>ows:BoundingBox</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="FederatedCatalogues">
-      <ows20:AllowedValues>
-        <ows20:Value>http://demo.pycsw.org/gisdata/csw</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="MaxRecordDefault">
-      <ows20:AllowedValues>
-        <ows20:Value>10</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="PostEncoding">
-      <ows20:AllowedValues>
-        <ows20:Value>SOAP</ows20:Value>
-        <ows20:Value>XML</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="XPathQueryables">
-      <ows20:AllowedValues>
-        <ows20:Value>allowed</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/CoreQueryables">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/CoreSortables">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/DefaultSortingAlgorithm">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Filter-CQL">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Filter-FES-KVP-Advanced">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Filter-FES-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetCapabilities-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetDomain-KVP">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetDomain-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetRecordById-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetRecords-Async-KVP">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetRecords-Async-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetRecords-Basic-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetRecords-Distributed-KVP">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetRecords-Distributed-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Harvest-Async-KVP">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Harvest-Async-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Harvest-Basic-KVP">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Harvest-Basic-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Harvest-Periodic-KVP">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Harvest-Periodic-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/OpenSearch">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/SupportedGMLVersions">
-      <ows20:AllowedValues>
-        <ows20:Value>http://www.opengis.net/gml</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Transaction">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-  </ows20:OperationsMetadata>
-  <ows20:Languages>
-    <ows20:Language>en</ows20:Language>
-  </ows20:Languages>
-  <fes20:Filter_Capabilities>
-    <fes20:Conformance>
-      <fes20:Constraint name="ImplementsQuery">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsAdHocQuery">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsFunctions">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsResourceld">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsMinStandardFilter">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsStandardFilter">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsMinSpatialFilter">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsSpatialFilter">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsMinTemporalFilter">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsTemporalFilter">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsVersionNav">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsSorting">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsExtendedOperators">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsMinimumXPath">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsSchemaElementFunc">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-    </fes20:Conformance>
-    <fes20:Id_Capabilities>
-      <fes20:ResourceIdentifier name="csw30:id"/>
-    </fes20:Id_Capabilities>
-    <fes20:Scalar_Capabilities>
-      <fes20:LogicalOperators/>
-      <fes20:ComparisonOperators>
-        <fes20:ComparisonOperator name="PropertyIsBetween"/>
-        <fes20:ComparisonOperator name="PropertyIsEqualTo"/>
-        <fes20:ComparisonOperator name="PropertyIsGreaterThan"/>
-        <fes20:ComparisonOperator name="PropertyIsGreaterThanOrEqualTo"/>
-        <fes20:ComparisonOperator name="PropertyIsLessThan"/>
-        <fes20:ComparisonOperator name="PropertyIsLessThanOrEqualTo"/>
-        <fes20:ComparisonOperator name="PropertyIsLike"/>
-        <fes20:ComparisonOperator name="PropertyIsNotEqualTo"/>
-        <fes20:ComparisonOperator name="PropertyIsNull"/>
-      </fes20:ComparisonOperators>
-    </fes20:Scalar_Capabilities>
-    <fes20:Spatial_Capabilities>
-      <fes20:GeometryOperands>
-        <fes20:GeometryOperand name="gml:Point"/>
-        <fes20:GeometryOperand name="gml:LineString"/>
-        <fes20:GeometryOperand name="gml:Polygon"/>
-        <fes20:GeometryOperand name="gml:Envelope"/>
-      </fes20:GeometryOperands>
-      <fes20:SpatialOperators>
-        <fes20:SpatialOperator name="BBOX"/>
-        <fes20:SpatialOperator name="Beyond"/>
-        <fes20:SpatialOperator name="Contains"/>
-        <fes20:SpatialOperator name="Crosses"/>
-        <fes20:SpatialOperator name="Disjoint"/>
-        <fes20:SpatialOperator name="DWithin"/>
-        <fes20:SpatialOperator name="Equals"/>
-        <fes20:SpatialOperator name="Intersects"/>
-        <fes20:SpatialOperator name="Overlaps"/>
-        <fes20:SpatialOperator name="Touches"/>
-        <fes20:SpatialOperator name="Within"/>
-      </fes20:SpatialOperators>
-    </fes20:Spatial_Capabilities>
-    <fes20:Functions>
-      <fes20:Function name="length">
-        <fes20:Returns>xs:string</fes20:Returns>
-      </fes20:Function>
-      <fes20:Function name="lower">
-        <fes20:Returns>xs:string</fes20:Returns>
-      </fes20:Function>
-      <fes20:Function name="ltrim">
-        <fes20:Returns>xs:string</fes20:Returns>
-      </fes20:Function>
-      <fes20:Function name="rtrim">
-        <fes20:Returns>xs:string</fes20:Returns>
-      </fes20:Function>
-      <fes20:Function name="trim">
-        <fes20:Returns>xs:string</fes20:Returns>
-      </fes20:Function>
-      <fes20:Function name="upper">
-        <fes20:Returns>xs:string</fes20:Returns>
-      </fes20:Function>
-    </fes20:Functions>
-  </fes20:Filter_Capabilities>
-</csw30:Capabilities>
diff --git a/tests/expected/suites_csw30_get_8025978e-1a35-4d70-80c2-e8329e0c7864.xml b/tests/expected/suites_csw30_get_8025978e-1a35-4d70-80c2-e8329e0c7864.xml
deleted file mode 100644
index c5cb70e..0000000
--- a/tests/expected/suites_csw30_get_8025978e-1a35-4d70-80c2-e8329e0c7864.xml
+++ /dev/null
@@ -1,493 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- PYCSW_VERSION -->
-<csw30:Capabilities xmlns:csw="http://www.opengis.net/cat/csw/2.0.2" xmlns:csw30="http://www.opengis.net/cat/csw/3.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dct="http://purl.org/dc/terms/" xmlns:fes20="http://www.opengis.net/fes/2.0" xmlns:gmd="http://www.isotc211.org/2005/gmd" xmlns:gml="http://www.opengis.net/gml" xmlns:ows="http://www.opengis.net/ows" xmlns:ows11="http://www.opengis.net/ows/1.1" xmlns:ows20="http://www.opengis.net/ows/2.0" xmlns:xlink="http://www.w3.org/199 [...]
-  <ows20:ServiceIdentification>
-    <ows20:Title>pycsw Geospatial Catalogue</ows20:Title>
-    <ows20:Abstract>pycsw is an OGC CSW server implementation written in Python</ows20:Abstract>
-    <ows20:Keywords>
-      <ows20:Keyword>catalogue</ows20:Keyword>
-      <ows20:Keyword>discovery</ows20:Keyword>
-      <ows20:Type codeSpace="ISOTC211/19115">theme</ows20:Type>
-    </ows20:Keywords>
-    <ows20:ServiceType codeSpace="OGC">CSW</ows20:ServiceType>
-    <ows20:ServiceTypeVersion>2.0.2</ows20:ServiceTypeVersion>
-    <ows20:ServiceTypeVersion>3.0.0</ows20:ServiceTypeVersion>
-    <ows20:Fees>None</ows20:Fees>
-    <ows20:AccessConstraints>None</ows20:AccessConstraints>
-  </ows20:ServiceIdentification>
-  <ows20:ServiceProvider>
-    <ows20:ProviderName>pycsw</ows20:ProviderName>
-    <ows20:ProviderSite xlink:type="simple" xlink:href="http://pycsw.org/"/>
-    <ows20:ServiceContact>
-      <ows20:IndividualName>Kralidis, Tom</ows20:IndividualName>
-      <ows20:PositionName>Senior Systems Scientist</ows20:PositionName>
-      <ows20:ContactInfo>
-        <ows20:Phone>
-          <ows20:Voice>+01-416-xxx-xxxx</ows20:Voice>
-          <ows20:Facsimile>+01-416-xxx-xxxx</ows20:Facsimile>
-        </ows20:Phone>
-        <ows20:Address>
-          <ows20:DeliveryPoint>TBA</ows20:DeliveryPoint>
-          <ows20:City>Toronto</ows20:City>
-          <ows20:AdministrativeArea>Ontario</ows20:AdministrativeArea>
-          <ows20:PostalCode>M9C 3Z9</ows20:PostalCode>
-          <ows20:Country>Canada</ows20:Country>
-          <ows20:ElectronicMailAddress>tomkralidis at gmail.com</ows20:ElectronicMailAddress>
-        </ows20:Address>
-        <ows20:OnlineResource xlink:type="simple" xlink:href="http://kralidis.ca/"/>
-        <ows20:HoursOfService>0800h - 1600h EST</ows20:HoursOfService>
-        <ows20:ContactInstructions>During hours of service.  Off on weekends.</ows20:ContactInstructions>
-      </ows20:ContactInfo>
-      <ows20:Role codeSpace="ISOTC211/19115">pointOfContact</ows20:Role>
-    </ows20:ServiceContact>
-  </ows20:ServiceProvider>
-  <ows20:OperationsMetadata>
-    <ows20:Operation name="GetCapabilities">
-      <ows20:DCP>
-        <ows20:HTTP>
-          <ows20:Get xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-          <ows20:Post xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-        </ows20:HTTP>
-      </ows20:DCP>
-      <ows20:Parameter name="acceptFormats">
-        <ows20:AllowedValues>
-          <ows20:Value>application/xml</ows20:Value>
-          <ows20:Value>text/xml</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="acceptVersions">
-        <ows20:AllowedValues>
-          <ows20:Value>2.0.2</ows20:Value>
-          <ows20:Value>3.0.0</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="sections">
-        <ows20:AllowedValues>
-          <ows20:Value>All</ows20:Value>
-          <ows20:Value>Filter_Capabilities</ows20:Value>
-          <ows20:Value>OperationsMetadata</ows20:Value>
-          <ows20:Value>ServiceIdentification</ows20:Value>
-          <ows20:Value>ServiceProvider</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-    </ows20:Operation>
-    <ows20:Operation name="GetDomain">
-      <ows20:DCP>
-        <ows20:HTTP>
-          <ows20:Get xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-          <ows20:Post xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-        </ows20:HTTP>
-      </ows20:DCP>
-      <ows20:Parameter name="ParameterName">
-        <ows20:AllowedValues>
-          <ows20:Value>GetCapabilities.acceptFormats</ows20:Value>
-          <ows20:Value>GetCapabilities.acceptVersions</ows20:Value>
-          <ows20:Value>GetCapabilities.sections</ows20:Value>
-          <ows20:Value>GetRecordById.ElementSetName</ows20:Value>
-          <ows20:Value>GetRecordById.outputFormat</ows20:Value>
-          <ows20:Value>GetRecordById.outputSchema</ows20:Value>
-          <ows20:Value>GetRecords.CONSTRAINTLANGUAGE</ows20:Value>
-          <ows20:Value>GetRecords.ElementSetName</ows20:Value>
-          <ows20:Value>GetRecords.outputFormat</ows20:Value>
-          <ows20:Value>GetRecords.outputSchema</ows20:Value>
-          <ows20:Value>GetRecords.typeNames</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-    </ows20:Operation>
-    <ows20:Operation name="GetRecords">
-      <ows20:DCP>
-        <ows20:HTTP>
-          <ows20:Get xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-          <ows20:Post xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-        </ows20:HTTP>
-      </ows20:DCP>
-      <ows20:Parameter name="CONSTRAINTLANGUAGE">
-        <ows20:AllowedValues>
-          <ows20:Value>CQL_TEXT</ows20:Value>
-          <ows20:Value>FILTER</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="ElementSetName">
-        <ows20:AllowedValues>
-          <ows20:Value>brief</ows20:Value>
-          <ows20:Value>full</ows20:Value>
-          <ows20:Value>summary</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="outputFormat">
-        <ows20:AllowedValues>
-          <ows20:Value>application/atom+xml</ows20:Value>
-          <ows20:Value>application/json</ows20:Value>
-          <ows20:Value>application/xml</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="outputSchema">
-        <ows20:AllowedValues>
-          <ows20:Value>http://gcmd.gsfc.nasa.gov/Aboutus/xml/dif/</ows20:Value>
-          <ows20:Value>http://www.interlis.ch/INTERLIS2.3</ows20:Value>
-          <ows20:Value>http://www.opengis.net/cat/csw/3.0</ows20:Value>
-          <ows20:Value>http://www.opengis.net/cat/csw/csdgm</ows20:Value>
-          <ows20:Value>http://www.w3.org/2005/Atom</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="typeNames">
-        <ows20:AllowedValues>
-          <ows20:Value>csw:Record</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Constraint name="MaxRecordDefault">
-        <ows20:AllowedValues>
-          <ows20:Value>10</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Constraint>
-      <ows20:Constraint name="OpenSearchDescriptionDocument">
-        <ows20:AllowedValues>
-          <ows20:Value>http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg?mode=opensearch&service=CSW&version=3.0.0&request=GetCapabilities</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Constraint>
-      <ows20:Constraint name="FederatedCatalogues">
-        <ows20:AllowedValues>
-          <ows20:Value>http://demo.pycsw.org/gisdata/csw</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Constraint>
-    </ows20:Operation>
-    <ows20:Operation name="GetRecordById">
-      <ows20:DCP>
-        <ows20:HTTP>
-          <ows20:Get xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-          <ows20:Post xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-        </ows20:HTTP>
-      </ows20:DCP>
-      <ows20:Parameter name="ElementSetName">
-        <ows20:AllowedValues>
-          <ows20:Value>brief</ows20:Value>
-          <ows20:Value>full</ows20:Value>
-          <ows20:Value>summary</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="outputFormat">
-        <ows20:AllowedValues>
-          <ows20:Value>application/atom+xml</ows20:Value>
-          <ows20:Value>application/json</ows20:Value>
-          <ows20:Value>application/xml</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="outputSchema">
-        <ows20:AllowedValues>
-          <ows20:Value>http://gcmd.gsfc.nasa.gov/Aboutus/xml/dif/</ows20:Value>
-          <ows20:Value>http://www.interlis.ch/INTERLIS2.3</ows20:Value>
-          <ows20:Value>http://www.opengis.net/cat/csw/3.0</ows20:Value>
-          <ows20:Value>http://www.opengis.net/cat/csw/csdgm</ows20:Value>
-          <ows20:Value>http://www.w3.org/2005/Atom</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-    </ows20:Operation>
-    <ows20:Operation name="GetRepositoryItem">
-      <ows20:DCP>
-        <ows20:HTTP>
-          <ows20:Get xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-        </ows20:HTTP>
-      </ows20:DCP>
-    </ows20:Operation>
-    <ows20:Parameter name="service">
-      <ows20:AllowedValues>
-        <ows20:Value>CSW</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Parameter>
-    <ows20:Parameter name="version">
-      <ows20:AllowedValues>
-        <ows20:Value>2.0.2</ows20:Value>
-        <ows20:Value>3.0.0</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Parameter>
-    <ows20:Constraint name="CoreQueryables">
-      <ows20:AllowedValues>
-        <ows20:Value>csw:AnyText</ows20:Value>
-        <ows20:Value>dc:contributor</ows20:Value>
-        <ows20:Value>dc:creator</ows20:Value>
-        <ows20:Value>dc:date</ows20:Value>
-        <ows20:Value>dc:format</ows20:Value>
-        <ows20:Value>dc:identifier</ows20:Value>
-        <ows20:Value>dc:language</ows20:Value>
-        <ows20:Value>dc:publisher</ows20:Value>
-        <ows20:Value>dc:relation</ows20:Value>
-        <ows20:Value>dc:rights</ows20:Value>
-        <ows20:Value>dc:source</ows20:Value>
-        <ows20:Value>dc:subject</ows20:Value>
-        <ows20:Value>dc:title</ows20:Value>
-        <ows20:Value>dc:type</ows20:Value>
-        <ows20:Value>dct:abstract</ows20:Value>
-        <ows20:Value>dct:alternative</ows20:Value>
-        <ows20:Value>dct:modified</ows20:Value>
-        <ows20:Value>dct:spatial</ows20:Value>
-        <ows20:Value>ows:BoundingBox</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="FederatedCatalogues">
-      <ows20:AllowedValues>
-        <ows20:Value>http://demo.pycsw.org/gisdata/csw</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="MaxRecordDefault">
-      <ows20:AllowedValues>
-        <ows20:Value>10</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="PostEncoding">
-      <ows20:AllowedValues>
-        <ows20:Value>SOAP</ows20:Value>
-        <ows20:Value>XML</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="XPathQueryables">
-      <ows20:AllowedValues>
-        <ows20:Value>allowed</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/CoreQueryables">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/CoreSortables">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/DefaultSortingAlgorithm">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Filter-CQL">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Filter-FES-KVP-Advanced">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Filter-FES-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetCapabilities-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetDomain-KVP">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetDomain-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetRecordById-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetRecords-Async-KVP">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetRecords-Async-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetRecords-Basic-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetRecords-Distributed-KVP">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetRecords-Distributed-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Harvest-Async-KVP">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Harvest-Async-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Harvest-Basic-KVP">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Harvest-Basic-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Harvest-Periodic-KVP">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Harvest-Periodic-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/OpenSearch">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/SupportedGMLVersions">
-      <ows20:AllowedValues>
-        <ows20:Value>http://www.opengis.net/gml</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Transaction">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-  </ows20:OperationsMetadata>
-  <ows20:Languages>
-    <ows20:Language>en</ows20:Language>
-  </ows20:Languages>
-  <fes20:Filter_Capabilities>
-    <fes20:Conformance>
-      <fes20:Constraint name="ImplementsQuery">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsAdHocQuery">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsFunctions">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsResourceld">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsMinStandardFilter">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsStandardFilter">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsMinSpatialFilter">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsSpatialFilter">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsMinTemporalFilter">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsTemporalFilter">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsVersionNav">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsSorting">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsExtendedOperators">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsMinimumXPath">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsSchemaElementFunc">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-    </fes20:Conformance>
-    <fes20:Id_Capabilities>
-      <fes20:ResourceIdentifier name="csw30:id"/>
-    </fes20:Id_Capabilities>
-    <fes20:Scalar_Capabilities>
-      <fes20:LogicalOperators/>
-      <fes20:ComparisonOperators>
-        <fes20:ComparisonOperator name="PropertyIsBetween"/>
-        <fes20:ComparisonOperator name="PropertyIsEqualTo"/>
-        <fes20:ComparisonOperator name="PropertyIsGreaterThan"/>
-        <fes20:ComparisonOperator name="PropertyIsGreaterThanOrEqualTo"/>
-        <fes20:ComparisonOperator name="PropertyIsLessThan"/>
-        <fes20:ComparisonOperator name="PropertyIsLessThanOrEqualTo"/>
-        <fes20:ComparisonOperator name="PropertyIsLike"/>
-        <fes20:ComparisonOperator name="PropertyIsNotEqualTo"/>
-        <fes20:ComparisonOperator name="PropertyIsNull"/>
-      </fes20:ComparisonOperators>
-    </fes20:Scalar_Capabilities>
-    <fes20:Spatial_Capabilities>
-      <fes20:GeometryOperands>
-        <fes20:GeometryOperand name="gml:Point"/>
-        <fes20:GeometryOperand name="gml:LineString"/>
-        <fes20:GeometryOperand name="gml:Polygon"/>
-        <fes20:GeometryOperand name="gml:Envelope"/>
-      </fes20:GeometryOperands>
-      <fes20:SpatialOperators>
-        <fes20:SpatialOperator name="BBOX"/>
-        <fes20:SpatialOperator name="Beyond"/>
-        <fes20:SpatialOperator name="Contains"/>
-        <fes20:SpatialOperator name="Crosses"/>
-        <fes20:SpatialOperator name="Disjoint"/>
-        <fes20:SpatialOperator name="DWithin"/>
-        <fes20:SpatialOperator name="Equals"/>
-        <fes20:SpatialOperator name="Intersects"/>
-        <fes20:SpatialOperator name="Overlaps"/>
-        <fes20:SpatialOperator name="Touches"/>
-        <fes20:SpatialOperator name="Within"/>
-      </fes20:SpatialOperators>
-    </fes20:Spatial_Capabilities>
-    <fes20:Functions>
-      <fes20:Function name="length">
-        <fes20:Returns>xs:string</fes20:Returns>
-      </fes20:Function>
-      <fes20:Function name="lower">
-        <fes20:Returns>xs:string</fes20:Returns>
-      </fes20:Function>
-      <fes20:Function name="ltrim">
-        <fes20:Returns>xs:string</fes20:Returns>
-      </fes20:Function>
-      <fes20:Function name="rtrim">
-        <fes20:Returns>xs:string</fes20:Returns>
-      </fes20:Function>
-      <fes20:Function name="trim">
-        <fes20:Returns>xs:string</fes20:Returns>
-      </fes20:Function>
-      <fes20:Function name="upper">
-        <fes20:Returns>xs:string</fes20:Returns>
-      </fes20:Function>
-    </fes20:Functions>
-  </fes20:Filter_Capabilities>
-</csw30:Capabilities>
diff --git a/tests/expected/suites_csw30_get_GetCapabilities-base-url.xml b/tests/expected/suites_csw30_get_GetCapabilities-base-url.xml
deleted file mode 100644
index c5cb70e..0000000
--- a/tests/expected/suites_csw30_get_GetCapabilities-base-url.xml
+++ /dev/null
@@ -1,493 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- PYCSW_VERSION -->
-<csw30:Capabilities xmlns:csw="http://www.opengis.net/cat/csw/2.0.2" xmlns:csw30="http://www.opengis.net/cat/csw/3.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dct="http://purl.org/dc/terms/" xmlns:fes20="http://www.opengis.net/fes/2.0" xmlns:gmd="http://www.isotc211.org/2005/gmd" xmlns:gml="http://www.opengis.net/gml" xmlns:ows="http://www.opengis.net/ows" xmlns:ows11="http://www.opengis.net/ows/1.1" xmlns:ows20="http://www.opengis.net/ows/2.0" xmlns:xlink="http://www.w3.org/199 [...]
-  <ows20:ServiceIdentification>
-    <ows20:Title>pycsw Geospatial Catalogue</ows20:Title>
-    <ows20:Abstract>pycsw is an OGC CSW server implementation written in Python</ows20:Abstract>
-    <ows20:Keywords>
-      <ows20:Keyword>catalogue</ows20:Keyword>
-      <ows20:Keyword>discovery</ows20:Keyword>
-      <ows20:Type codeSpace="ISOTC211/19115">theme</ows20:Type>
-    </ows20:Keywords>
-    <ows20:ServiceType codeSpace="OGC">CSW</ows20:ServiceType>
-    <ows20:ServiceTypeVersion>2.0.2</ows20:ServiceTypeVersion>
-    <ows20:ServiceTypeVersion>3.0.0</ows20:ServiceTypeVersion>
-    <ows20:Fees>None</ows20:Fees>
-    <ows20:AccessConstraints>None</ows20:AccessConstraints>
-  </ows20:ServiceIdentification>
-  <ows20:ServiceProvider>
-    <ows20:ProviderName>pycsw</ows20:ProviderName>
-    <ows20:ProviderSite xlink:type="simple" xlink:href="http://pycsw.org/"/>
-    <ows20:ServiceContact>
-      <ows20:IndividualName>Kralidis, Tom</ows20:IndividualName>
-      <ows20:PositionName>Senior Systems Scientist</ows20:PositionName>
-      <ows20:ContactInfo>
-        <ows20:Phone>
-          <ows20:Voice>+01-416-xxx-xxxx</ows20:Voice>
-          <ows20:Facsimile>+01-416-xxx-xxxx</ows20:Facsimile>
-        </ows20:Phone>
-        <ows20:Address>
-          <ows20:DeliveryPoint>TBA</ows20:DeliveryPoint>
-          <ows20:City>Toronto</ows20:City>
-          <ows20:AdministrativeArea>Ontario</ows20:AdministrativeArea>
-          <ows20:PostalCode>M9C 3Z9</ows20:PostalCode>
-          <ows20:Country>Canada</ows20:Country>
-          <ows20:ElectronicMailAddress>tomkralidis at gmail.com</ows20:ElectronicMailAddress>
-        </ows20:Address>
-        <ows20:OnlineResource xlink:type="simple" xlink:href="http://kralidis.ca/"/>
-        <ows20:HoursOfService>0800h - 1600h EST</ows20:HoursOfService>
-        <ows20:ContactInstructions>During hours of service.  Off on weekends.</ows20:ContactInstructions>
-      </ows20:ContactInfo>
-      <ows20:Role codeSpace="ISOTC211/19115">pointOfContact</ows20:Role>
-    </ows20:ServiceContact>
-  </ows20:ServiceProvider>
-  <ows20:OperationsMetadata>
-    <ows20:Operation name="GetCapabilities">
-      <ows20:DCP>
-        <ows20:HTTP>
-          <ows20:Get xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-          <ows20:Post xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-        </ows20:HTTP>
-      </ows20:DCP>
-      <ows20:Parameter name="acceptFormats">
-        <ows20:AllowedValues>
-          <ows20:Value>application/xml</ows20:Value>
-          <ows20:Value>text/xml</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="acceptVersions">
-        <ows20:AllowedValues>
-          <ows20:Value>2.0.2</ows20:Value>
-          <ows20:Value>3.0.0</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="sections">
-        <ows20:AllowedValues>
-          <ows20:Value>All</ows20:Value>
-          <ows20:Value>Filter_Capabilities</ows20:Value>
-          <ows20:Value>OperationsMetadata</ows20:Value>
-          <ows20:Value>ServiceIdentification</ows20:Value>
-          <ows20:Value>ServiceProvider</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-    </ows20:Operation>
-    <ows20:Operation name="GetDomain">
-      <ows20:DCP>
-        <ows20:HTTP>
-          <ows20:Get xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-          <ows20:Post xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-        </ows20:HTTP>
-      </ows20:DCP>
-      <ows20:Parameter name="ParameterName">
-        <ows20:AllowedValues>
-          <ows20:Value>GetCapabilities.acceptFormats</ows20:Value>
-          <ows20:Value>GetCapabilities.acceptVersions</ows20:Value>
-          <ows20:Value>GetCapabilities.sections</ows20:Value>
-          <ows20:Value>GetRecordById.ElementSetName</ows20:Value>
-          <ows20:Value>GetRecordById.outputFormat</ows20:Value>
-          <ows20:Value>GetRecordById.outputSchema</ows20:Value>
-          <ows20:Value>GetRecords.CONSTRAINTLANGUAGE</ows20:Value>
-          <ows20:Value>GetRecords.ElementSetName</ows20:Value>
-          <ows20:Value>GetRecords.outputFormat</ows20:Value>
-          <ows20:Value>GetRecords.outputSchema</ows20:Value>
-          <ows20:Value>GetRecords.typeNames</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-    </ows20:Operation>
-    <ows20:Operation name="GetRecords">
-      <ows20:DCP>
-        <ows20:HTTP>
-          <ows20:Get xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-          <ows20:Post xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-        </ows20:HTTP>
-      </ows20:DCP>
-      <ows20:Parameter name="CONSTRAINTLANGUAGE">
-        <ows20:AllowedValues>
-          <ows20:Value>CQL_TEXT</ows20:Value>
-          <ows20:Value>FILTER</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="ElementSetName">
-        <ows20:AllowedValues>
-          <ows20:Value>brief</ows20:Value>
-          <ows20:Value>full</ows20:Value>
-          <ows20:Value>summary</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="outputFormat">
-        <ows20:AllowedValues>
-          <ows20:Value>application/atom+xml</ows20:Value>
-          <ows20:Value>application/json</ows20:Value>
-          <ows20:Value>application/xml</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="outputSchema">
-        <ows20:AllowedValues>
-          <ows20:Value>http://gcmd.gsfc.nasa.gov/Aboutus/xml/dif/</ows20:Value>
-          <ows20:Value>http://www.interlis.ch/INTERLIS2.3</ows20:Value>
-          <ows20:Value>http://www.opengis.net/cat/csw/3.0</ows20:Value>
-          <ows20:Value>http://www.opengis.net/cat/csw/csdgm</ows20:Value>
-          <ows20:Value>http://www.w3.org/2005/Atom</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="typeNames">
-        <ows20:AllowedValues>
-          <ows20:Value>csw:Record</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Constraint name="MaxRecordDefault">
-        <ows20:AllowedValues>
-          <ows20:Value>10</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Constraint>
-      <ows20:Constraint name="OpenSearchDescriptionDocument">
-        <ows20:AllowedValues>
-          <ows20:Value>http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg?mode=opensearch&service=CSW&version=3.0.0&request=GetCapabilities</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Constraint>
-      <ows20:Constraint name="FederatedCatalogues">
-        <ows20:AllowedValues>
-          <ows20:Value>http://demo.pycsw.org/gisdata/csw</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Constraint>
-    </ows20:Operation>
-    <ows20:Operation name="GetRecordById">
-      <ows20:DCP>
-        <ows20:HTTP>
-          <ows20:Get xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-          <ows20:Post xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-        </ows20:HTTP>
-      </ows20:DCP>
-      <ows20:Parameter name="ElementSetName">
-        <ows20:AllowedValues>
-          <ows20:Value>brief</ows20:Value>
-          <ows20:Value>full</ows20:Value>
-          <ows20:Value>summary</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="outputFormat">
-        <ows20:AllowedValues>
-          <ows20:Value>application/atom+xml</ows20:Value>
-          <ows20:Value>application/json</ows20:Value>
-          <ows20:Value>application/xml</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="outputSchema">
-        <ows20:AllowedValues>
-          <ows20:Value>http://gcmd.gsfc.nasa.gov/Aboutus/xml/dif/</ows20:Value>
-          <ows20:Value>http://www.interlis.ch/INTERLIS2.3</ows20:Value>
-          <ows20:Value>http://www.opengis.net/cat/csw/3.0</ows20:Value>
-          <ows20:Value>http://www.opengis.net/cat/csw/csdgm</ows20:Value>
-          <ows20:Value>http://www.w3.org/2005/Atom</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-    </ows20:Operation>
-    <ows20:Operation name="GetRepositoryItem">
-      <ows20:DCP>
-        <ows20:HTTP>
-          <ows20:Get xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-        </ows20:HTTP>
-      </ows20:DCP>
-    </ows20:Operation>
-    <ows20:Parameter name="service">
-      <ows20:AllowedValues>
-        <ows20:Value>CSW</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Parameter>
-    <ows20:Parameter name="version">
-      <ows20:AllowedValues>
-        <ows20:Value>2.0.2</ows20:Value>
-        <ows20:Value>3.0.0</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Parameter>
-    <ows20:Constraint name="CoreQueryables">
-      <ows20:AllowedValues>
-        <ows20:Value>csw:AnyText</ows20:Value>
-        <ows20:Value>dc:contributor</ows20:Value>
-        <ows20:Value>dc:creator</ows20:Value>
-        <ows20:Value>dc:date</ows20:Value>
-        <ows20:Value>dc:format</ows20:Value>
-        <ows20:Value>dc:identifier</ows20:Value>
-        <ows20:Value>dc:language</ows20:Value>
-        <ows20:Value>dc:publisher</ows20:Value>
-        <ows20:Value>dc:relation</ows20:Value>
-        <ows20:Value>dc:rights</ows20:Value>
-        <ows20:Value>dc:source</ows20:Value>
-        <ows20:Value>dc:subject</ows20:Value>
-        <ows20:Value>dc:title</ows20:Value>
-        <ows20:Value>dc:type</ows20:Value>
-        <ows20:Value>dct:abstract</ows20:Value>
-        <ows20:Value>dct:alternative</ows20:Value>
-        <ows20:Value>dct:modified</ows20:Value>
-        <ows20:Value>dct:spatial</ows20:Value>
-        <ows20:Value>ows:BoundingBox</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="FederatedCatalogues">
-      <ows20:AllowedValues>
-        <ows20:Value>http://demo.pycsw.org/gisdata/csw</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="MaxRecordDefault">
-      <ows20:AllowedValues>
-        <ows20:Value>10</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="PostEncoding">
-      <ows20:AllowedValues>
-        <ows20:Value>SOAP</ows20:Value>
-        <ows20:Value>XML</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="XPathQueryables">
-      <ows20:AllowedValues>
-        <ows20:Value>allowed</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/CoreQueryables">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/CoreSortables">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/DefaultSortingAlgorithm">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Filter-CQL">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Filter-FES-KVP-Advanced">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Filter-FES-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetCapabilities-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetDomain-KVP">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetDomain-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetRecordById-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetRecords-Async-KVP">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetRecords-Async-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetRecords-Basic-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetRecords-Distributed-KVP">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetRecords-Distributed-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Harvest-Async-KVP">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Harvest-Async-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Harvest-Basic-KVP">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Harvest-Basic-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Harvest-Periodic-KVP">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Harvest-Periodic-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/OpenSearch">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/SupportedGMLVersions">
-      <ows20:AllowedValues>
-        <ows20:Value>http://www.opengis.net/gml</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Transaction">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-  </ows20:OperationsMetadata>
-  <ows20:Languages>
-    <ows20:Language>en</ows20:Language>
-  </ows20:Languages>
-  <fes20:Filter_Capabilities>
-    <fes20:Conformance>
-      <fes20:Constraint name="ImplementsQuery">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsAdHocQuery">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsFunctions">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsResourceld">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsMinStandardFilter">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsStandardFilter">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsMinSpatialFilter">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsSpatialFilter">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsMinTemporalFilter">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsTemporalFilter">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsVersionNav">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsSorting">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsExtendedOperators">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsMinimumXPath">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsSchemaElementFunc">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-    </fes20:Conformance>
-    <fes20:Id_Capabilities>
-      <fes20:ResourceIdentifier name="csw30:id"/>
-    </fes20:Id_Capabilities>
-    <fes20:Scalar_Capabilities>
-      <fes20:LogicalOperators/>
-      <fes20:ComparisonOperators>
-        <fes20:ComparisonOperator name="PropertyIsBetween"/>
-        <fes20:ComparisonOperator name="PropertyIsEqualTo"/>
-        <fes20:ComparisonOperator name="PropertyIsGreaterThan"/>
-        <fes20:ComparisonOperator name="PropertyIsGreaterThanOrEqualTo"/>
-        <fes20:ComparisonOperator name="PropertyIsLessThan"/>
-        <fes20:ComparisonOperator name="PropertyIsLessThanOrEqualTo"/>
-        <fes20:ComparisonOperator name="PropertyIsLike"/>
-        <fes20:ComparisonOperator name="PropertyIsNotEqualTo"/>
-        <fes20:ComparisonOperator name="PropertyIsNull"/>
-      </fes20:ComparisonOperators>
-    </fes20:Scalar_Capabilities>
-    <fes20:Spatial_Capabilities>
-      <fes20:GeometryOperands>
-        <fes20:GeometryOperand name="gml:Point"/>
-        <fes20:GeometryOperand name="gml:LineString"/>
-        <fes20:GeometryOperand name="gml:Polygon"/>
-        <fes20:GeometryOperand name="gml:Envelope"/>
-      </fes20:GeometryOperands>
-      <fes20:SpatialOperators>
-        <fes20:SpatialOperator name="BBOX"/>
-        <fes20:SpatialOperator name="Beyond"/>
-        <fes20:SpatialOperator name="Contains"/>
-        <fes20:SpatialOperator name="Crosses"/>
-        <fes20:SpatialOperator name="Disjoint"/>
-        <fes20:SpatialOperator name="DWithin"/>
-        <fes20:SpatialOperator name="Equals"/>
-        <fes20:SpatialOperator name="Intersects"/>
-        <fes20:SpatialOperator name="Overlaps"/>
-        <fes20:SpatialOperator name="Touches"/>
-        <fes20:SpatialOperator name="Within"/>
-      </fes20:SpatialOperators>
-    </fes20:Spatial_Capabilities>
-    <fes20:Functions>
-      <fes20:Function name="length">
-        <fes20:Returns>xs:string</fes20:Returns>
-      </fes20:Function>
-      <fes20:Function name="lower">
-        <fes20:Returns>xs:string</fes20:Returns>
-      </fes20:Function>
-      <fes20:Function name="ltrim">
-        <fes20:Returns>xs:string</fes20:Returns>
-      </fes20:Function>
-      <fes20:Function name="rtrim">
-        <fes20:Returns>xs:string</fes20:Returns>
-      </fes20:Function>
-      <fes20:Function name="trim">
-        <fes20:Returns>xs:string</fes20:Returns>
-      </fes20:Function>
-      <fes20:Function name="upper">
-        <fes20:Returns>xs:string</fes20:Returns>
-      </fes20:Function>
-    </fes20:Functions>
-  </fes20:Filter_Capabilities>
-</csw30:Capabilities>
diff --git a/tests/expected/suites_csw30_get_GetCapabilities-no-version.xml b/tests/expected/suites_csw30_get_GetCapabilities-no-version.xml
deleted file mode 100644
index c5cb70e..0000000
--- a/tests/expected/suites_csw30_get_GetCapabilities-no-version.xml
+++ /dev/null
@@ -1,493 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- PYCSW_VERSION -->
-<csw30:Capabilities xmlns:csw="http://www.opengis.net/cat/csw/2.0.2" xmlns:csw30="http://www.opengis.net/cat/csw/3.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dct="http://purl.org/dc/terms/" xmlns:fes20="http://www.opengis.net/fes/2.0" xmlns:gmd="http://www.isotc211.org/2005/gmd" xmlns:gml="http://www.opengis.net/gml" xmlns:ows="http://www.opengis.net/ows" xmlns:ows11="http://www.opengis.net/ows/1.1" xmlns:ows20="http://www.opengis.net/ows/2.0" xmlns:xlink="http://www.w3.org/199 [...]
-  <ows20:ServiceIdentification>
-    <ows20:Title>pycsw Geospatial Catalogue</ows20:Title>
-    <ows20:Abstract>pycsw is an OGC CSW server implementation written in Python</ows20:Abstract>
-    <ows20:Keywords>
-      <ows20:Keyword>catalogue</ows20:Keyword>
-      <ows20:Keyword>discovery</ows20:Keyword>
-      <ows20:Type codeSpace="ISOTC211/19115">theme</ows20:Type>
-    </ows20:Keywords>
-    <ows20:ServiceType codeSpace="OGC">CSW</ows20:ServiceType>
-    <ows20:ServiceTypeVersion>2.0.2</ows20:ServiceTypeVersion>
-    <ows20:ServiceTypeVersion>3.0.0</ows20:ServiceTypeVersion>
-    <ows20:Fees>None</ows20:Fees>
-    <ows20:AccessConstraints>None</ows20:AccessConstraints>
-  </ows20:ServiceIdentification>
-  <ows20:ServiceProvider>
-    <ows20:ProviderName>pycsw</ows20:ProviderName>
-    <ows20:ProviderSite xlink:type="simple" xlink:href="http://pycsw.org/"/>
-    <ows20:ServiceContact>
-      <ows20:IndividualName>Kralidis, Tom</ows20:IndividualName>
-      <ows20:PositionName>Senior Systems Scientist</ows20:PositionName>
-      <ows20:ContactInfo>
-        <ows20:Phone>
-          <ows20:Voice>+01-416-xxx-xxxx</ows20:Voice>
-          <ows20:Facsimile>+01-416-xxx-xxxx</ows20:Facsimile>
-        </ows20:Phone>
-        <ows20:Address>
-          <ows20:DeliveryPoint>TBA</ows20:DeliveryPoint>
-          <ows20:City>Toronto</ows20:City>
-          <ows20:AdministrativeArea>Ontario</ows20:AdministrativeArea>
-          <ows20:PostalCode>M9C 3Z9</ows20:PostalCode>
-          <ows20:Country>Canada</ows20:Country>
-          <ows20:ElectronicMailAddress>tomkralidis at gmail.com</ows20:ElectronicMailAddress>
-        </ows20:Address>
-        <ows20:OnlineResource xlink:type="simple" xlink:href="http://kralidis.ca/"/>
-        <ows20:HoursOfService>0800h - 1600h EST</ows20:HoursOfService>
-        <ows20:ContactInstructions>During hours of service.  Off on weekends.</ows20:ContactInstructions>
-      </ows20:ContactInfo>
-      <ows20:Role codeSpace="ISOTC211/19115">pointOfContact</ows20:Role>
-    </ows20:ServiceContact>
-  </ows20:ServiceProvider>
-  <ows20:OperationsMetadata>
-    <ows20:Operation name="GetCapabilities">
-      <ows20:DCP>
-        <ows20:HTTP>
-          <ows20:Get xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-          <ows20:Post xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-        </ows20:HTTP>
-      </ows20:DCP>
-      <ows20:Parameter name="acceptFormats">
-        <ows20:AllowedValues>
-          <ows20:Value>application/xml</ows20:Value>
-          <ows20:Value>text/xml</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="acceptVersions">
-        <ows20:AllowedValues>
-          <ows20:Value>2.0.2</ows20:Value>
-          <ows20:Value>3.0.0</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="sections">
-        <ows20:AllowedValues>
-          <ows20:Value>All</ows20:Value>
-          <ows20:Value>Filter_Capabilities</ows20:Value>
-          <ows20:Value>OperationsMetadata</ows20:Value>
-          <ows20:Value>ServiceIdentification</ows20:Value>
-          <ows20:Value>ServiceProvider</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-    </ows20:Operation>
-    <ows20:Operation name="GetDomain">
-      <ows20:DCP>
-        <ows20:HTTP>
-          <ows20:Get xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-          <ows20:Post xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-        </ows20:HTTP>
-      </ows20:DCP>
-      <ows20:Parameter name="ParameterName">
-        <ows20:AllowedValues>
-          <ows20:Value>GetCapabilities.acceptFormats</ows20:Value>
-          <ows20:Value>GetCapabilities.acceptVersions</ows20:Value>
-          <ows20:Value>GetCapabilities.sections</ows20:Value>
-          <ows20:Value>GetRecordById.ElementSetName</ows20:Value>
-          <ows20:Value>GetRecordById.outputFormat</ows20:Value>
-          <ows20:Value>GetRecordById.outputSchema</ows20:Value>
-          <ows20:Value>GetRecords.CONSTRAINTLANGUAGE</ows20:Value>
-          <ows20:Value>GetRecords.ElementSetName</ows20:Value>
-          <ows20:Value>GetRecords.outputFormat</ows20:Value>
-          <ows20:Value>GetRecords.outputSchema</ows20:Value>
-          <ows20:Value>GetRecords.typeNames</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-    </ows20:Operation>
-    <ows20:Operation name="GetRecords">
-      <ows20:DCP>
-        <ows20:HTTP>
-          <ows20:Get xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-          <ows20:Post xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-        </ows20:HTTP>
-      </ows20:DCP>
-      <ows20:Parameter name="CONSTRAINTLANGUAGE">
-        <ows20:AllowedValues>
-          <ows20:Value>CQL_TEXT</ows20:Value>
-          <ows20:Value>FILTER</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="ElementSetName">
-        <ows20:AllowedValues>
-          <ows20:Value>brief</ows20:Value>
-          <ows20:Value>full</ows20:Value>
-          <ows20:Value>summary</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="outputFormat">
-        <ows20:AllowedValues>
-          <ows20:Value>application/atom+xml</ows20:Value>
-          <ows20:Value>application/json</ows20:Value>
-          <ows20:Value>application/xml</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="outputSchema">
-        <ows20:AllowedValues>
-          <ows20:Value>http://gcmd.gsfc.nasa.gov/Aboutus/xml/dif/</ows20:Value>
-          <ows20:Value>http://www.interlis.ch/INTERLIS2.3</ows20:Value>
-          <ows20:Value>http://www.opengis.net/cat/csw/3.0</ows20:Value>
-          <ows20:Value>http://www.opengis.net/cat/csw/csdgm</ows20:Value>
-          <ows20:Value>http://www.w3.org/2005/Atom</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="typeNames">
-        <ows20:AllowedValues>
-          <ows20:Value>csw:Record</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Constraint name="MaxRecordDefault">
-        <ows20:AllowedValues>
-          <ows20:Value>10</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Constraint>
-      <ows20:Constraint name="OpenSearchDescriptionDocument">
-        <ows20:AllowedValues>
-          <ows20:Value>http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg?mode=opensearch&service=CSW&version=3.0.0&request=GetCapabilities</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Constraint>
-      <ows20:Constraint name="FederatedCatalogues">
-        <ows20:AllowedValues>
-          <ows20:Value>http://demo.pycsw.org/gisdata/csw</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Constraint>
-    </ows20:Operation>
-    <ows20:Operation name="GetRecordById">
-      <ows20:DCP>
-        <ows20:HTTP>
-          <ows20:Get xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-          <ows20:Post xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-        </ows20:HTTP>
-      </ows20:DCP>
-      <ows20:Parameter name="ElementSetName">
-        <ows20:AllowedValues>
-          <ows20:Value>brief</ows20:Value>
-          <ows20:Value>full</ows20:Value>
-          <ows20:Value>summary</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="outputFormat">
-        <ows20:AllowedValues>
-          <ows20:Value>application/atom+xml</ows20:Value>
-          <ows20:Value>application/json</ows20:Value>
-          <ows20:Value>application/xml</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="outputSchema">
-        <ows20:AllowedValues>
-          <ows20:Value>http://gcmd.gsfc.nasa.gov/Aboutus/xml/dif/</ows20:Value>
-          <ows20:Value>http://www.interlis.ch/INTERLIS2.3</ows20:Value>
-          <ows20:Value>http://www.opengis.net/cat/csw/3.0</ows20:Value>
-          <ows20:Value>http://www.opengis.net/cat/csw/csdgm</ows20:Value>
-          <ows20:Value>http://www.w3.org/2005/Atom</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-    </ows20:Operation>
-    <ows20:Operation name="GetRepositoryItem">
-      <ows20:DCP>
-        <ows20:HTTP>
-          <ows20:Get xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-        </ows20:HTTP>
-      </ows20:DCP>
-    </ows20:Operation>
-    <ows20:Parameter name="service">
-      <ows20:AllowedValues>
-        <ows20:Value>CSW</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Parameter>
-    <ows20:Parameter name="version">
-      <ows20:AllowedValues>
-        <ows20:Value>2.0.2</ows20:Value>
-        <ows20:Value>3.0.0</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Parameter>
-    <ows20:Constraint name="CoreQueryables">
-      <ows20:AllowedValues>
-        <ows20:Value>csw:AnyText</ows20:Value>
-        <ows20:Value>dc:contributor</ows20:Value>
-        <ows20:Value>dc:creator</ows20:Value>
-        <ows20:Value>dc:date</ows20:Value>
-        <ows20:Value>dc:format</ows20:Value>
-        <ows20:Value>dc:identifier</ows20:Value>
-        <ows20:Value>dc:language</ows20:Value>
-        <ows20:Value>dc:publisher</ows20:Value>
-        <ows20:Value>dc:relation</ows20:Value>
-        <ows20:Value>dc:rights</ows20:Value>
-        <ows20:Value>dc:source</ows20:Value>
-        <ows20:Value>dc:subject</ows20:Value>
-        <ows20:Value>dc:title</ows20:Value>
-        <ows20:Value>dc:type</ows20:Value>
-        <ows20:Value>dct:abstract</ows20:Value>
-        <ows20:Value>dct:alternative</ows20:Value>
-        <ows20:Value>dct:modified</ows20:Value>
-        <ows20:Value>dct:spatial</ows20:Value>
-        <ows20:Value>ows:BoundingBox</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="FederatedCatalogues">
-      <ows20:AllowedValues>
-        <ows20:Value>http://demo.pycsw.org/gisdata/csw</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="MaxRecordDefault">
-      <ows20:AllowedValues>
-        <ows20:Value>10</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="PostEncoding">
-      <ows20:AllowedValues>
-        <ows20:Value>SOAP</ows20:Value>
-        <ows20:Value>XML</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="XPathQueryables">
-      <ows20:AllowedValues>
-        <ows20:Value>allowed</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/CoreQueryables">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/CoreSortables">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/DefaultSortingAlgorithm">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Filter-CQL">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Filter-FES-KVP-Advanced">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Filter-FES-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetCapabilities-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetDomain-KVP">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetDomain-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetRecordById-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetRecords-Async-KVP">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetRecords-Async-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetRecords-Basic-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetRecords-Distributed-KVP">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetRecords-Distributed-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Harvest-Async-KVP">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Harvest-Async-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Harvest-Basic-KVP">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Harvest-Basic-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Harvest-Periodic-KVP">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Harvest-Periodic-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/OpenSearch">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/SupportedGMLVersions">
-      <ows20:AllowedValues>
-        <ows20:Value>http://www.opengis.net/gml</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Transaction">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-  </ows20:OperationsMetadata>
-  <ows20:Languages>
-    <ows20:Language>en</ows20:Language>
-  </ows20:Languages>
-  <fes20:Filter_Capabilities>
-    <fes20:Conformance>
-      <fes20:Constraint name="ImplementsQuery">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsAdHocQuery">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsFunctions">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsResourceld">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsMinStandardFilter">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsStandardFilter">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsMinSpatialFilter">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsSpatialFilter">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsMinTemporalFilter">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsTemporalFilter">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsVersionNav">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsSorting">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsExtendedOperators">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsMinimumXPath">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsSchemaElementFunc">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-    </fes20:Conformance>
-    <fes20:Id_Capabilities>
-      <fes20:ResourceIdentifier name="csw30:id"/>
-    </fes20:Id_Capabilities>
-    <fes20:Scalar_Capabilities>
-      <fes20:LogicalOperators/>
-      <fes20:ComparisonOperators>
-        <fes20:ComparisonOperator name="PropertyIsBetween"/>
-        <fes20:ComparisonOperator name="PropertyIsEqualTo"/>
-        <fes20:ComparisonOperator name="PropertyIsGreaterThan"/>
-        <fes20:ComparisonOperator name="PropertyIsGreaterThanOrEqualTo"/>
-        <fes20:ComparisonOperator name="PropertyIsLessThan"/>
-        <fes20:ComparisonOperator name="PropertyIsLessThanOrEqualTo"/>
-        <fes20:ComparisonOperator name="PropertyIsLike"/>
-        <fes20:ComparisonOperator name="PropertyIsNotEqualTo"/>
-        <fes20:ComparisonOperator name="PropertyIsNull"/>
-      </fes20:ComparisonOperators>
-    </fes20:Scalar_Capabilities>
-    <fes20:Spatial_Capabilities>
-      <fes20:GeometryOperands>
-        <fes20:GeometryOperand name="gml:Point"/>
-        <fes20:GeometryOperand name="gml:LineString"/>
-        <fes20:GeometryOperand name="gml:Polygon"/>
-        <fes20:GeometryOperand name="gml:Envelope"/>
-      </fes20:GeometryOperands>
-      <fes20:SpatialOperators>
-        <fes20:SpatialOperator name="BBOX"/>
-        <fes20:SpatialOperator name="Beyond"/>
-        <fes20:SpatialOperator name="Contains"/>
-        <fes20:SpatialOperator name="Crosses"/>
-        <fes20:SpatialOperator name="Disjoint"/>
-        <fes20:SpatialOperator name="DWithin"/>
-        <fes20:SpatialOperator name="Equals"/>
-        <fes20:SpatialOperator name="Intersects"/>
-        <fes20:SpatialOperator name="Overlaps"/>
-        <fes20:SpatialOperator name="Touches"/>
-        <fes20:SpatialOperator name="Within"/>
-      </fes20:SpatialOperators>
-    </fes20:Spatial_Capabilities>
-    <fes20:Functions>
-      <fes20:Function name="length">
-        <fes20:Returns>xs:string</fes20:Returns>
-      </fes20:Function>
-      <fes20:Function name="lower">
-        <fes20:Returns>xs:string</fes20:Returns>
-      </fes20:Function>
-      <fes20:Function name="ltrim">
-        <fes20:Returns>xs:string</fes20:Returns>
-      </fes20:Function>
-      <fes20:Function name="rtrim">
-        <fes20:Returns>xs:string</fes20:Returns>
-      </fes20:Function>
-      <fes20:Function name="trim">
-        <fes20:Returns>xs:string</fes20:Returns>
-      </fes20:Function>
-      <fes20:Function name="upper">
-        <fes20:Returns>xs:string</fes20:Returns>
-      </fes20:Function>
-    </fes20:Functions>
-  </fes20:Filter_Capabilities>
-</csw30:Capabilities>
diff --git a/tests/expected/suites_csw30_get_GetCapabilities.xml b/tests/expected/suites_csw30_get_GetCapabilities.xml
deleted file mode 100644
index c5cb70e..0000000
--- a/tests/expected/suites_csw30_get_GetCapabilities.xml
+++ /dev/null
@@ -1,493 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- PYCSW_VERSION -->
-<csw30:Capabilities xmlns:csw="http://www.opengis.net/cat/csw/2.0.2" xmlns:csw30="http://www.opengis.net/cat/csw/3.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dct="http://purl.org/dc/terms/" xmlns:fes20="http://www.opengis.net/fes/2.0" xmlns:gmd="http://www.isotc211.org/2005/gmd" xmlns:gml="http://www.opengis.net/gml" xmlns:ows="http://www.opengis.net/ows" xmlns:ows11="http://www.opengis.net/ows/1.1" xmlns:ows20="http://www.opengis.net/ows/2.0" xmlns:xlink="http://www.w3.org/199 [...]
-  <ows20:ServiceIdentification>
-    <ows20:Title>pycsw Geospatial Catalogue</ows20:Title>
-    <ows20:Abstract>pycsw is an OGC CSW server implementation written in Python</ows20:Abstract>
-    <ows20:Keywords>
-      <ows20:Keyword>catalogue</ows20:Keyword>
-      <ows20:Keyword>discovery</ows20:Keyword>
-      <ows20:Type codeSpace="ISOTC211/19115">theme</ows20:Type>
-    </ows20:Keywords>
-    <ows20:ServiceType codeSpace="OGC">CSW</ows20:ServiceType>
-    <ows20:ServiceTypeVersion>2.0.2</ows20:ServiceTypeVersion>
-    <ows20:ServiceTypeVersion>3.0.0</ows20:ServiceTypeVersion>
-    <ows20:Fees>None</ows20:Fees>
-    <ows20:AccessConstraints>None</ows20:AccessConstraints>
-  </ows20:ServiceIdentification>
-  <ows20:ServiceProvider>
-    <ows20:ProviderName>pycsw</ows20:ProviderName>
-    <ows20:ProviderSite xlink:type="simple" xlink:href="http://pycsw.org/"/>
-    <ows20:ServiceContact>
-      <ows20:IndividualName>Kralidis, Tom</ows20:IndividualName>
-      <ows20:PositionName>Senior Systems Scientist</ows20:PositionName>
-      <ows20:ContactInfo>
-        <ows20:Phone>
-          <ows20:Voice>+01-416-xxx-xxxx</ows20:Voice>
-          <ows20:Facsimile>+01-416-xxx-xxxx</ows20:Facsimile>
-        </ows20:Phone>
-        <ows20:Address>
-          <ows20:DeliveryPoint>TBA</ows20:DeliveryPoint>
-          <ows20:City>Toronto</ows20:City>
-          <ows20:AdministrativeArea>Ontario</ows20:AdministrativeArea>
-          <ows20:PostalCode>M9C 3Z9</ows20:PostalCode>
-          <ows20:Country>Canada</ows20:Country>
-          <ows20:ElectronicMailAddress>tomkralidis at gmail.com</ows20:ElectronicMailAddress>
-        </ows20:Address>
-        <ows20:OnlineResource xlink:type="simple" xlink:href="http://kralidis.ca/"/>
-        <ows20:HoursOfService>0800h - 1600h EST</ows20:HoursOfService>
-        <ows20:ContactInstructions>During hours of service.  Off on weekends.</ows20:ContactInstructions>
-      </ows20:ContactInfo>
-      <ows20:Role codeSpace="ISOTC211/19115">pointOfContact</ows20:Role>
-    </ows20:ServiceContact>
-  </ows20:ServiceProvider>
-  <ows20:OperationsMetadata>
-    <ows20:Operation name="GetCapabilities">
-      <ows20:DCP>
-        <ows20:HTTP>
-          <ows20:Get xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-          <ows20:Post xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-        </ows20:HTTP>
-      </ows20:DCP>
-      <ows20:Parameter name="acceptFormats">
-        <ows20:AllowedValues>
-          <ows20:Value>application/xml</ows20:Value>
-          <ows20:Value>text/xml</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="acceptVersions">
-        <ows20:AllowedValues>
-          <ows20:Value>2.0.2</ows20:Value>
-          <ows20:Value>3.0.0</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="sections">
-        <ows20:AllowedValues>
-          <ows20:Value>All</ows20:Value>
-          <ows20:Value>Filter_Capabilities</ows20:Value>
-          <ows20:Value>OperationsMetadata</ows20:Value>
-          <ows20:Value>ServiceIdentification</ows20:Value>
-          <ows20:Value>ServiceProvider</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-    </ows20:Operation>
-    <ows20:Operation name="GetDomain">
-      <ows20:DCP>
-        <ows20:HTTP>
-          <ows20:Get xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-          <ows20:Post xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-        </ows20:HTTP>
-      </ows20:DCP>
-      <ows20:Parameter name="ParameterName">
-        <ows20:AllowedValues>
-          <ows20:Value>GetCapabilities.acceptFormats</ows20:Value>
-          <ows20:Value>GetCapabilities.acceptVersions</ows20:Value>
-          <ows20:Value>GetCapabilities.sections</ows20:Value>
-          <ows20:Value>GetRecordById.ElementSetName</ows20:Value>
-          <ows20:Value>GetRecordById.outputFormat</ows20:Value>
-          <ows20:Value>GetRecordById.outputSchema</ows20:Value>
-          <ows20:Value>GetRecords.CONSTRAINTLANGUAGE</ows20:Value>
-          <ows20:Value>GetRecords.ElementSetName</ows20:Value>
-          <ows20:Value>GetRecords.outputFormat</ows20:Value>
-          <ows20:Value>GetRecords.outputSchema</ows20:Value>
-          <ows20:Value>GetRecords.typeNames</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-    </ows20:Operation>
-    <ows20:Operation name="GetRecords">
-      <ows20:DCP>
-        <ows20:HTTP>
-          <ows20:Get xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-          <ows20:Post xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-        </ows20:HTTP>
-      </ows20:DCP>
-      <ows20:Parameter name="CONSTRAINTLANGUAGE">
-        <ows20:AllowedValues>
-          <ows20:Value>CQL_TEXT</ows20:Value>
-          <ows20:Value>FILTER</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="ElementSetName">
-        <ows20:AllowedValues>
-          <ows20:Value>brief</ows20:Value>
-          <ows20:Value>full</ows20:Value>
-          <ows20:Value>summary</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="outputFormat">
-        <ows20:AllowedValues>
-          <ows20:Value>application/atom+xml</ows20:Value>
-          <ows20:Value>application/json</ows20:Value>
-          <ows20:Value>application/xml</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="outputSchema">
-        <ows20:AllowedValues>
-          <ows20:Value>http://gcmd.gsfc.nasa.gov/Aboutus/xml/dif/</ows20:Value>
-          <ows20:Value>http://www.interlis.ch/INTERLIS2.3</ows20:Value>
-          <ows20:Value>http://www.opengis.net/cat/csw/3.0</ows20:Value>
-          <ows20:Value>http://www.opengis.net/cat/csw/csdgm</ows20:Value>
-          <ows20:Value>http://www.w3.org/2005/Atom</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="typeNames">
-        <ows20:AllowedValues>
-          <ows20:Value>csw:Record</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Constraint name="MaxRecordDefault">
-        <ows20:AllowedValues>
-          <ows20:Value>10</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Constraint>
-      <ows20:Constraint name="OpenSearchDescriptionDocument">
-        <ows20:AllowedValues>
-          <ows20:Value>http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg?mode=opensearch&service=CSW&version=3.0.0&request=GetCapabilities</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Constraint>
-      <ows20:Constraint name="FederatedCatalogues">
-        <ows20:AllowedValues>
-          <ows20:Value>http://demo.pycsw.org/gisdata/csw</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Constraint>
-    </ows20:Operation>
-    <ows20:Operation name="GetRecordById">
-      <ows20:DCP>
-        <ows20:HTTP>
-          <ows20:Get xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-          <ows20:Post xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-        </ows20:HTTP>
-      </ows20:DCP>
-      <ows20:Parameter name="ElementSetName">
-        <ows20:AllowedValues>
-          <ows20:Value>brief</ows20:Value>
-          <ows20:Value>full</ows20:Value>
-          <ows20:Value>summary</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="outputFormat">
-        <ows20:AllowedValues>
-          <ows20:Value>application/atom+xml</ows20:Value>
-          <ows20:Value>application/json</ows20:Value>
-          <ows20:Value>application/xml</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="outputSchema">
-        <ows20:AllowedValues>
-          <ows20:Value>http://gcmd.gsfc.nasa.gov/Aboutus/xml/dif/</ows20:Value>
-          <ows20:Value>http://www.interlis.ch/INTERLIS2.3</ows20:Value>
-          <ows20:Value>http://www.opengis.net/cat/csw/3.0</ows20:Value>
-          <ows20:Value>http://www.opengis.net/cat/csw/csdgm</ows20:Value>
-          <ows20:Value>http://www.w3.org/2005/Atom</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-    </ows20:Operation>
-    <ows20:Operation name="GetRepositoryItem">
-      <ows20:DCP>
-        <ows20:HTTP>
-          <ows20:Get xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-        </ows20:HTTP>
-      </ows20:DCP>
-    </ows20:Operation>
-    <ows20:Parameter name="service">
-      <ows20:AllowedValues>
-        <ows20:Value>CSW</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Parameter>
-    <ows20:Parameter name="version">
-      <ows20:AllowedValues>
-        <ows20:Value>2.0.2</ows20:Value>
-        <ows20:Value>3.0.0</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Parameter>
-    <ows20:Constraint name="CoreQueryables">
-      <ows20:AllowedValues>
-        <ows20:Value>csw:AnyText</ows20:Value>
-        <ows20:Value>dc:contributor</ows20:Value>
-        <ows20:Value>dc:creator</ows20:Value>
-        <ows20:Value>dc:date</ows20:Value>
-        <ows20:Value>dc:format</ows20:Value>
-        <ows20:Value>dc:identifier</ows20:Value>
-        <ows20:Value>dc:language</ows20:Value>
-        <ows20:Value>dc:publisher</ows20:Value>
-        <ows20:Value>dc:relation</ows20:Value>
-        <ows20:Value>dc:rights</ows20:Value>
-        <ows20:Value>dc:source</ows20:Value>
-        <ows20:Value>dc:subject</ows20:Value>
-        <ows20:Value>dc:title</ows20:Value>
-        <ows20:Value>dc:type</ows20:Value>
-        <ows20:Value>dct:abstract</ows20:Value>
-        <ows20:Value>dct:alternative</ows20:Value>
-        <ows20:Value>dct:modified</ows20:Value>
-        <ows20:Value>dct:spatial</ows20:Value>
-        <ows20:Value>ows:BoundingBox</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="FederatedCatalogues">
-      <ows20:AllowedValues>
-        <ows20:Value>http://demo.pycsw.org/gisdata/csw</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="MaxRecordDefault">
-      <ows20:AllowedValues>
-        <ows20:Value>10</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="PostEncoding">
-      <ows20:AllowedValues>
-        <ows20:Value>SOAP</ows20:Value>
-        <ows20:Value>XML</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="XPathQueryables">
-      <ows20:AllowedValues>
-        <ows20:Value>allowed</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/CoreQueryables">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/CoreSortables">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/DefaultSortingAlgorithm">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Filter-CQL">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Filter-FES-KVP-Advanced">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Filter-FES-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetCapabilities-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetDomain-KVP">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetDomain-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetRecordById-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetRecords-Async-KVP">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetRecords-Async-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetRecords-Basic-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetRecords-Distributed-KVP">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetRecords-Distributed-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Harvest-Async-KVP">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Harvest-Async-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Harvest-Basic-KVP">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Harvest-Basic-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Harvest-Periodic-KVP">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Harvest-Periodic-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/OpenSearch">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/SupportedGMLVersions">
-      <ows20:AllowedValues>
-        <ows20:Value>http://www.opengis.net/gml</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Transaction">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-  </ows20:OperationsMetadata>
-  <ows20:Languages>
-    <ows20:Language>en</ows20:Language>
-  </ows20:Languages>
-  <fes20:Filter_Capabilities>
-    <fes20:Conformance>
-      <fes20:Constraint name="ImplementsQuery">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsAdHocQuery">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsFunctions">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsResourceld">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsMinStandardFilter">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsStandardFilter">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsMinSpatialFilter">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsSpatialFilter">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsMinTemporalFilter">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsTemporalFilter">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsVersionNav">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsSorting">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsExtendedOperators">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsMinimumXPath">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsSchemaElementFunc">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-    </fes20:Conformance>
-    <fes20:Id_Capabilities>
-      <fes20:ResourceIdentifier name="csw30:id"/>
-    </fes20:Id_Capabilities>
-    <fes20:Scalar_Capabilities>
-      <fes20:LogicalOperators/>
-      <fes20:ComparisonOperators>
-        <fes20:ComparisonOperator name="PropertyIsBetween"/>
-        <fes20:ComparisonOperator name="PropertyIsEqualTo"/>
-        <fes20:ComparisonOperator name="PropertyIsGreaterThan"/>
-        <fes20:ComparisonOperator name="PropertyIsGreaterThanOrEqualTo"/>
-        <fes20:ComparisonOperator name="PropertyIsLessThan"/>
-        <fes20:ComparisonOperator name="PropertyIsLessThanOrEqualTo"/>
-        <fes20:ComparisonOperator name="PropertyIsLike"/>
-        <fes20:ComparisonOperator name="PropertyIsNotEqualTo"/>
-        <fes20:ComparisonOperator name="PropertyIsNull"/>
-      </fes20:ComparisonOperators>
-    </fes20:Scalar_Capabilities>
-    <fes20:Spatial_Capabilities>
-      <fes20:GeometryOperands>
-        <fes20:GeometryOperand name="gml:Point"/>
-        <fes20:GeometryOperand name="gml:LineString"/>
-        <fes20:GeometryOperand name="gml:Polygon"/>
-        <fes20:GeometryOperand name="gml:Envelope"/>
-      </fes20:GeometryOperands>
-      <fes20:SpatialOperators>
-        <fes20:SpatialOperator name="BBOX"/>
-        <fes20:SpatialOperator name="Beyond"/>
-        <fes20:SpatialOperator name="Contains"/>
-        <fes20:SpatialOperator name="Crosses"/>
-        <fes20:SpatialOperator name="Disjoint"/>
-        <fes20:SpatialOperator name="DWithin"/>
-        <fes20:SpatialOperator name="Equals"/>
-        <fes20:SpatialOperator name="Intersects"/>
-        <fes20:SpatialOperator name="Overlaps"/>
-        <fes20:SpatialOperator name="Touches"/>
-        <fes20:SpatialOperator name="Within"/>
-      </fes20:SpatialOperators>
-    </fes20:Spatial_Capabilities>
-    <fes20:Functions>
-      <fes20:Function name="length">
-        <fes20:Returns>xs:string</fes20:Returns>
-      </fes20:Function>
-      <fes20:Function name="lower">
-        <fes20:Returns>xs:string</fes20:Returns>
-      </fes20:Function>
-      <fes20:Function name="ltrim">
-        <fes20:Returns>xs:string</fes20:Returns>
-      </fes20:Function>
-      <fes20:Function name="rtrim">
-        <fes20:Returns>xs:string</fes20:Returns>
-      </fes20:Function>
-      <fes20:Function name="trim">
-        <fes20:Returns>xs:string</fes20:Returns>
-      </fes20:Function>
-      <fes20:Function name="upper">
-        <fes20:Returns>xs:string</fes20:Returns>
-      </fes20:Function>
-    </fes20:Functions>
-  </fes20:Filter_Capabilities>
-</csw30:Capabilities>
diff --git a/tests/expected/suites_csw30_get_c03d173a-3f42-4956-89c8-1fe02c3a0873.xml b/tests/expected/suites_csw30_get_c03d173a-3f42-4956-89c8-1fe02c3a0873.xml
deleted file mode 100644
index c5cb70e..0000000
--- a/tests/expected/suites_csw30_get_c03d173a-3f42-4956-89c8-1fe02c3a0873.xml
+++ /dev/null
@@ -1,493 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- PYCSW_VERSION -->
-<csw30:Capabilities xmlns:csw="http://www.opengis.net/cat/csw/2.0.2" xmlns:csw30="http://www.opengis.net/cat/csw/3.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dct="http://purl.org/dc/terms/" xmlns:fes20="http://www.opengis.net/fes/2.0" xmlns:gmd="http://www.isotc211.org/2005/gmd" xmlns:gml="http://www.opengis.net/gml" xmlns:ows="http://www.opengis.net/ows" xmlns:ows11="http://www.opengis.net/ows/1.1" xmlns:ows20="http://www.opengis.net/ows/2.0" xmlns:xlink="http://www.w3.org/199 [...]
-  <ows20:ServiceIdentification>
-    <ows20:Title>pycsw Geospatial Catalogue</ows20:Title>
-    <ows20:Abstract>pycsw is an OGC CSW server implementation written in Python</ows20:Abstract>
-    <ows20:Keywords>
-      <ows20:Keyword>catalogue</ows20:Keyword>
-      <ows20:Keyword>discovery</ows20:Keyword>
-      <ows20:Type codeSpace="ISOTC211/19115">theme</ows20:Type>
-    </ows20:Keywords>
-    <ows20:ServiceType codeSpace="OGC">CSW</ows20:ServiceType>
-    <ows20:ServiceTypeVersion>2.0.2</ows20:ServiceTypeVersion>
-    <ows20:ServiceTypeVersion>3.0.0</ows20:ServiceTypeVersion>
-    <ows20:Fees>None</ows20:Fees>
-    <ows20:AccessConstraints>None</ows20:AccessConstraints>
-  </ows20:ServiceIdentification>
-  <ows20:ServiceProvider>
-    <ows20:ProviderName>pycsw</ows20:ProviderName>
-    <ows20:ProviderSite xlink:type="simple" xlink:href="http://pycsw.org/"/>
-    <ows20:ServiceContact>
-      <ows20:IndividualName>Kralidis, Tom</ows20:IndividualName>
-      <ows20:PositionName>Senior Systems Scientist</ows20:PositionName>
-      <ows20:ContactInfo>
-        <ows20:Phone>
-          <ows20:Voice>+01-416-xxx-xxxx</ows20:Voice>
-          <ows20:Facsimile>+01-416-xxx-xxxx</ows20:Facsimile>
-        </ows20:Phone>
-        <ows20:Address>
-          <ows20:DeliveryPoint>TBA</ows20:DeliveryPoint>
-          <ows20:City>Toronto</ows20:City>
-          <ows20:AdministrativeArea>Ontario</ows20:AdministrativeArea>
-          <ows20:PostalCode>M9C 3Z9</ows20:PostalCode>
-          <ows20:Country>Canada</ows20:Country>
-          <ows20:ElectronicMailAddress>tomkralidis at gmail.com</ows20:ElectronicMailAddress>
-        </ows20:Address>
-        <ows20:OnlineResource xlink:type="simple" xlink:href="http://kralidis.ca/"/>
-        <ows20:HoursOfService>0800h - 1600h EST</ows20:HoursOfService>
-        <ows20:ContactInstructions>During hours of service.  Off on weekends.</ows20:ContactInstructions>
-      </ows20:ContactInfo>
-      <ows20:Role codeSpace="ISOTC211/19115">pointOfContact</ows20:Role>
-    </ows20:ServiceContact>
-  </ows20:ServiceProvider>
-  <ows20:OperationsMetadata>
-    <ows20:Operation name="GetCapabilities">
-      <ows20:DCP>
-        <ows20:HTTP>
-          <ows20:Get xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-          <ows20:Post xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-        </ows20:HTTP>
-      </ows20:DCP>
-      <ows20:Parameter name="acceptFormats">
-        <ows20:AllowedValues>
-          <ows20:Value>application/xml</ows20:Value>
-          <ows20:Value>text/xml</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="acceptVersions">
-        <ows20:AllowedValues>
-          <ows20:Value>2.0.2</ows20:Value>
-          <ows20:Value>3.0.0</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="sections">
-        <ows20:AllowedValues>
-          <ows20:Value>All</ows20:Value>
-          <ows20:Value>Filter_Capabilities</ows20:Value>
-          <ows20:Value>OperationsMetadata</ows20:Value>
-          <ows20:Value>ServiceIdentification</ows20:Value>
-          <ows20:Value>ServiceProvider</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-    </ows20:Operation>
-    <ows20:Operation name="GetDomain">
-      <ows20:DCP>
-        <ows20:HTTP>
-          <ows20:Get xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-          <ows20:Post xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-        </ows20:HTTP>
-      </ows20:DCP>
-      <ows20:Parameter name="ParameterName">
-        <ows20:AllowedValues>
-          <ows20:Value>GetCapabilities.acceptFormats</ows20:Value>
-          <ows20:Value>GetCapabilities.acceptVersions</ows20:Value>
-          <ows20:Value>GetCapabilities.sections</ows20:Value>
-          <ows20:Value>GetRecordById.ElementSetName</ows20:Value>
-          <ows20:Value>GetRecordById.outputFormat</ows20:Value>
-          <ows20:Value>GetRecordById.outputSchema</ows20:Value>
-          <ows20:Value>GetRecords.CONSTRAINTLANGUAGE</ows20:Value>
-          <ows20:Value>GetRecords.ElementSetName</ows20:Value>
-          <ows20:Value>GetRecords.outputFormat</ows20:Value>
-          <ows20:Value>GetRecords.outputSchema</ows20:Value>
-          <ows20:Value>GetRecords.typeNames</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-    </ows20:Operation>
-    <ows20:Operation name="GetRecords">
-      <ows20:DCP>
-        <ows20:HTTP>
-          <ows20:Get xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-          <ows20:Post xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-        </ows20:HTTP>
-      </ows20:DCP>
-      <ows20:Parameter name="CONSTRAINTLANGUAGE">
-        <ows20:AllowedValues>
-          <ows20:Value>CQL_TEXT</ows20:Value>
-          <ows20:Value>FILTER</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="ElementSetName">
-        <ows20:AllowedValues>
-          <ows20:Value>brief</ows20:Value>
-          <ows20:Value>full</ows20:Value>
-          <ows20:Value>summary</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="outputFormat">
-        <ows20:AllowedValues>
-          <ows20:Value>application/atom+xml</ows20:Value>
-          <ows20:Value>application/json</ows20:Value>
-          <ows20:Value>application/xml</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="outputSchema">
-        <ows20:AllowedValues>
-          <ows20:Value>http://gcmd.gsfc.nasa.gov/Aboutus/xml/dif/</ows20:Value>
-          <ows20:Value>http://www.interlis.ch/INTERLIS2.3</ows20:Value>
-          <ows20:Value>http://www.opengis.net/cat/csw/3.0</ows20:Value>
-          <ows20:Value>http://www.opengis.net/cat/csw/csdgm</ows20:Value>
-          <ows20:Value>http://www.w3.org/2005/Atom</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="typeNames">
-        <ows20:AllowedValues>
-          <ows20:Value>csw:Record</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Constraint name="MaxRecordDefault">
-        <ows20:AllowedValues>
-          <ows20:Value>10</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Constraint>
-      <ows20:Constraint name="OpenSearchDescriptionDocument">
-        <ows20:AllowedValues>
-          <ows20:Value>http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg?mode=opensearch&service=CSW&version=3.0.0&request=GetCapabilities</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Constraint>
-      <ows20:Constraint name="FederatedCatalogues">
-        <ows20:AllowedValues>
-          <ows20:Value>http://demo.pycsw.org/gisdata/csw</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Constraint>
-    </ows20:Operation>
-    <ows20:Operation name="GetRecordById">
-      <ows20:DCP>
-        <ows20:HTTP>
-          <ows20:Get xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-          <ows20:Post xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-        </ows20:HTTP>
-      </ows20:DCP>
-      <ows20:Parameter name="ElementSetName">
-        <ows20:AllowedValues>
-          <ows20:Value>brief</ows20:Value>
-          <ows20:Value>full</ows20:Value>
-          <ows20:Value>summary</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="outputFormat">
-        <ows20:AllowedValues>
-          <ows20:Value>application/atom+xml</ows20:Value>
-          <ows20:Value>application/json</ows20:Value>
-          <ows20:Value>application/xml</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="outputSchema">
-        <ows20:AllowedValues>
-          <ows20:Value>http://gcmd.gsfc.nasa.gov/Aboutus/xml/dif/</ows20:Value>
-          <ows20:Value>http://www.interlis.ch/INTERLIS2.3</ows20:Value>
-          <ows20:Value>http://www.opengis.net/cat/csw/3.0</ows20:Value>
-          <ows20:Value>http://www.opengis.net/cat/csw/csdgm</ows20:Value>
-          <ows20:Value>http://www.w3.org/2005/Atom</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-    </ows20:Operation>
-    <ows20:Operation name="GetRepositoryItem">
-      <ows20:DCP>
-        <ows20:HTTP>
-          <ows20:Get xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-        </ows20:HTTP>
-      </ows20:DCP>
-    </ows20:Operation>
-    <ows20:Parameter name="service">
-      <ows20:AllowedValues>
-        <ows20:Value>CSW</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Parameter>
-    <ows20:Parameter name="version">
-      <ows20:AllowedValues>
-        <ows20:Value>2.0.2</ows20:Value>
-        <ows20:Value>3.0.0</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Parameter>
-    <ows20:Constraint name="CoreQueryables">
-      <ows20:AllowedValues>
-        <ows20:Value>csw:AnyText</ows20:Value>
-        <ows20:Value>dc:contributor</ows20:Value>
-        <ows20:Value>dc:creator</ows20:Value>
-        <ows20:Value>dc:date</ows20:Value>
-        <ows20:Value>dc:format</ows20:Value>
-        <ows20:Value>dc:identifier</ows20:Value>
-        <ows20:Value>dc:language</ows20:Value>
-        <ows20:Value>dc:publisher</ows20:Value>
-        <ows20:Value>dc:relation</ows20:Value>
-        <ows20:Value>dc:rights</ows20:Value>
-        <ows20:Value>dc:source</ows20:Value>
-        <ows20:Value>dc:subject</ows20:Value>
-        <ows20:Value>dc:title</ows20:Value>
-        <ows20:Value>dc:type</ows20:Value>
-        <ows20:Value>dct:abstract</ows20:Value>
-        <ows20:Value>dct:alternative</ows20:Value>
-        <ows20:Value>dct:modified</ows20:Value>
-        <ows20:Value>dct:spatial</ows20:Value>
-        <ows20:Value>ows:BoundingBox</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="FederatedCatalogues">
-      <ows20:AllowedValues>
-        <ows20:Value>http://demo.pycsw.org/gisdata/csw</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="MaxRecordDefault">
-      <ows20:AllowedValues>
-        <ows20:Value>10</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="PostEncoding">
-      <ows20:AllowedValues>
-        <ows20:Value>SOAP</ows20:Value>
-        <ows20:Value>XML</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="XPathQueryables">
-      <ows20:AllowedValues>
-        <ows20:Value>allowed</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/CoreQueryables">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/CoreSortables">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/DefaultSortingAlgorithm">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Filter-CQL">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Filter-FES-KVP-Advanced">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Filter-FES-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetCapabilities-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetDomain-KVP">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetDomain-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetRecordById-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetRecords-Async-KVP">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetRecords-Async-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetRecords-Basic-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetRecords-Distributed-KVP">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetRecords-Distributed-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Harvest-Async-KVP">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Harvest-Async-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Harvest-Basic-KVP">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Harvest-Basic-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Harvest-Periodic-KVP">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Harvest-Periodic-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/OpenSearch">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/SupportedGMLVersions">
-      <ows20:AllowedValues>
-        <ows20:Value>http://www.opengis.net/gml</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Transaction">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-  </ows20:OperationsMetadata>
-  <ows20:Languages>
-    <ows20:Language>en</ows20:Language>
-  </ows20:Languages>
-  <fes20:Filter_Capabilities>
-    <fes20:Conformance>
-      <fes20:Constraint name="ImplementsQuery">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsAdHocQuery">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsFunctions">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsResourceld">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsMinStandardFilter">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsStandardFilter">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsMinSpatialFilter">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsSpatialFilter">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsMinTemporalFilter">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsTemporalFilter">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsVersionNav">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsSorting">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsExtendedOperators">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsMinimumXPath">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsSchemaElementFunc">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-    </fes20:Conformance>
-    <fes20:Id_Capabilities>
-      <fes20:ResourceIdentifier name="csw30:id"/>
-    </fes20:Id_Capabilities>
-    <fes20:Scalar_Capabilities>
-      <fes20:LogicalOperators/>
-      <fes20:ComparisonOperators>
-        <fes20:ComparisonOperator name="PropertyIsBetween"/>
-        <fes20:ComparisonOperator name="PropertyIsEqualTo"/>
-        <fes20:ComparisonOperator name="PropertyIsGreaterThan"/>
-        <fes20:ComparisonOperator name="PropertyIsGreaterThanOrEqualTo"/>
-        <fes20:ComparisonOperator name="PropertyIsLessThan"/>
-        <fes20:ComparisonOperator name="PropertyIsLessThanOrEqualTo"/>
-        <fes20:ComparisonOperator name="PropertyIsLike"/>
-        <fes20:ComparisonOperator name="PropertyIsNotEqualTo"/>
-        <fes20:ComparisonOperator name="PropertyIsNull"/>
-      </fes20:ComparisonOperators>
-    </fes20:Scalar_Capabilities>
-    <fes20:Spatial_Capabilities>
-      <fes20:GeometryOperands>
-        <fes20:GeometryOperand name="gml:Point"/>
-        <fes20:GeometryOperand name="gml:LineString"/>
-        <fes20:GeometryOperand name="gml:Polygon"/>
-        <fes20:GeometryOperand name="gml:Envelope"/>
-      </fes20:GeometryOperands>
-      <fes20:SpatialOperators>
-        <fes20:SpatialOperator name="BBOX"/>
-        <fes20:SpatialOperator name="Beyond"/>
-        <fes20:SpatialOperator name="Contains"/>
-        <fes20:SpatialOperator name="Crosses"/>
-        <fes20:SpatialOperator name="Disjoint"/>
-        <fes20:SpatialOperator name="DWithin"/>
-        <fes20:SpatialOperator name="Equals"/>
-        <fes20:SpatialOperator name="Intersects"/>
-        <fes20:SpatialOperator name="Overlaps"/>
-        <fes20:SpatialOperator name="Touches"/>
-        <fes20:SpatialOperator name="Within"/>
-      </fes20:SpatialOperators>
-    </fes20:Spatial_Capabilities>
-    <fes20:Functions>
-      <fes20:Function name="length">
-        <fes20:Returns>xs:string</fes20:Returns>
-      </fes20:Function>
-      <fes20:Function name="lower">
-        <fes20:Returns>xs:string</fes20:Returns>
-      </fes20:Function>
-      <fes20:Function name="ltrim">
-        <fes20:Returns>xs:string</fes20:Returns>
-      </fes20:Function>
-      <fes20:Function name="rtrim">
-        <fes20:Returns>xs:string</fes20:Returns>
-      </fes20:Function>
-      <fes20:Function name="trim">
-        <fes20:Returns>xs:string</fes20:Returns>
-      </fes20:Function>
-      <fes20:Function name="upper">
-        <fes20:Returns>xs:string</fes20:Returns>
-      </fes20:Function>
-    </fes20:Functions>
-  </fes20:Filter_Capabilities>
-</csw30:Capabilities>
diff --git a/tests/expected/suites_csw30_get_e67ca935-d65d-4d8c-8302-1405333dded0.xml b/tests/expected/suites_csw30_get_e67ca935-d65d-4d8c-8302-1405333dded0.xml
deleted file mode 100644
index c5cb70e..0000000
--- a/tests/expected/suites_csw30_get_e67ca935-d65d-4d8c-8302-1405333dded0.xml
+++ /dev/null
@@ -1,493 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- PYCSW_VERSION -->
-<csw30:Capabilities xmlns:csw="http://www.opengis.net/cat/csw/2.0.2" xmlns:csw30="http://www.opengis.net/cat/csw/3.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dct="http://purl.org/dc/terms/" xmlns:fes20="http://www.opengis.net/fes/2.0" xmlns:gmd="http://www.isotc211.org/2005/gmd" xmlns:gml="http://www.opengis.net/gml" xmlns:ows="http://www.opengis.net/ows" xmlns:ows11="http://www.opengis.net/ows/1.1" xmlns:ows20="http://www.opengis.net/ows/2.0" xmlns:xlink="http://www.w3.org/199 [...]
-  <ows20:ServiceIdentification>
-    <ows20:Title>pycsw Geospatial Catalogue</ows20:Title>
-    <ows20:Abstract>pycsw is an OGC CSW server implementation written in Python</ows20:Abstract>
-    <ows20:Keywords>
-      <ows20:Keyword>catalogue</ows20:Keyword>
-      <ows20:Keyword>discovery</ows20:Keyword>
-      <ows20:Type codeSpace="ISOTC211/19115">theme</ows20:Type>
-    </ows20:Keywords>
-    <ows20:ServiceType codeSpace="OGC">CSW</ows20:ServiceType>
-    <ows20:ServiceTypeVersion>2.0.2</ows20:ServiceTypeVersion>
-    <ows20:ServiceTypeVersion>3.0.0</ows20:ServiceTypeVersion>
-    <ows20:Fees>None</ows20:Fees>
-    <ows20:AccessConstraints>None</ows20:AccessConstraints>
-  </ows20:ServiceIdentification>
-  <ows20:ServiceProvider>
-    <ows20:ProviderName>pycsw</ows20:ProviderName>
-    <ows20:ProviderSite xlink:type="simple" xlink:href="http://pycsw.org/"/>
-    <ows20:ServiceContact>
-      <ows20:IndividualName>Kralidis, Tom</ows20:IndividualName>
-      <ows20:PositionName>Senior Systems Scientist</ows20:PositionName>
-      <ows20:ContactInfo>
-        <ows20:Phone>
-          <ows20:Voice>+01-416-xxx-xxxx</ows20:Voice>
-          <ows20:Facsimile>+01-416-xxx-xxxx</ows20:Facsimile>
-        </ows20:Phone>
-        <ows20:Address>
-          <ows20:DeliveryPoint>TBA</ows20:DeliveryPoint>
-          <ows20:City>Toronto</ows20:City>
-          <ows20:AdministrativeArea>Ontario</ows20:AdministrativeArea>
-          <ows20:PostalCode>M9C 3Z9</ows20:PostalCode>
-          <ows20:Country>Canada</ows20:Country>
-          <ows20:ElectronicMailAddress>tomkralidis at gmail.com</ows20:ElectronicMailAddress>
-        </ows20:Address>
-        <ows20:OnlineResource xlink:type="simple" xlink:href="http://kralidis.ca/"/>
-        <ows20:HoursOfService>0800h - 1600h EST</ows20:HoursOfService>
-        <ows20:ContactInstructions>During hours of service.  Off on weekends.</ows20:ContactInstructions>
-      </ows20:ContactInfo>
-      <ows20:Role codeSpace="ISOTC211/19115">pointOfContact</ows20:Role>
-    </ows20:ServiceContact>
-  </ows20:ServiceProvider>
-  <ows20:OperationsMetadata>
-    <ows20:Operation name="GetCapabilities">
-      <ows20:DCP>
-        <ows20:HTTP>
-          <ows20:Get xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-          <ows20:Post xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-        </ows20:HTTP>
-      </ows20:DCP>
-      <ows20:Parameter name="acceptFormats">
-        <ows20:AllowedValues>
-          <ows20:Value>application/xml</ows20:Value>
-          <ows20:Value>text/xml</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="acceptVersions">
-        <ows20:AllowedValues>
-          <ows20:Value>2.0.2</ows20:Value>
-          <ows20:Value>3.0.0</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="sections">
-        <ows20:AllowedValues>
-          <ows20:Value>All</ows20:Value>
-          <ows20:Value>Filter_Capabilities</ows20:Value>
-          <ows20:Value>OperationsMetadata</ows20:Value>
-          <ows20:Value>ServiceIdentification</ows20:Value>
-          <ows20:Value>ServiceProvider</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-    </ows20:Operation>
-    <ows20:Operation name="GetDomain">
-      <ows20:DCP>
-        <ows20:HTTP>
-          <ows20:Get xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-          <ows20:Post xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-        </ows20:HTTP>
-      </ows20:DCP>
-      <ows20:Parameter name="ParameterName">
-        <ows20:AllowedValues>
-          <ows20:Value>GetCapabilities.acceptFormats</ows20:Value>
-          <ows20:Value>GetCapabilities.acceptVersions</ows20:Value>
-          <ows20:Value>GetCapabilities.sections</ows20:Value>
-          <ows20:Value>GetRecordById.ElementSetName</ows20:Value>
-          <ows20:Value>GetRecordById.outputFormat</ows20:Value>
-          <ows20:Value>GetRecordById.outputSchema</ows20:Value>
-          <ows20:Value>GetRecords.CONSTRAINTLANGUAGE</ows20:Value>
-          <ows20:Value>GetRecords.ElementSetName</ows20:Value>
-          <ows20:Value>GetRecords.outputFormat</ows20:Value>
-          <ows20:Value>GetRecords.outputSchema</ows20:Value>
-          <ows20:Value>GetRecords.typeNames</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-    </ows20:Operation>
-    <ows20:Operation name="GetRecords">
-      <ows20:DCP>
-        <ows20:HTTP>
-          <ows20:Get xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-          <ows20:Post xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-        </ows20:HTTP>
-      </ows20:DCP>
-      <ows20:Parameter name="CONSTRAINTLANGUAGE">
-        <ows20:AllowedValues>
-          <ows20:Value>CQL_TEXT</ows20:Value>
-          <ows20:Value>FILTER</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="ElementSetName">
-        <ows20:AllowedValues>
-          <ows20:Value>brief</ows20:Value>
-          <ows20:Value>full</ows20:Value>
-          <ows20:Value>summary</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="outputFormat">
-        <ows20:AllowedValues>
-          <ows20:Value>application/atom+xml</ows20:Value>
-          <ows20:Value>application/json</ows20:Value>
-          <ows20:Value>application/xml</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="outputSchema">
-        <ows20:AllowedValues>
-          <ows20:Value>http://gcmd.gsfc.nasa.gov/Aboutus/xml/dif/</ows20:Value>
-          <ows20:Value>http://www.interlis.ch/INTERLIS2.3</ows20:Value>
-          <ows20:Value>http://www.opengis.net/cat/csw/3.0</ows20:Value>
-          <ows20:Value>http://www.opengis.net/cat/csw/csdgm</ows20:Value>
-          <ows20:Value>http://www.w3.org/2005/Atom</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="typeNames">
-        <ows20:AllowedValues>
-          <ows20:Value>csw:Record</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Constraint name="MaxRecordDefault">
-        <ows20:AllowedValues>
-          <ows20:Value>10</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Constraint>
-      <ows20:Constraint name="OpenSearchDescriptionDocument">
-        <ows20:AllowedValues>
-          <ows20:Value>http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg?mode=opensearch&service=CSW&version=3.0.0&request=GetCapabilities</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Constraint>
-      <ows20:Constraint name="FederatedCatalogues">
-        <ows20:AllowedValues>
-          <ows20:Value>http://demo.pycsw.org/gisdata/csw</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Constraint>
-    </ows20:Operation>
-    <ows20:Operation name="GetRecordById">
-      <ows20:DCP>
-        <ows20:HTTP>
-          <ows20:Get xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-          <ows20:Post xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-        </ows20:HTTP>
-      </ows20:DCP>
-      <ows20:Parameter name="ElementSetName">
-        <ows20:AllowedValues>
-          <ows20:Value>brief</ows20:Value>
-          <ows20:Value>full</ows20:Value>
-          <ows20:Value>summary</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="outputFormat">
-        <ows20:AllowedValues>
-          <ows20:Value>application/atom+xml</ows20:Value>
-          <ows20:Value>application/json</ows20:Value>
-          <ows20:Value>application/xml</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="outputSchema">
-        <ows20:AllowedValues>
-          <ows20:Value>http://gcmd.gsfc.nasa.gov/Aboutus/xml/dif/</ows20:Value>
-          <ows20:Value>http://www.interlis.ch/INTERLIS2.3</ows20:Value>
-          <ows20:Value>http://www.opengis.net/cat/csw/3.0</ows20:Value>
-          <ows20:Value>http://www.opengis.net/cat/csw/csdgm</ows20:Value>
-          <ows20:Value>http://www.w3.org/2005/Atom</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-    </ows20:Operation>
-    <ows20:Operation name="GetRepositoryItem">
-      <ows20:DCP>
-        <ows20:HTTP>
-          <ows20:Get xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-        </ows20:HTTP>
-      </ows20:DCP>
-    </ows20:Operation>
-    <ows20:Parameter name="service">
-      <ows20:AllowedValues>
-        <ows20:Value>CSW</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Parameter>
-    <ows20:Parameter name="version">
-      <ows20:AllowedValues>
-        <ows20:Value>2.0.2</ows20:Value>
-        <ows20:Value>3.0.0</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Parameter>
-    <ows20:Constraint name="CoreQueryables">
-      <ows20:AllowedValues>
-        <ows20:Value>csw:AnyText</ows20:Value>
-        <ows20:Value>dc:contributor</ows20:Value>
-        <ows20:Value>dc:creator</ows20:Value>
-        <ows20:Value>dc:date</ows20:Value>
-        <ows20:Value>dc:format</ows20:Value>
-        <ows20:Value>dc:identifier</ows20:Value>
-        <ows20:Value>dc:language</ows20:Value>
-        <ows20:Value>dc:publisher</ows20:Value>
-        <ows20:Value>dc:relation</ows20:Value>
-        <ows20:Value>dc:rights</ows20:Value>
-        <ows20:Value>dc:source</ows20:Value>
-        <ows20:Value>dc:subject</ows20:Value>
-        <ows20:Value>dc:title</ows20:Value>
-        <ows20:Value>dc:type</ows20:Value>
-        <ows20:Value>dct:abstract</ows20:Value>
-        <ows20:Value>dct:alternative</ows20:Value>
-        <ows20:Value>dct:modified</ows20:Value>
-        <ows20:Value>dct:spatial</ows20:Value>
-        <ows20:Value>ows:BoundingBox</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="FederatedCatalogues">
-      <ows20:AllowedValues>
-        <ows20:Value>http://demo.pycsw.org/gisdata/csw</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="MaxRecordDefault">
-      <ows20:AllowedValues>
-        <ows20:Value>10</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="PostEncoding">
-      <ows20:AllowedValues>
-        <ows20:Value>SOAP</ows20:Value>
-        <ows20:Value>XML</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="XPathQueryables">
-      <ows20:AllowedValues>
-        <ows20:Value>allowed</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/CoreQueryables">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/CoreSortables">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/DefaultSortingAlgorithm">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Filter-CQL">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Filter-FES-KVP-Advanced">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Filter-FES-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetCapabilities-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetDomain-KVP">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetDomain-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetRecordById-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetRecords-Async-KVP">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetRecords-Async-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetRecords-Basic-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetRecords-Distributed-KVP">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetRecords-Distributed-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Harvest-Async-KVP">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Harvest-Async-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Harvest-Basic-KVP">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Harvest-Basic-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Harvest-Periodic-KVP">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Harvest-Periodic-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/OpenSearch">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/SupportedGMLVersions">
-      <ows20:AllowedValues>
-        <ows20:Value>http://www.opengis.net/gml</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Transaction">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-  </ows20:OperationsMetadata>
-  <ows20:Languages>
-    <ows20:Language>en</ows20:Language>
-  </ows20:Languages>
-  <fes20:Filter_Capabilities>
-    <fes20:Conformance>
-      <fes20:Constraint name="ImplementsQuery">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsAdHocQuery">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsFunctions">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsResourceld">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsMinStandardFilter">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsStandardFilter">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsMinSpatialFilter">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsSpatialFilter">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsMinTemporalFilter">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsTemporalFilter">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsVersionNav">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsSorting">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsExtendedOperators">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsMinimumXPath">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsSchemaElementFunc">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-    </fes20:Conformance>
-    <fes20:Id_Capabilities>
-      <fes20:ResourceIdentifier name="csw30:id"/>
-    </fes20:Id_Capabilities>
-    <fes20:Scalar_Capabilities>
-      <fes20:LogicalOperators/>
-      <fes20:ComparisonOperators>
-        <fes20:ComparisonOperator name="PropertyIsBetween"/>
-        <fes20:ComparisonOperator name="PropertyIsEqualTo"/>
-        <fes20:ComparisonOperator name="PropertyIsGreaterThan"/>
-        <fes20:ComparisonOperator name="PropertyIsGreaterThanOrEqualTo"/>
-        <fes20:ComparisonOperator name="PropertyIsLessThan"/>
-        <fes20:ComparisonOperator name="PropertyIsLessThanOrEqualTo"/>
-        <fes20:ComparisonOperator name="PropertyIsLike"/>
-        <fes20:ComparisonOperator name="PropertyIsNotEqualTo"/>
-        <fes20:ComparisonOperator name="PropertyIsNull"/>
-      </fes20:ComparisonOperators>
-    </fes20:Scalar_Capabilities>
-    <fes20:Spatial_Capabilities>
-      <fes20:GeometryOperands>
-        <fes20:GeometryOperand name="gml:Point"/>
-        <fes20:GeometryOperand name="gml:LineString"/>
-        <fes20:GeometryOperand name="gml:Polygon"/>
-        <fes20:GeometryOperand name="gml:Envelope"/>
-      </fes20:GeometryOperands>
-      <fes20:SpatialOperators>
-        <fes20:SpatialOperator name="BBOX"/>
-        <fes20:SpatialOperator name="Beyond"/>
-        <fes20:SpatialOperator name="Contains"/>
-        <fes20:SpatialOperator name="Crosses"/>
-        <fes20:SpatialOperator name="Disjoint"/>
-        <fes20:SpatialOperator name="DWithin"/>
-        <fes20:SpatialOperator name="Equals"/>
-        <fes20:SpatialOperator name="Intersects"/>
-        <fes20:SpatialOperator name="Overlaps"/>
-        <fes20:SpatialOperator name="Touches"/>
-        <fes20:SpatialOperator name="Within"/>
-      </fes20:SpatialOperators>
-    </fes20:Spatial_Capabilities>
-    <fes20:Functions>
-      <fes20:Function name="length">
-        <fes20:Returns>xs:string</fes20:Returns>
-      </fes20:Function>
-      <fes20:Function name="lower">
-        <fes20:Returns>xs:string</fes20:Returns>
-      </fes20:Function>
-      <fes20:Function name="ltrim">
-        <fes20:Returns>xs:string</fes20:Returns>
-      </fes20:Function>
-      <fes20:Function name="rtrim">
-        <fes20:Returns>xs:string</fes20:Returns>
-      </fes20:Function>
-      <fes20:Function name="trim">
-        <fes20:Returns>xs:string</fes20:Returns>
-      </fes20:Function>
-      <fes20:Function name="upper">
-        <fes20:Returns>xs:string</fes20:Returns>
-      </fes20:Function>
-    </fes20:Functions>
-  </fes20:Filter_Capabilities>
-</csw30:Capabilities>
diff --git a/tests/expected/suites_csw30_post_GetCapabilities.xml b/tests/expected/suites_csw30_post_GetCapabilities.xml
deleted file mode 100644
index c5cb70e..0000000
--- a/tests/expected/suites_csw30_post_GetCapabilities.xml
+++ /dev/null
@@ -1,493 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- PYCSW_VERSION -->
-<csw30:Capabilities xmlns:csw="http://www.opengis.net/cat/csw/2.0.2" xmlns:csw30="http://www.opengis.net/cat/csw/3.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dct="http://purl.org/dc/terms/" xmlns:fes20="http://www.opengis.net/fes/2.0" xmlns:gmd="http://www.isotc211.org/2005/gmd" xmlns:gml="http://www.opengis.net/gml" xmlns:ows="http://www.opengis.net/ows" xmlns:ows11="http://www.opengis.net/ows/1.1" xmlns:ows20="http://www.opengis.net/ows/2.0" xmlns:xlink="http://www.w3.org/199 [...]
-  <ows20:ServiceIdentification>
-    <ows20:Title>pycsw Geospatial Catalogue</ows20:Title>
-    <ows20:Abstract>pycsw is an OGC CSW server implementation written in Python</ows20:Abstract>
-    <ows20:Keywords>
-      <ows20:Keyword>catalogue</ows20:Keyword>
-      <ows20:Keyword>discovery</ows20:Keyword>
-      <ows20:Type codeSpace="ISOTC211/19115">theme</ows20:Type>
-    </ows20:Keywords>
-    <ows20:ServiceType codeSpace="OGC">CSW</ows20:ServiceType>
-    <ows20:ServiceTypeVersion>2.0.2</ows20:ServiceTypeVersion>
-    <ows20:ServiceTypeVersion>3.0.0</ows20:ServiceTypeVersion>
-    <ows20:Fees>None</ows20:Fees>
-    <ows20:AccessConstraints>None</ows20:AccessConstraints>
-  </ows20:ServiceIdentification>
-  <ows20:ServiceProvider>
-    <ows20:ProviderName>pycsw</ows20:ProviderName>
-    <ows20:ProviderSite xlink:type="simple" xlink:href="http://pycsw.org/"/>
-    <ows20:ServiceContact>
-      <ows20:IndividualName>Kralidis, Tom</ows20:IndividualName>
-      <ows20:PositionName>Senior Systems Scientist</ows20:PositionName>
-      <ows20:ContactInfo>
-        <ows20:Phone>
-          <ows20:Voice>+01-416-xxx-xxxx</ows20:Voice>
-          <ows20:Facsimile>+01-416-xxx-xxxx</ows20:Facsimile>
-        </ows20:Phone>
-        <ows20:Address>
-          <ows20:DeliveryPoint>TBA</ows20:DeliveryPoint>
-          <ows20:City>Toronto</ows20:City>
-          <ows20:AdministrativeArea>Ontario</ows20:AdministrativeArea>
-          <ows20:PostalCode>M9C 3Z9</ows20:PostalCode>
-          <ows20:Country>Canada</ows20:Country>
-          <ows20:ElectronicMailAddress>tomkralidis at gmail.com</ows20:ElectronicMailAddress>
-        </ows20:Address>
-        <ows20:OnlineResource xlink:type="simple" xlink:href="http://kralidis.ca/"/>
-        <ows20:HoursOfService>0800h - 1600h EST</ows20:HoursOfService>
-        <ows20:ContactInstructions>During hours of service.  Off on weekends.</ows20:ContactInstructions>
-      </ows20:ContactInfo>
-      <ows20:Role codeSpace="ISOTC211/19115">pointOfContact</ows20:Role>
-    </ows20:ServiceContact>
-  </ows20:ServiceProvider>
-  <ows20:OperationsMetadata>
-    <ows20:Operation name="GetCapabilities">
-      <ows20:DCP>
-        <ows20:HTTP>
-          <ows20:Get xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-          <ows20:Post xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-        </ows20:HTTP>
-      </ows20:DCP>
-      <ows20:Parameter name="acceptFormats">
-        <ows20:AllowedValues>
-          <ows20:Value>application/xml</ows20:Value>
-          <ows20:Value>text/xml</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="acceptVersions">
-        <ows20:AllowedValues>
-          <ows20:Value>2.0.2</ows20:Value>
-          <ows20:Value>3.0.0</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="sections">
-        <ows20:AllowedValues>
-          <ows20:Value>All</ows20:Value>
-          <ows20:Value>Filter_Capabilities</ows20:Value>
-          <ows20:Value>OperationsMetadata</ows20:Value>
-          <ows20:Value>ServiceIdentification</ows20:Value>
-          <ows20:Value>ServiceProvider</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-    </ows20:Operation>
-    <ows20:Operation name="GetDomain">
-      <ows20:DCP>
-        <ows20:HTTP>
-          <ows20:Get xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-          <ows20:Post xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-        </ows20:HTTP>
-      </ows20:DCP>
-      <ows20:Parameter name="ParameterName">
-        <ows20:AllowedValues>
-          <ows20:Value>GetCapabilities.acceptFormats</ows20:Value>
-          <ows20:Value>GetCapabilities.acceptVersions</ows20:Value>
-          <ows20:Value>GetCapabilities.sections</ows20:Value>
-          <ows20:Value>GetRecordById.ElementSetName</ows20:Value>
-          <ows20:Value>GetRecordById.outputFormat</ows20:Value>
-          <ows20:Value>GetRecordById.outputSchema</ows20:Value>
-          <ows20:Value>GetRecords.CONSTRAINTLANGUAGE</ows20:Value>
-          <ows20:Value>GetRecords.ElementSetName</ows20:Value>
-          <ows20:Value>GetRecords.outputFormat</ows20:Value>
-          <ows20:Value>GetRecords.outputSchema</ows20:Value>
-          <ows20:Value>GetRecords.typeNames</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-    </ows20:Operation>
-    <ows20:Operation name="GetRecords">
-      <ows20:DCP>
-        <ows20:HTTP>
-          <ows20:Get xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-          <ows20:Post xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-        </ows20:HTTP>
-      </ows20:DCP>
-      <ows20:Parameter name="CONSTRAINTLANGUAGE">
-        <ows20:AllowedValues>
-          <ows20:Value>CQL_TEXT</ows20:Value>
-          <ows20:Value>FILTER</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="ElementSetName">
-        <ows20:AllowedValues>
-          <ows20:Value>brief</ows20:Value>
-          <ows20:Value>full</ows20:Value>
-          <ows20:Value>summary</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="outputFormat">
-        <ows20:AllowedValues>
-          <ows20:Value>application/atom+xml</ows20:Value>
-          <ows20:Value>application/json</ows20:Value>
-          <ows20:Value>application/xml</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="outputSchema">
-        <ows20:AllowedValues>
-          <ows20:Value>http://gcmd.gsfc.nasa.gov/Aboutus/xml/dif/</ows20:Value>
-          <ows20:Value>http://www.interlis.ch/INTERLIS2.3</ows20:Value>
-          <ows20:Value>http://www.opengis.net/cat/csw/3.0</ows20:Value>
-          <ows20:Value>http://www.opengis.net/cat/csw/csdgm</ows20:Value>
-          <ows20:Value>http://www.w3.org/2005/Atom</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="typeNames">
-        <ows20:AllowedValues>
-          <ows20:Value>csw:Record</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Constraint name="MaxRecordDefault">
-        <ows20:AllowedValues>
-          <ows20:Value>10</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Constraint>
-      <ows20:Constraint name="OpenSearchDescriptionDocument">
-        <ows20:AllowedValues>
-          <ows20:Value>http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg?mode=opensearch&service=CSW&version=3.0.0&request=GetCapabilities</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Constraint>
-      <ows20:Constraint name="FederatedCatalogues">
-        <ows20:AllowedValues>
-          <ows20:Value>http://demo.pycsw.org/gisdata/csw</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Constraint>
-    </ows20:Operation>
-    <ows20:Operation name="GetRecordById">
-      <ows20:DCP>
-        <ows20:HTTP>
-          <ows20:Get xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-          <ows20:Post xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-        </ows20:HTTP>
-      </ows20:DCP>
-      <ows20:Parameter name="ElementSetName">
-        <ows20:AllowedValues>
-          <ows20:Value>brief</ows20:Value>
-          <ows20:Value>full</ows20:Value>
-          <ows20:Value>summary</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="outputFormat">
-        <ows20:AllowedValues>
-          <ows20:Value>application/atom+xml</ows20:Value>
-          <ows20:Value>application/json</ows20:Value>
-          <ows20:Value>application/xml</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-      <ows20:Parameter name="outputSchema">
-        <ows20:AllowedValues>
-          <ows20:Value>http://gcmd.gsfc.nasa.gov/Aboutus/xml/dif/</ows20:Value>
-          <ows20:Value>http://www.interlis.ch/INTERLIS2.3</ows20:Value>
-          <ows20:Value>http://www.opengis.net/cat/csw/3.0</ows20:Value>
-          <ows20:Value>http://www.opengis.net/cat/csw/csdgm</ows20:Value>
-          <ows20:Value>http://www.w3.org/2005/Atom</ows20:Value>
-        </ows20:AllowedValues>
-      </ows20:Parameter>
-    </ows20:Operation>
-    <ows20:Operation name="GetRepositoryItem">
-      <ows20:DCP>
-        <ows20:HTTP>
-          <ows20:Get xlink:type="simple" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/csw30/default.cfg"/>
-        </ows20:HTTP>
-      </ows20:DCP>
-    </ows20:Operation>
-    <ows20:Parameter name="service">
-      <ows20:AllowedValues>
-        <ows20:Value>CSW</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Parameter>
-    <ows20:Parameter name="version">
-      <ows20:AllowedValues>
-        <ows20:Value>2.0.2</ows20:Value>
-        <ows20:Value>3.0.0</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Parameter>
-    <ows20:Constraint name="CoreQueryables">
-      <ows20:AllowedValues>
-        <ows20:Value>csw:AnyText</ows20:Value>
-        <ows20:Value>dc:contributor</ows20:Value>
-        <ows20:Value>dc:creator</ows20:Value>
-        <ows20:Value>dc:date</ows20:Value>
-        <ows20:Value>dc:format</ows20:Value>
-        <ows20:Value>dc:identifier</ows20:Value>
-        <ows20:Value>dc:language</ows20:Value>
-        <ows20:Value>dc:publisher</ows20:Value>
-        <ows20:Value>dc:relation</ows20:Value>
-        <ows20:Value>dc:rights</ows20:Value>
-        <ows20:Value>dc:source</ows20:Value>
-        <ows20:Value>dc:subject</ows20:Value>
-        <ows20:Value>dc:title</ows20:Value>
-        <ows20:Value>dc:type</ows20:Value>
-        <ows20:Value>dct:abstract</ows20:Value>
-        <ows20:Value>dct:alternative</ows20:Value>
-        <ows20:Value>dct:modified</ows20:Value>
-        <ows20:Value>dct:spatial</ows20:Value>
-        <ows20:Value>ows:BoundingBox</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="FederatedCatalogues">
-      <ows20:AllowedValues>
-        <ows20:Value>http://demo.pycsw.org/gisdata/csw</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="MaxRecordDefault">
-      <ows20:AllowedValues>
-        <ows20:Value>10</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="PostEncoding">
-      <ows20:AllowedValues>
-        <ows20:Value>SOAP</ows20:Value>
-        <ows20:Value>XML</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="XPathQueryables">
-      <ows20:AllowedValues>
-        <ows20:Value>allowed</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/CoreQueryables">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/CoreSortables">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/DefaultSortingAlgorithm">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Filter-CQL">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Filter-FES-KVP-Advanced">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Filter-FES-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetCapabilities-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetDomain-KVP">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetDomain-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetRecordById-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetRecords-Async-KVP">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetRecords-Async-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetRecords-Basic-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetRecords-Distributed-KVP">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/GetRecords-Distributed-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Harvest-Async-KVP">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Harvest-Async-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Harvest-Basic-KVP">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Harvest-Basic-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Harvest-Periodic-KVP">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Harvest-Periodic-XML">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/OpenSearch">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/SupportedGMLVersions">
-      <ows20:AllowedValues>
-        <ows20:Value>http://www.opengis.net/gml</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-    <ows20:Constraint name="http://www.opengis.net/spec/csw/3.0/conf/Transaction">
-      <ows20:AllowedValues>
-        <ows20:Value>TRUE</ows20:Value>
-      </ows20:AllowedValues>
-    </ows20:Constraint>
-  </ows20:OperationsMetadata>
-  <ows20:Languages>
-    <ows20:Language>en</ows20:Language>
-  </ows20:Languages>
-  <fes20:Filter_Capabilities>
-    <fes20:Conformance>
-      <fes20:Constraint name="ImplementsQuery">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsAdHocQuery">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsFunctions">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsResourceld">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsMinStandardFilter">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsStandardFilter">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsMinSpatialFilter">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsSpatialFilter">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsMinTemporalFilter">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsTemporalFilter">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsVersionNav">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsSorting">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsExtendedOperators">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsMinimumXPath">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-      <fes20:Constraint name="ImplementsSchemaElementFunc">
-        <ows11:NoValues/>
-        <ows11:DefaultValue>TRUE</ows11:DefaultValue>
-      </fes20:Constraint>
-    </fes20:Conformance>
-    <fes20:Id_Capabilities>
-      <fes20:ResourceIdentifier name="csw30:id"/>
-    </fes20:Id_Capabilities>
-    <fes20:Scalar_Capabilities>
-      <fes20:LogicalOperators/>
-      <fes20:ComparisonOperators>
-        <fes20:ComparisonOperator name="PropertyIsBetween"/>
-        <fes20:ComparisonOperator name="PropertyIsEqualTo"/>
-        <fes20:ComparisonOperator name="PropertyIsGreaterThan"/>
-        <fes20:ComparisonOperator name="PropertyIsGreaterThanOrEqualTo"/>
-        <fes20:ComparisonOperator name="PropertyIsLessThan"/>
-        <fes20:ComparisonOperator name="PropertyIsLessThanOrEqualTo"/>
-        <fes20:ComparisonOperator name="PropertyIsLike"/>
-        <fes20:ComparisonOperator name="PropertyIsNotEqualTo"/>
-        <fes20:ComparisonOperator name="PropertyIsNull"/>
-      </fes20:ComparisonOperators>
-    </fes20:Scalar_Capabilities>
-    <fes20:Spatial_Capabilities>
-      <fes20:GeometryOperands>
-        <fes20:GeometryOperand name="gml:Point"/>
-        <fes20:GeometryOperand name="gml:LineString"/>
-        <fes20:GeometryOperand name="gml:Polygon"/>
-        <fes20:GeometryOperand name="gml:Envelope"/>
-      </fes20:GeometryOperands>
-      <fes20:SpatialOperators>
-        <fes20:SpatialOperator name="BBOX"/>
-        <fes20:SpatialOperator name="Beyond"/>
-        <fes20:SpatialOperator name="Contains"/>
-        <fes20:SpatialOperator name="Crosses"/>
-        <fes20:SpatialOperator name="Disjoint"/>
-        <fes20:SpatialOperator name="DWithin"/>
-        <fes20:SpatialOperator name="Equals"/>
-        <fes20:SpatialOperator name="Intersects"/>
-        <fes20:SpatialOperator name="Overlaps"/>
-        <fes20:SpatialOperator name="Touches"/>
-        <fes20:SpatialOperator name="Within"/>
-      </fes20:SpatialOperators>
-    </fes20:Spatial_Capabilities>
-    <fes20:Functions>
-      <fes20:Function name="length">
-        <fes20:Returns>xs:string</fes20:Returns>
-      </fes20:Function>
-      <fes20:Function name="lower">
-        <fes20:Returns>xs:string</fes20:Returns>
-      </fes20:Function>
-      <fes20:Function name="ltrim">
-        <fes20:Returns>xs:string</fes20:Returns>
-      </fes20:Function>
-      <fes20:Function name="rtrim">
-        <fes20:Returns>xs:string</fes20:Returns>
-      </fes20:Function>
-      <fes20:Function name="trim">
-        <fes20:Returns>xs:string</fes20:Returns>
-      </fes20:Function>
-      <fes20:Function name="upper">
-        <fes20:Returns>xs:string</fes20:Returns>
-      </fes20:Function>
-    </fes20:Functions>
-  </fes20:Filter_Capabilities>
-</csw30:Capabilities>
diff --git a/tests/expected/suites_default_post_Exception-GetRecords-badsrsname.xml b/tests/expected/suites_default_post_Exception-GetRecords-badsrsname.xml
deleted file mode 100644
index fe0c923..0000000
--- a/tests/expected/suites_default_post_Exception-GetRecords-badsrsname.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- PYCSW_VERSION -->
-<ows:ExceptionReport xmlns:csw="http://www.opengis.net/cat/csw/2.0.2" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dct="http://purl.org/dc/terms/" xmlns:gmd="http://www.isotc211.org/2005/gmd" xmlns:gml="http://www.opengis.net/gml" xmlns:ows="http://www.opengis.net/ows" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" language="en-US" version="1.2.0" xsi:schemaLocation="http://www.opengis.net/ows http://schemas.opengis.net/ows/1.0.0/ow [...]
-  <ows:Exception exceptionCode="InvalidParameterValue" locator="service">
-    <ows:ExceptionText>Invalid Constraint: Invalid Filter request: Reprojection error: Invalid srsName "EPSG:226": Invalid source projection</ows:ExceptionText>
-  </ows:Exception>
-</ows:ExceptionReport>
diff --git a/tests/expected/suites_harvesting_post_Harvest-wmts.xml b/tests/expected/suites_harvesting_post_Harvest-wmts.xml
deleted file mode 100644
index 3bd0bd4..0000000
--- a/tests/expected/suites_harvesting_post_Harvest-wmts.xml
+++ /dev/null
@@ -1,1517 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- PYCSW_VERSION -->
-<csw:HarvestResponse xmlns:csw="http://www.opengis.net/cat/csw/2.0.2" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dct="http://purl.org/dc/terms/" xmlns:gmd="http://www.isotc211.org/2005/gmd" xmlns:gml="http://www.opengis.net/gml" xmlns:ows="http://www.opengis.net/ows" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/cat/csw/2.0.2 http://schemas.opengis.net/csw/2.0.2/CSW-publication.xsd">
-  <csw:TransactionResponse version="2.0.2">
-    <csw:TransactionSummary>
-      <csw:totalInserted>376</csw:totalInserted>
-      <csw:totalUpdated>0</csw:totalUpdated>
-      <csw:totalDeleted>0</csw:totalDeleted>
-    </csw:TransactionSummary>
-    <csw:InsertResult>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER</dc:identifier>
-        <dc:title>NASA Global Imagery Browse Services for EOSDIS</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-VIIRS_SNPP_CorrectedReflectance_BandsM3-I3-M11</dc:identifier>
-        <dc:title>Corrected Reflectance (M3-I3-M11, VIIRS, SNPP)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MISR_Radiance_Average_Infrared_Color_Monthly</dc:identifier>
-        <dc:title>Radiance Average (AN, Infrared Color, Monthly, MISR, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SSMI_DMSP_F14_Water_Vapor_Over_Oceans_Descending</dc:identifier>
-        <dc:title>Water Vapor (Descending, Local AM, DMSP-F14 / SSMI)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-CERES_Combined_TOA_Window_Region_Flux_All_Sky_Monthly</dc:identifier>
-        <dc:title>TOA Window-Region Flux All-Sky (Monthly, CERES, Aqua+Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SMAP_L3_Passive_Soil_Moisture</dc:identifier>
-        <dc:title>Soil Moisture (L3, Passive, Radiometer, SMAP)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Terra_Cloud_Fraction_Night</dc:identifier>
-        <dc:title>Cloud Fraction (Night, MODIS, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SMAP_L3_Active_Sigma0_HH_RFI</dc:identifier>
-        <dc:title>Sigma0 RFI (L3, Active, HH Polarization, Radar, SMAP)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MLS_HNO3_46hPa_Night</dc:identifier>
-        <dc:title>Nitric Acid (46 hPa, Night, MLS, Aura)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-AIRS_Temperature_700hPa_Night</dc:identifier>
-        <dc:title>Air Temperature (700 hPa, Night, AIRS, Aqua)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-AIRS_RelativeHumidity_500hPa_Night</dc:identifier>
-        <dc:title>Relative Humidity (500 hPa, Night, AIRS, Aqua)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-GMI_Rain_Rate_Dsc</dc:identifier>
-        <dc:title>Rain Rate (Descending, GMI, GPM)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MOPITT_CO_Monthly_Surface_Mixing_Ratio_Night</dc:identifier>
-        <dc:title>Carbon Monoxide (Monthly, Night, Surface Mixing Ratio, MOPITT, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Terra_Brightness_Temp_Band31_Day</dc:identifier>
-        <dc:title>Brightness Temperature (Band31, Day, MODIS, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-Coastlines</dc:identifier>
-        <dc:title>Coastlines (OSM)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-OMI_SO2_Middle_Troposphere</dc:identifier>
-        <dc:title>Sulfur Dioxide (Middle Troposphere, OMI, Aura)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SMAP_L3_Active_Sigma0_VV</dc:identifier>
-        <dc:title>Sigma0 (L3, Active, VV Polarization, Radar, SMAP)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-GHRSST_L4_MUR_Sea_Surface_Temperature</dc:identifier>
-        <dc:title>Sea Surface Temperature (L4, MUR Global Foundation, GHRSST)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Aqua_Cloud_Top_Temp_Day</dc:identifier>
-        <dc:title>Cloud Top Temperature (Day, MODIS, Aqua)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SSMI_DMSP_F13_Cloud_Liquid_Water_Over_Oceans_Descending</dc:identifier>
-        <dc:title>Cloud Liquid Water (Descending, Local AM, DMSP-F13 / SSMI)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SMAP_L3_Active_Sigma0_VV_RFI</dc:identifier>
-        <dc:title>Sigma0 RFI (L3, Active, VV Polarization, Radar, SMAP)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Aqua_SurfaceReflectance_Bands143</dc:identifier>
-        <dc:title>Land Surface Reflectance (True Color, MODIS, Aqua)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-Reference_Labels</dc:identifier>
-        <dc:title>Reference Labels (OSM)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-CERES_EBAF_Surface_Net_Total_Flux_All_Sky_Monthly</dc:identifier>
-        <dc:title>Surface Net Total Flux (Monthly, All-Sky, CERES, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MLS_O3_46hPa_Day</dc:identifier>
-        <dc:title>Ozone (46 hPa, Day, MLS, Aura)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MLS_Temperature_46hPa_Day</dc:identifier>
-        <dc:title>Air Temperature (46 hPa, Day, MLS, Aura)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SSMI_DMSP_F14_Water_Vapor_Over_Oceans_Ascending</dc:identifier>
-        <dc:title>Water Vapor (Ascending, Local PM, DMSP-F14 / SSMI)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Terra_CorrectedReflectance_Bands721</dc:identifier>
-        <dc:title>Corrected Reflectance (Bands 7-2-1, MODIS, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Aqua_Brightness_Temp_Band31_Day</dc:identifier>
-        <dc:title>Brightness Temperature (Band31, Day, MODIS, Aqua)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Aqua_Land_Surface_Temp_Day</dc:identifier>
-        <dc:title>Land Surface Temperature (Day, MODIS, Aqua)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Aqua_Chlorophyll_A</dc:identifier>
-        <dc:title>Chlorophyll (MODIS, Aqua)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Aqua_Cloud_Phase_Infrared_Night</dc:identifier>
-        <dc:title>Cloud Phase (Infrared, Night, MODIS, Aqua)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SSMI_DMSP_F8_Cloud_Liquid_Water_Over_Oceans_Descending</dc:identifier>
-        <dc:title>Cloud Liquid Water (Descending, Local PM, DMSP-F8 / SSMI)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SSMI_DMSP_F11_Water_Vapor_Over_Oceans_Ascending</dc:identifier>
-        <dc:title>Water Vapor (Ascending, Local PM, DMSP-F11 / SSMI)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-CERES_Combined_TOA_Longwave_Flux_All_Sky_Monthly</dc:identifier>
-        <dc:title>TOA Longwave Flux All-Sky (Monthly, CERES, Aqua+Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SSMI_DMSP_F8_Rain_Rate_Over_Oceans_Descending</dc:identifier>
-        <dc:title>Rain Rate (Descending, DMSP-F8 / SSMI)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Aqua_AOD_Deep_Blue_Land</dc:identifier>
-        <dc:title>Deep Blue Aerosol Optical Depth (Land, MODIS, Aqua)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SSMI_DMSP_F10_Water_Vapor_Over_Oceans_Ascending</dc:identifier>
-        <dc:title>Water Vapor (Ascending, Local PM, DMSP-F10 / SSMI)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Aqua_Cloud_Optical_Thickness_PCL</dc:identifier>
-        <dc:title>Cloud Optical Thickness (PCL, MODIS, Aqua)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-AIRS_Prata_SO2_Index_Night</dc:identifier>
-        <dc:title>Sulfur Dioxide (Prata, Night, AIRS, Aqua)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-CERES_EBAF_TOA_Net_Flux_Clear_Sky_Monthly</dc:identifier>
-        <dc:title>TOA Net Flux (Monthly, Clear-Sky, CERES, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-AMSRE_Sea_Ice_Concentration_12km</dc:identifier>
-        <dc:title>Sea Ice Concentration (12 km, AMSR-E, Aqua)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Aqua_CorrectedReflectance_Bands721</dc:identifier>
-        <dc:title>Corrected Reflectance (Bands 7-2-1, MODIS, Aqua)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-AIRS_RelativeHumidity_500hPa_Day</dc:identifier>
-        <dc:title>Relative Humidity (500 hPa, Day, AIRS, Aqua)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-CERES_EBAF_Surface_Net_Longwave_Flux_Clear_Sky_Monthly</dc:identifier>
-        <dc:title>Surface Net Longwave Flux (Monthly, Clear-Sky, CERES, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SSMI_DMSP_F17_Cloud_Liquid_Water_Over_Oceans_Descending</dc:identifier>
-        <dc:title>Cloud Liquid Water (Descending, Local AM, DMSP-F17 / SSMIS)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SMAP_L3_Active_Sigma0_HH_QA</dc:identifier>
-        <dc:title>Sigma0 QA (L3, Active, HH Polarization, Radar, SMAP)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Terra_Cloud_Phase_Infrared_Day</dc:identifier>
-        <dc:title>Cloud Phase (Infrared, Day, MODIS, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MISR_Cloud_Stereo_Height_Histogram_Bin_0.5km_Monthly</dc:identifier>
-        <dc:title>Cloud Stereo Height (No Wind Correction, < 0.5 km, Monthly, MISR)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MISR_Cloud_Stereo_Height_Histogram_Bin_1.5-2.0km_Monthly</dc:identifier>
-        <dc:title>Cloud Stereo Height (No Wind Correction, 1.5 - 2.0 km, Monthly, MISR)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SSMI_DMSP_F16_Rain_Rate_Over_Oceans_Ascending</dc:identifier>
-        <dc:title>Rain Rate (Ascending, DMSP-F16 / SSMIS)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-AMSR2_Surface_Rain_Rate_Day</dc:identifier>
-        <dc:title>Surface Rain Rate (Day, AMSR2, GCOM-W1)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SSMI_DMSP_F17_Rain_Rate_Over_Oceans_Ascending</dc:identifier>
-        <dc:title>Rain Rate (Ascending, DMSP-F17 / SSMIS)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-AIRS_RelativeHumidity_850hPa_Night</dc:identifier>
-        <dc:title>Relative Humidity (850 hPa, Night, AIRS, Aqua)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Terra_Cloud_Phase_Infrared_Night</dc:identifier>
-        <dc:title>Cloud Phase (Infrared, Night, MODIS, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SSMI_DMSP_F8_Water_Vapor_Over_Oceans_Descending</dc:identifier>
-        <dc:title>Water Vapor (Descending, Local PM, DMSP-F8 / SSMI)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-GMI_Snow_Rate_Asc</dc:identifier>
-        <dc:title>Snow Rate (Ascending, GMI, GPM)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SSMI_DMSP_F10_Rain_Rate_Over_Oceans_Descending</dc:identifier>
-        <dc:title>Rain Rate (Descending, DMSP-F10 / SSMI)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-CERES_EBAF_Surface_Longwave_Flux_Up_All_Sky_Monthly</dc:identifier>
-        <dc:title>Surface Longwave Flux (Monthly, Up, All-Sky, CERES, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Terra_Aerosol</dc:identifier>
-        <dc:title>Dark Target Aerosol Optical Depth (Land and Ocean, MODIS, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-AMSR2_Surface_Precipitation_Rate_Night</dc:identifier>
-        <dc:title>Surface Precipitation Rate (Night, AMSR2, GCOM-W1)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-CERES_Terra_TOA_Shortwave_Flux_All_Sky_Monthly</dc:identifier>
-        <dc:title>TOA Shortwave Flux All-Sky (Monthly, CERES, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Aqua_Cloud_Top_Height_Night</dc:identifier>
-        <dc:title>Cloud Top Height (Night, MODIS, Aqua)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-CERES_Terra_TOA_Shortwave_Flux_Clear_Sky_Monthly</dc:identifier>
-        <dc:title>TOA Shortwave Flux Clear-Sky (Monthly, CERES, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Aqua_Cloud_Multi_Layer_Flag</dc:identifier>
-        <dc:title>Cloud Multi Layer Flag (MODIS, Aqua)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-AIRS_RelativeHumidity_700hPa_Day</dc:identifier>
-        <dc:title>Relative Humidity (700 hPa, Day, AIRS, Aqua)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-CERES_EBAF_TOA_CRE_Longwave_Flux_Monthly</dc:identifier>
-        <dc:title>TOA CRE Longwave Flux (Monthly, CERES, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-BlueMarble_ShadedRelief_Bathymetry</dc:identifier>
-        <dc:title>Blue Marble Shaded Relief and Bathymetry (MODIS)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SMAP_L1_Passive_Brightness_Temp_Fore_H_RFI</dc:identifier>
-        <dc:title>Uncorrected Brightness Temperature RFI (L1, Passive, Fore, H Polarization, Radiometer, SMAP)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SMAP_L4_Mean_Heterotrophic_Respiration</dc:identifier>
-        <dc:title>Heterotrophic Respiration (L4, 9 km Grid Cell Mean, Model Value-Added, SMAP)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MLS_H2O_46hPa_Night</dc:identifier>
-        <dc:title>Water Vapor (46 hPa, Night, MLS, Aura)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Terra_SurfaceReflectance_Bands143</dc:identifier>
-        <dc:title>Land Surface Reflectance (True Color, MODIS, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-LIS_High_Resolution_Full_Climatology_LIS_Scaled_Flashes</dc:identifier>
-        <dc:title>Lightning Flashes (Scaled, TRMM / LIS)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-CERES_EBAF_Surface_Shortwave_Flux_Up_All_Sky_Monthly</dc:identifier>
-        <dc:title>Surface Shortwave Flux (Monthly, Up, All-Sky, CERES, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-Reference_Features</dc:identifier>
-        <dc:title>Reference Features (OSM)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Terra_Cloud_Top_Pressure_Night</dc:identifier>
-        <dc:title>Cloud Top Pressure (Night, MODIS, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-OMI_SO2_Upper_Troposphere_and_Stratosphere</dc:identifier>
-        <dc:title>Sulfur Dioxide (Upper Troposphere and Stratosphere, OMI, Aura)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SSMI_DMSP_F15_Cloud_Liquid_Water_Over_Oceans_Ascending</dc:identifier>
-        <dc:title>Cloud Liquid Water (Ascending, Local PM, DMSP-F15 / SSMI)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SSMI_DMSP_F14_Rain_Rate_Over_Oceans_Descending</dc:identifier>
-        <dc:title>Rain Rate (Descending, DMSP-F14 / SSMI)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-RSS_Merged_Wind_Climatology_Monthly</dc:identifier>
-        <dc:title>Wind Speed over Ice-Free Oceans (Monthly, Average, Merged Microwave Radiometers)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Terra_Brightness_Temp_Band31_Night</dc:identifier>
-        <dc:title>Brightness Temperature (Band31, Night, MODIS, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SMAP_L1_Passive_Brightness_Temp_Fore_V_RFI</dc:identifier>
-        <dc:title>Uncorrected Brightness Temperature RFI (L1, Passive, Fore, V Polarization, Radiometer, SMAP)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SSMI_DMSP_F10_Water_Vapor_Over_Oceans_Descending</dc:identifier>
-        <dc:title>Water Vapor (Descending, Local AM, DMSP-F10 / SSMI)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SMAP_L4_Soil_Temperature_Layer_1</dc:identifier>
-        <dc:title>Surface Soil Temperature (L4, 12z Instantaneous, Model Value-Added, SMAP)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-AMSR2_Surface_Rain_Rate_Night</dc:identifier>
-        <dc:title>Surface Rain Rate (Night, AMSR2, GCOM-W1)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Aqua_CorrectedReflectance_TrueColor</dc:identifier>
-        <dc:title>Corrected Reflectance (True Color, MODIS, Aqua)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-AIRS_Temperature_500hPa_Day</dc:identifier>
-        <dc:title>Air Temperature (500 hPa, Day, AIRS, Aqua)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Aqua_Sea_Ice</dc:identifier>
-        <dc:title>Sea Ice Extent (MODIS, Aqua)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-CERES_Terra_TOA_Window_Region_Flux_All_Sky_Monthly</dc:identifier>
-        <dc:title>TOA Window-Region Flux All-Sky (Monthly, CERES, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-CERES_EBAF_Surface_Net_Shortwave_Flux_Clear_Sky_Monthly</dc:identifier>
-        <dc:title>Surface Net Shortwave Flux (Monthly, Clear-Sky, CERES, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SMAP_L4_Uncertainty_Analyzed_Root_Zone_Soil_Moisture</dc:identifier>
-        <dc:title>Root Zone Soil Moisture Uncertainty (L4, 12z Instantaneous, Model Value-Added, SMAP)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Combined_Value_Added_AOD</dc:identifier>
-        <dc:title>Aerosol Optical Depth (Value Added, MODIS, Combined Aqua and Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-CERES_EBAF_TOA_Shortwave_Flux_All_Sky_Monthly</dc:identifier>
-        <dc:title>TOA Shortwave Flux (Monthly, All-Sky, CERES, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-CERES_Combined_TOA_Shortwave_Flux_Clear_Sky_Monthly</dc:identifier>
-        <dc:title>TOA Shortwave Flux Clear-Sky (Monthly, CERES, Aqua+Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Terra_AOD_Deep_Blue_Combined</dc:identifier>
-        <dc:title>Merged Aerosol Optical Depth (Deep Blue, Land and Ocean, MODIS, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Terra_Angstrom_Exponent_Ocean</dc:identifier>
-        <dc:title>Dark Target Aerosol Angstrom Exponent (Ocean, MODIS, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SMAP_L1_Passive_Brightness_Temp_Fore_V</dc:identifier>
-        <dc:title>Uncorrected Brightness Temperature (L1, Passive, Fore, V Polarization, Radiometer, SMAP)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SMAP_L1_Passive_Brightness_Temp_Fore_H</dc:identifier>
-        <dc:title>Uncorrected Brightness Temperature (L1, Passive, Fore, H Polarization, Radiometer, SMAP)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-CERES_EBAF_Surface_CRE_Net_Total_Flux_Monthly</dc:identifier>
-        <dc:title>Surface CRE Net Total Flux (Monthly, CERES, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-CERES_EBAF_Surface_Net_Total_Flux_Clear_Sky_Monthly</dc:identifier>
-        <dc:title>Surface Net Total Flux (Monthly, Clear-Sky, CERES, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SSMI_DMSP_F10_Cloud_Liquid_Water_Over_Oceans_Descending</dc:identifier>
-        <dc:title>Cloud Liquid Water (Descending, Local AM, DMSP-F10 / SSMI)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SMAP_L4_Uncertainty_Mean_Net_Ecosystem_Exchange</dc:identifier>
-        <dc:title>Net Ecosystem CO2 Exchange Uncertainty (L4, 9 km Grid Cell Mean, Model Value-Added, SMAP)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Terra_NDVI_8Day</dc:identifier>
-        <dc:title>Normalized Difference Vegetation Index (8-Day, MODIS, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SMAP_L1_Passive_Faraday_Rotation_Aft</dc:identifier>
-        <dc:title>Faraday Rotation Angle (L1, Passive, Aft, Radiometer, SMAP)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Terra_Land_Surface_Temp_Day</dc:identifier>
-        <dc:title>Land Surface Temperature (Day, MODIS, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MOPITT_CO_Monthly_Total_Column_Day</dc:identifier>
-        <dc:title>Carbon Monoxide (Monthly, Day, Total Column, v6, Standard, MOPITT, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-AIRS_RelativeHumidity_600hPa_Night</dc:identifier>
-        <dc:title>Relative Humidity (600 hPa, Night, AIRS, Aqua)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-RSS_Total_Precipitable_Water_Climatology_Monthly</dc:identifier>
-        <dc:title>Precipitable Water over Ice-Free Oceans (Monthly, Average, Merged Microwave Radiometers)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-Landsat_WELD_CorrectedReflectance_TrueColor_Global_Monthly</dc:identifier>
-        <dc:title>Corrected Reflectance (True Color, Global Monthly, Best Available, NEX, Landsat)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Terra_Land_Surface_Temp_Night</dc:identifier>
-        <dc:title>Land Surface Temperature (Night, MODIS, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MISR_Directional_Hemispherical_Reflectance_Average_Natural_Color_Monthly</dc:identifier>
-        <dc:title>DHR Average (Monthly, Natural Color, MISR, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SSMI_DMSP_F11_Rain_Rate_Over_Oceans_Ascending</dc:identifier>
-        <dc:title>Rain Rate (Ascending, DMSP-F11 / SSMI)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SSMI_DMSP_F16_Cloud_Liquid_Water_Over_Oceans_Descending</dc:identifier>
-        <dc:title>Cloud Liquid Water (Descending, Local AM, DMSP-F16 / SSMIS)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SMAP_L1_Passive_Brightness_Temp_Aft_V</dc:identifier>
-        <dc:title>Uncorrected Brightness Temperature (L1, Passive, Aft, V Polarization, Radiometer, SMAP)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-OMI_Absorbing_Aerosol_Optical_Depth</dc:identifier>
-        <dc:title>Aerosol Optical Depth, Absorbing (OMI, Aura)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Aqua_Cloud_Top_Pressure_Night</dc:identifier>
-        <dc:title>Cloud Top Pressure (Night, MODIS, Aqua)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Terra_Chlorophyll_A</dc:identifier>
-        <dc:title>Chlorophyll (MODIS, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Terra_Cloud_Effective_Radius_37</dc:identifier>
-        <dc:title>Cloud Effective Radius (3.7 micron, MODIS, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-CERES_EBAF_Surface_Longwave_Flux_Down_All_Sky_Monthly</dc:identifier>
-        <dc:title>Surface Longwave Flux (Monthly, Down, All-Sky, CERES, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-AIRS_Temperature_400hPa_Night</dc:identifier>
-        <dc:title>Air Temperature (400 hPa, Night, AIRS, Aqua)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Aqua_Water_Vapor_5km_Day</dc:identifier>
-        <dc:title>Water Vapor Infrared (Day, MODIS, Aqua)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-BlueMarble_ShadedRelief</dc:identifier>
-        <dc:title>Blue Marble Shaded Relief (MODIS)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MLS_O3_46hPa_Night</dc:identifier>
-        <dc:title>Ozone (46 hPa, Night, MLS, Aura)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-CERES_EBAF_TOA_Longwave_Flux_Clear_Sky_Monthly</dc:identifier>
-        <dc:title>TOA Longwave Flux (Monthly, Clear-Sky, CERES, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Aqua_Cloud_Water_Path_PCL</dc:identifier>
-        <dc:title>Cloud Water Path (PCL, MODIS, Aqua)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-LIS_High_Resolution_Full_Climatology_LIS_Raw_Flashes</dc:identifier>
-        <dc:title>Lightning Flashes (Raw, TRMM / LIS)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Terra_EVI_8Day</dc:identifier>
-        <dc:title>Enhanced Vegetation Index (8-Day, MODIS, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SSMI_DMSP_F14_Cloud_Liquid_Water_Over_Oceans_Descending</dc:identifier>
-        <dc:title>Cloud Liquid Water (Descending, Local AM, DMSP-F14 / SSMI)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SSMI_DMSP_F13_Rain_Rate_Over_Oceans_Descending</dc:identifier>
-        <dc:title>Rain Rate (Descending, DMSP-F13 / SSMI)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-AIRS_CO_Total_Column_Night</dc:identifier>
-        <dc:title>Carbon Monoxide (Total Column, Night, AIRS, Aqua)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-AIRS_Precipitation_Day</dc:identifier>
-        <dc:title>Precipitation (Day, AIRS, Aqua)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SSMI_DMSP_F17_Wind_Speed_Over_Oceans_Ascending</dc:identifier>
-        <dc:title>Surface Wind Speed (Ascending, DMSP-F17 / SSMIS)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Terra_Angstrom_Exponent_Land</dc:identifier>
-        <dc:title>Deep Blue Aerosol Angstrom Exponent (Land, MODIS, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SSMI_DMSP_F14_Wind_Speed_Over_Oceans_Ascending</dc:identifier>
-        <dc:title>Surface Wind Speed (Ascending, DMSP-F14 / SSMI)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MISR_Land_NDVI_Average_Monthly</dc:identifier>
-        <dc:title>Land NDVI Average (Monthly, MISR)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MOPITT_CO_Daily_Total_Column_Night</dc:identifier>
-        <dc:title>Carbon Monoxide (Daily, Night, Total Column, MOPITT, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-ASTER_GDEM_Color_Index</dc:identifier>
-        <dc:title>Digital Elevation Model (Color Index, ASTER, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SSMI_DMSP_F15_Rain_Rate_Over_Oceans_Descending</dc:identifier>
-        <dc:title>Rain Rate (Descending, DMSP-F15 / SSMI)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SMAP_L4_Frozen_Area</dc:identifier>
-        <dc:title>Percent Frozen Area (L4, 9 km Grid Cell Coverage, Model Value-Added, SMAP)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Terra_Cloud_Effective_Radius_PCL</dc:identifier>
-        <dc:title>Cloud Effective Radius (PCL, MODIS, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-Landsat_WELD_CorrectedReflectance_TrueColor_Alaska_Seasonal</dc:identifier>
-        <dc:title>Corrected Reflectance (True Color, Alaska Seasonal, Best Available, Landsat)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-VIIRS_SNPP_CorrectedReflectance_TrueColor</dc:identifier>
-        <dc:title>Corrected Reflectance (True Color, VIIRS, SNPP)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-AIRS_RelativeHumidity_850hPa_Day</dc:identifier>
-        <dc:title>Relative Humidity (850 hPa, Day, AIRS, Aqua)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Aqua_Angstrom_Exponent_Land</dc:identifier>
-        <dc:title>Deep Blue Aerosol Angstrom Exponent (Land, MODIS, Aqua)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SSMI_DMSP_F13_Water_Vapor_Over_Oceans_Ascending</dc:identifier>
-        <dc:title>Water Vapor (Ascending, Local PM, DMSP-F13 / SSMI)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-CERES_EBAF_Surface_Shortwave_Flux_Down_Clear_Sky_Monthly</dc:identifier>
-        <dc:title>Surface Shortwave Flux (Monthly, Down, Clear-Sky, CERES, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SSMI_DMSP_F8_Water_Vapor_Over_Oceans_Ascending</dc:identifier>
-        <dc:title>Water Vapor (Ascending, Local AM, DMSP-F8 / SSMI)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SMAP_L1_Passive_Brightness_Temp_Fore_V_QA</dc:identifier>
-        <dc:title>Uncorrected Brightness Temperature QA (L1, Passive, Fore, V Polarization, Radiometer, SMAP)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Terra_Cloud_Effective_Radius</dc:identifier>
-        <dc:title>Cloud Effective Radius (MODIS, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Terra_Aerosol_Optical_Depth_3km</dc:identifier>
-        <dc:title>Aerosol Optical Depth (3km, MODIS, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Terra_SurfaceReflectance_Bands121</dc:identifier>
-        <dc:title>Land Surface Reflectance (Bands 1-2-1, MODIS, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SSMI_DMSP_F16_Rain_Rate_Over_Oceans_Descending</dc:identifier>
-        <dc:title>Rain Rate (Descending, DMSP-F16 / SSMIS)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MISR_TOA_Albedo_Average_Red_Monthly</dc:identifier>
-        <dc:title>TOA Albedo Average (Red, Monthly, MISR)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MOPITT_CO_Monthly_Surface_Mixing_Ratio_Day</dc:identifier>
-        <dc:title>Carbon Monoxide (Monthly, Day, Surface Mixing Ratio, v6, Standard, MOPITT, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SMAP_L3_Active_Sigma0_XPOL</dc:identifier>
-        <dc:title>Sigma0 (L3, Active, XPOL Polarization, Radar, SMAP)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SMAP_L4_Emult_Average</dc:identifier>
-        <dc:title>Percent of Potential Vegetation Light Use Efficiency (L4, 9 km Grid Cell Mean, Model Value-Added, SMAP)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-AMSR2_Sea_Ice_Brightness_Temp_6km_89H</dc:identifier>
-        <dc:title>Brightness Temperature for Sea Ice (89H Ghz, AMSR2, GCOM-W1)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MLS_N2O_46hPa_Night</dc:identifier>
-        <dc:title>Nitrous Oxide (46 hPa, Night, MLS, Aura)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SSMI_DMSP_F8_Cloud_Liquid_Water_Over_Oceans_Ascending</dc:identifier>
-        <dc:title>Cloud Liquid Water (Ascending, Local AM, DMSP-F8 / SSMI)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Terra_Cloud_Top_Temp_Day</dc:identifier>
-        <dc:title>Cloud Top Temperature (Day, MODIS, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-AMSR2_Sea_Ice_Brightness_Temp_6km_89V</dc:identifier>
-        <dc:title>Brightness Temperature for Sea Ice (89V Ghz, AMSR2, GCOM-W1)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-AIRS_Temperature_400hPa_Day</dc:identifier>
-        <dc:title>Air Temperature (400 hPa, Day, AIRS, Aqua)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Water_Mask</dc:identifier>
-        <dc:title>Water Mask (MODIS/SRTM)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MLS_Temperature_46hPa_Night</dc:identifier>
-        <dc:title>Air Temperature (46 hPa, Night, MLS, Aura)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SSMI_DMSP_F11_Rain_Rate_Over_Oceans_Descending</dc:identifier>
-        <dc:title>Rain Rate (Descending, DMSP-F11 / SSMI)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Terra_Cloud_Multi_Layer_Flag</dc:identifier>
-        <dc:title>Cloud Multi Layer Flag (MODIS, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-OMI_SO2_Lower_Troposphere</dc:identifier>
-        <dc:title>Sulfur Dioxide (Lower Troposphere, OMI, Aura)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-OTD_High_Resolution_Full_Climatology_OTD_Scaled_Flashes</dc:identifier>
-        <dc:title>Lightning Flashes (Scaled, OrbView-1 / OTD)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-AIRS_Temperature_600hPa_Day</dc:identifier>
-        <dc:title>Air Temperature (600 hPa, Day, AIRS, Aqua)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SMAP_L3_Active_Soil_Moisture</dc:identifier>
-        <dc:title>Soil Moisture (L3, Active, Radar, SMAP)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Aqua_Angstrom_Exponent_Ocean</dc:identifier>
-        <dc:title>Dark Target Aerosol Angstrom Exponent (Ocean, MODIS, Aqua)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MOPITT_CO_Daily_Surface_Mixing_Ratio_Day</dc:identifier>
-        <dc:title>Carbon Monoxide (Daily, Day, Surface Mixing Ratio, v6, Standard, MOPITT, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-AMSR2_Columnar_Water_Vapor_Night</dc:identifier>
-        <dc:title>Columnar Water Vapor (Night, AMSR2, GCOM-W1)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SSMI_DMSP_F14_Wind_Speed_Over_Oceans_Descending</dc:identifier>
-        <dc:title>Surface Wind Speed (Descending, DMSP-F14 / SSMI)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-OMI_Aerosol_Optical_Depth</dc:identifier>
-        <dc:title>Aerosol Optical Depth (OMI, Aura)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MOPITT_CO_Daily_Surface_Mixing_Ratio_Night</dc:identifier>
-        <dc:title>Carbon Monoxide (Daily, Night, Surface Mixing Ratio, MOPITT, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SMAP_L1_Passive_Brightness_Temp_Aft_H_QA</dc:identifier>
-        <dc:title>Uncorrected Brightness Temperature QA (L1, Passive, Aft, H Polarization, Radiometer, SMAP)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SSMI_DMSP_F10_Wind_Speed_Over_Oceans_Descending</dc:identifier>
-        <dc:title>Surface Wind Speed (Descending, DMSP-F10 / SSMI)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Terra_CorrectedReflectance_TrueColor</dc:identifier>
-        <dc:title>Corrected Reflectance (True Color, MODIS, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-CERES_Terra_TOA_Longwave_Flux_Clear_Sky_Monthly</dc:identifier>
-        <dc:title>TOA Longwave Flux Clear-Sky (Monthly, CERES, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Aqua_Land_Surface_Temp_Night</dc:identifier>
-        <dc:title>Land Surface Temperature (Night, MODIS, Aqua)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MLS_SO2_147hPa_Day</dc:identifier>
-        <dc:title>Sulfur Dioxide (147 hPa, Day, MLS, Aura)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SSMI_DMSP_F13_Rain_Rate_Over_Oceans_Ascending</dc:identifier>
-        <dc:title>Rain Rate (Ascending, DMSP-F13 / SSMI)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-AIRS_Temperature_850hPa_Day</dc:identifier>
-        <dc:title>Air Temperature (850 hPa, Day, AIRS, Aqua)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MISR_Radiance_Average_Natural_Color_Monthly</dc:identifier>
-        <dc:title>Radiance Average (AN, Natural Color, Monthly, MISR, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Aqua_Cloud_Top_Temp_Night</dc:identifier>
-        <dc:title>Cloud Top Temperature (Night, MODIS, Aqua)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Aqua_SurfaceReflectance_Bands721</dc:identifier>
-        <dc:title>Land Surface Reflectance (Bands 7-2-1, MODIS, Aqua)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Terra_Cloud_Top_Pressure_Day</dc:identifier>
-        <dc:title>Cloud Top Pressure (Day, MODIS, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-Landsat_WELD_CorrectedReflectance_TrueColor_Alaska_Monthly</dc:identifier>
-        <dc:title>Corrected Reflectance (True Color, Alaska Monthly, Best Available, Landsat)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-CERES_EBAF_Surface_Shortwave_Flux_Up_Clear_Sky_Monthly</dc:identifier>
-        <dc:title>Surface Shortwave Flux (Monthly, Up, Clear-Sky, CERES, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-Blue_Marble</dc:identifier>
-        <dc:title>Blue Marble (Reverb)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SSMI_DMSP_F16_Water_Vapor_Over_Oceans_Ascending</dc:identifier>
-        <dc:title>Water Vapor (Ascending, Local PM, DMSP-F16 / SSMIS)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-AMSR2_Cloud_Liquid_Water_Night</dc:identifier>
-        <dc:title>Columnar Cloud Liquid Water (Night, AMSR2, GCOM-W1)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-AIRS_RelativeHumidity_400hPa_Night</dc:identifier>
-        <dc:title>Relative Humidity (400 hPa, Night, AIRS, Aqua)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-GMI_Brightness_Temp_Asc</dc:identifier>
-        <dc:title>Brightness Temperature (Ascending, GMI, GPM)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Aqua_Cloud_Top_Height_Day</dc:identifier>
-        <dc:title>Cloud Top Height (Day, MODIS, Aqua)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SMAP_L3_Active_Sigma0_XPOL_RFI</dc:identifier>
-        <dc:title>Sigma0 RFI (L3, Active, XPOL Polarization, Radar, SMAP)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SMAP_L4_Mean_Gross_Primary_Productivity</dc:identifier>
-        <dc:title>Gross Primary Production (L4, 9 km Grid Cell Mean, Model Value-Added, SMAP)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-AMSR2_Snow_Water_Equivalent</dc:identifier>
-        <dc:title>Snow Water Equivalent (AMSR2, GCOM-W1)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SMAP_L2_Passive_Soil_Moisture_Option1</dc:identifier>
-        <dc:title>Soil Moisture (L2, Passive, Single Channel Algorithm, H Polarization, Radiometer, SMAP)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SMAP_L2_Passive_Soil_Moisture_Option2</dc:identifier>
-        <dc:title>Soil Moisture (L2, Passive, Single Channel Algorithm, V Polarization, Radiometer, SMAP)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SMAP_L2_Passive_Soil_Moisture_Option3</dc:identifier>
-        <dc:title>Soil Moisture (L2, Passive, Dual Channel Algorithm, Radiometer, SMAP)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MEaSUREs_Daily_Landscape_Freeze_Thaw_AMSRE</dc:identifier>
-        <dc:title>Freeze Thaw (Daily Landscape, AMSR-E, MEaSUREs)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-VIIRS_SNPP_CorrectedReflectance_BandsM11-I2-I1</dc:identifier>
-        <dc:title>Corrected Reflectance (M11-I2-I1, VIIRS, SNPP)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-VIIRS_CityLights_2012</dc:identifier>
-        <dc:title>Earth at Night (2012, VIIRS, SNPP)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-AMSRE_Surface_Rain_Rate_Day</dc:identifier>
-        <dc:title>Surface Rain Rate (Day, AMSR-E, Aqua)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SSMI_DMSP_F10_Rain_Rate_Over_Oceans_Ascending</dc:identifier>
-        <dc:title>Rain Rate (Ascending, DMSP-F10 / SSMI)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SMAP_L4_Uncertainty_Analyzed_Surface_Soil_Moisture</dc:identifier>
-        <dc:title>Surface Soil Moisture Uncertainty (L4, 12z Instantaneous, Model Value-Added, SMAP)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SMAP_L4_Snow_Mass</dc:identifier>
-        <dc:title>Snow Mass (L4, 12z-3z Average, Model Value-Added, SMAP)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SSMI_DMSP_F15_Rain_Rate_Over_Oceans_Ascending</dc:identifier>
-        <dc:title>Rain Rate (Ascending, DMSP-F15 / SSMI)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Terra_Cloud_Fraction_Day</dc:identifier>
-        <dc:title>Cloud Fraction (Day, MODIS, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-Landsat_WELD_NDVI_Global_Annual</dc:identifier>
-        <dc:title>NDVI (Global Annual, Best Available, NEX, Landsat)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-OTD_High_Resolution_Full_Climatology_OTD_Raw_Flashes</dc:identifier>
-        <dc:title>Lightning Flashes (Raw, OrbView-1 / OTD)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-AMSRE_Brightness_Temp_89V_Day</dc:identifier>
-        <dc:title>Brightness Temperature (89V Ghz B Scan, Day, AMSR-E, Aqua)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-CERES_Terra_TOA_Longwave_Flux_All_Sky_Monthly</dc:identifier>
-        <dc:title>TOA Longwave Flux All-Sky (Monthly, CERES, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-CERES_Terra_TOA_Window_Region_Flux_Clear_Sky_Monthly</dc:identifier>
-        <dc:title>TOA Window-Region Flux Clear-Sky (Monthly, CERES, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Aqua_Cloud_Phase_Optical_Properties</dc:identifier>
-        <dc:title>Cloud Phase Optical Properties (MODIS, Aqua)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SMAP_L3_Active_Passive_Brightness_Temp_V</dc:identifier>
-        <dc:title>Disaggregated Brightness Temperature (L3, Active/Passive, V Polarization, Radar/Radiometer, SMAP)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SSMI_DMSP_F15_Cloud_Liquid_Water_Over_Oceans_Descending</dc:identifier>
-        <dc:title>Cloud Liquid Water (Descending, Local AM, DMSP-F15 / SSMI)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-OMI_Aerosol_Index</dc:identifier>
-        <dc:title>Aerosol Index (OMI, Aura)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SMAP_L4_Analyzed_Surface_Soil_Moisture</dc:identifier>
-        <dc:title>Surface Soil Moisture (L4, 12z Instantaneous, Model Value-Added, SMAP)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-AMSR2_Columnar_Water_Vapor_Day</dc:identifier>
-        <dc:title>Columnar Water Vapor (Day, AMSR2, GCOM-W1)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-CERES_EBAF_Surface_Shortwave_Flux_Down_All_Sky_Monthly</dc:identifier>
-        <dc:title>Surface Shortwave Flux (Monthly, Down, All-Sky, CERES, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SSMI_DMSP_F11_Water_Vapor_Over_Oceans_Descending</dc:identifier>
-        <dc:title>Water Vapor (Descending, Local AM, DMSP-F11 / SSMI)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-AIRS_CO_Total_Column_Day</dc:identifier>
-        <dc:title>Carbon Monoxide (Total Column, Day, AIRS, Aqua)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SSMI_DMSP_F16_Water_Vapor_Over_Oceans_Descending</dc:identifier>
-        <dc:title>Water Vapor (Descending, Local AM, DMSP-F16 / SSMIS)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SSMI_DMSP_F13_Wind_Speed_Over_Oceans_Ascending</dc:identifier>
-        <dc:title>Surface Wind Speed (Ascending, DMSP-F13 / SSMI)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SSMI_DMSP_F13_Wind_Speed_Over_Oceans_Descending</dc:identifier>
-        <dc:title>Surface Wind Speed (Descending, DMSP-F13 / SSMI)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MOPITT_CO_Monthly_Total_Column_Night</dc:identifier>
-        <dc:title>Carbon Monoxide (Monthly, Night, Total Column, MOPITT, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Terra_Cloud_Optical_Thickness_PCL</dc:identifier>
-        <dc:title>Cloud Optical Thickness (PCL, MODIS, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-AIRS_Temperature_850hPa_Night</dc:identifier>
-        <dc:title>Air Temperature (850 hPa, Night, AIRS, Aqua)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SMAP_L4_Mean_Net_Ecosystem_Exchange</dc:identifier>
-        <dc:title>Net Ecosystem CO2 Exchange (L4, 9 km Grid Cell Mean, Model Value-Added, SMAP)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-CERES_EBAF_Surface_Net_Shortwave_Flux_All_Sky_Monthly</dc:identifier>
-        <dc:title>Surface Net Shortwave Flux (Monthly, All-Sky, CERES, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Aqua_Snow_Cover</dc:identifier>
-        <dc:title>Snow Cover (MODIS, Aqua)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Aqua_Cloud_Phase_Infrared_Day</dc:identifier>
-        <dc:title>Cloud Phase (Infrared, Day, MODIS, Aqua)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SMAP_L3_Active_Sigma0_HH</dc:identifier>
-        <dc:title>Sigma0 (L3, Active, HH Polarization, Radar, SMAP)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SMAP_L3_Active_Passive_Brightness_Temp_H</dc:identifier>
-        <dc:title>Disaggregated Brightness Temperature (L3, Active/Passive, H Polarization, Radar/Radiometer, SMAP)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SSMI_DMSP_F10_Cloud_Liquid_Water_Over_Oceans_Ascending</dc:identifier>
-        <dc:title>Cloud Liquid Water (Ascending, Local PM, DMSP-F10 / SSMI)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SMAP_L1_Passive_Brightness_Temp_Aft_V_QA</dc:identifier>
-        <dc:title>Uncorrected Brightness Temperature QA (L1, Passive, Aft, V Polarization, Radiometer, SMAP)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-BlueMarble_NextGeneration</dc:identifier>
-        <dc:title>Blue Marble (MODIS)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MLS_CO_215hPa_Day</dc:identifier>
-        <dc:title>Carbon Monoxide (215 hPa, Day, MLS, Aura)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Aqua_Cloud_Effective_Radius</dc:identifier>
-        <dc:title>Cloud Effective Radius (MODIS, Aqua)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SSMI_DMSP_F10_Wind_Speed_Over_Oceans_Ascending</dc:identifier>
-        <dc:title>Surface Wind Speed (Ascending, DMSP-F10 / SSMI)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SSMI_DMSP_F16_Cloud_Liquid_Water_Over_Oceans_Ascending</dc:identifier>
-        <dc:title>Cloud Liquid Water (Ascending, Local PM, DMSP-F16 / SSMIS)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Aqua_Cloud_Optical_Thickness</dc:identifier>
-        <dc:title>Cloud Optical Thickness (MODIS, Aqua)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Aqua_Brightness_Temp_Band31_Night</dc:identifier>
-        <dc:title>Brightness Temperature (Band31, Night, MODIS, Aqua)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-CERES_EBAF_TOA_Longwave_Flux_All_Sky_Monthly</dc:identifier>
-        <dc:title>TOA Longwave Flux (Monthly, All-Sky, CERES, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-Landsat_WELD_NDVI_Global_Monthly</dc:identifier>
-        <dc:title>NDVI (Global Monthly, Best Available, NEX, Landsat)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-OSM_Land_Mask</dc:identifier>
-        <dc:title>Land Mask (OSM)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-CERES_EBAF_TOA_Net_Flux_All_Sky_Monthly</dc:identifier>
-        <dc:title>TOA Net Flux (Monthly, All-Sky, CERES, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-CERES_EBAF_Surface_Longwave_Flux_Down_Clear_Sky_Monthly</dc:identifier>
-        <dc:title>Surface Longwave Flux (Monthly, Down, Clear-Sky, CERES, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Terra_Water_Vapor_5km_Night</dc:identifier>
-        <dc:title>Water Vapor Infrared (Night, MODIS, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-GHRSST_L4_G1SST_Sea_Surface_Temperature</dc:identifier>
-        <dc:title>Sea Surface Temperature (L4, G1SST Global Foundation, GHRSST)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Terra_Cloud_Effective_Radius_37_PCL</dc:identifier>
-        <dc:title>Cloud Effective Radius (3.7 micron PCL, MODIS, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Terra_Snow_Cover</dc:identifier>
-        <dc:title>Snow Cover (MODIS, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SMAP_L4_Analyzed_Root_Zone_Soil_Moisture</dc:identifier>
-        <dc:title>Root Zone Soil Moisture (L4, 12z Instantaneous, Model Value-Added, SMAP)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Terra_AOD_Deep_Blue_Land</dc:identifier>
-        <dc:title>Deep Blue Aerosol Optical Depth (Land, MODIS, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-CERES_EBAF_Surface_Net_Longwave_Flux_All_Sky_Monthly</dc:identifier>
-        <dc:title>Surface Net Longwave Flux (Monthly, All-Sky, CERES, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SSMI_DMSP_F8_Wind_Speed_Over_Oceans_Descending</dc:identifier>
-        <dc:title>Surface Wind Speed (Descending, DMSP-F8 / SSMI)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-AMSR2_Sea_Ice_Concentration_25km</dc:identifier>
-        <dc:title>Sea Ice Concentration (25 km, AMSR2, GCOM-W1)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Terra_Cloud_Optical_Thickness</dc:identifier>
-        <dc:title>Cloud Optical Thickness (MODIS, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-AIRS_Prata_SO2_Index_Day</dc:identifier>
-        <dc:title>Sulfur Dioxide (Prata, Day, AIRS, Aqua)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MLS_N2O_46hPa_Day</dc:identifier>
-        <dc:title>Nitrous Oxide (46 hPa, Day, MLS, Aura)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-AIRS_Temperature_600hPa_Night</dc:identifier>
-        <dc:title>Air Temperature (600 hPa, Night, AIRS, Aqua)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SSMI_DMSP_F15_Wind_Speed_Over_Oceans_Ascending</dc:identifier>
-        <dc:title>Surface Wind Speed (Ascending, DMSP-F15 / SSMI)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Terra_CorrectedReflectance_Bands367</dc:identifier>
-        <dc:title>Corrected Reflectance (Bands 3-6-7, MODIS, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SSMI_DMSP_F15_Water_Vapor_Over_Oceans_Descending</dc:identifier>
-        <dc:title>Water Vapor (Descending, Local AM, DMSP-F15 / SSMI)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Terra_Data_No_Data</dc:identifier>
-        <dc:title>Data/No Data Mask (MODIS, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Terra_Cloud_Top_Temp_Night</dc:identifier>
-        <dc:title>Cloud Top Temperature (Night, MODIS, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MEaSUREs_Daily_Landscape_Freeze_Thaw_SSMI</dc:identifier>
-        <dc:title>Freeze Thaw (Daily Landscape, SSMI, MEaSUREs)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-AIRS_RelativeHumidity_400hPa_Day</dc:identifier>
-        <dc:title>Relative Humidity (400 hPa, Day, AIRS, Aqua)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SSMI_DMSP_F14_Rain_Rate_Over_Oceans_Ascending</dc:identifier>
-        <dc:title>Rain Rate (Ascending, DMSP-F14 / SSMI)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SSMI_DMSP_F14_Cloud_Liquid_Water_Over_Oceans_Ascending</dc:identifier>
-        <dc:title>Cloud Liquid Water (Ascending, Local PM, DMSP-F14 / SSMI)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Aqua_SurfaceReflectance_Bands121</dc:identifier>
-        <dc:title>Land Surface Reflectance (Bands 1-2-1, MODIS, Aqua)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SSMI_DMSP_F13_Cloud_Liquid_Water_Over_Oceans_Ascending</dc:identifier>
-        <dc:title>Cloud Liquid Water (Ascending, Local PM, DMSP-F13 / SSMI)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SSMI_DMSP_F17_Cloud_Liquid_Water_Over_Oceans_Ascending</dc:identifier>
-        <dc:title>Cloud Liquid Water (Ascending, Local PM, DMSP-F17 / SSMIS)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SSMI_DMSP_F8_Rain_Rate_Over_Oceans_Ascending</dc:identifier>
-        <dc:title>Rain Rate (Ascending, DMSP-F8 / SSMI)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SSMI_DMSP_F15_Wind_Speed_Over_Oceans_Descending</dc:identifier>
-        <dc:title>Surface Wind Speed (Descending, DMSP-F15 / SSMI)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-OTD_High_Resolution_Full_Climatology_OTD_Flash_Rate_Climatology</dc:identifier>
-        <dc:title>Lightning Flash Rate (, OrbView-1 / OTD)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-ASTER_GDEM_Color_Shaded_Relief</dc:identifier>
-        <dc:title>Digital Elevation Model (Color Shaded Relief, ASTER, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-CERES_EBAF_TOA_Shortwave_Flux_Clear_Sky_Monthly</dc:identifier>
-        <dc:title>TOA Shortwave Flux (Monthly, Clear-Sky, CERES, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SSMI_DMSP_F17_Wind_Speed_Over_Oceans_Descending</dc:identifier>
-        <dc:title>Surface Wind Speed (Descending, DMSP-F17 / SSMIS)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-AMSRE_Brightness_Temp_89H_Day</dc:identifier>
-        <dc:title>Brightness Temperature (89H Ghz B Scan, Day, AMSR-E, Aqua)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SSMI_DMSP_F8_Wind_Speed_Over_Oceans_Ascending</dc:identifier>
-        <dc:title>Surface Wind Speed (Ascending, DMSP-F8 / SSMI)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-CERES_Combined_TOA_Shortwave_Flux_All_Sky_Monthly</dc:identifier>
-        <dc:title>TOA Shortwave Flux All-Sky (Monthly, CERES, Aqua+Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SMAP_L1_Passive_Brightness_Temp_Fore_H_QA</dc:identifier>
-        <dc:title>Uncorrected Brightness Temperature QA (L1, Passive, Fore, H Polarization, Radiometer, SMAP)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SMAP_L1_Passive_Faraday_Rotation_Fore</dc:identifier>
-        <dc:title>Faraday Rotation Angle (L1, Passive, Fore, Radiometer, SMAP)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-AIRS_Temperature_700hPa_Day</dc:identifier>
-        <dc:title>Air Temperature (700 hPa, Day, AIRS, Aqua)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MLS_HNO3_46hPa_Day</dc:identifier>
-        <dc:title>Nitric Acid (46 hPa, Day, MLS, Aura)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SSMI_DMSP_F15_Water_Vapor_Over_Oceans_Ascending</dc:identifier>
-        <dc:title>Water Vapor (Ascending, Local PM, DMSP-F15 / SSMI)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Aqua_Cloud_Effective_Radius_PCL</dc:identifier>
-        <dc:title>Cloud Effective Radius (PCL, MODIS, Aqua)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SSMI_DMSP_F11_Wind_Speed_Over_Oceans_Descending</dc:identifier>
-        <dc:title>Surface Wind Speed (Descending, DMSP-F11 / SSMI)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SMAP_L1_Passive_Brightness_Temp_Aft_V_RFI</dc:identifier>
-        <dc:title>Uncorrected Brightness Temperature RFI (L1, Passive, Aft, V Polarization, Radiometer, SMAP)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-AMSRE_Surface_Precipitation_Rate_Day</dc:identifier>
-        <dc:title>Surface Precipitation Rate (Day, AMSR-E, Aqua)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SSMI_DMSP_F11_Wind_Speed_Over_Oceans_Ascending</dc:identifier>
-        <dc:title>Surface Wind Speed (Ascending, DMSP-F11 / SSMI)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-CERES_EBAF_Surface_Longwave_Flux_Up_Clear_Sky_Monthly</dc:identifier>
-        <dc:title>Surface Longwave Flux (Monthly, Up, Clear-Sky, CERES, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Aqua_Cloud_Fraction_Day</dc:identifier>
-        <dc:title>Cloud Fraction (Day, MODIS, Aqua)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-CERES_EBAF_Surface_CRE_Net_Shortwave_Flux_Monthly</dc:identifier>
-        <dc:title>Surface CRE Net Shortwave Flux (Monthly, CERES, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SSMI_DMSP_F13_Water_Vapor_Over_Oceans_Descending</dc:identifier>
-        <dc:title>Water Vapor (Descending, Local AM, DMSP-F13 / SSMI)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Terra_Cloud_Phase_Optical_Properties</dc:identifier>
-        <dc:title>Cloud Phase Optical Properties (MODIS, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MOPITT_CO_Daily_Total_Column_Day</dc:identifier>
-        <dc:title>Carbon Monoxide (Daily, Day, Total Column, v6, Standard, MOPITT, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SSMI_DMSP_F16_Wind_Speed_Over_Oceans_Ascending</dc:identifier>
-        <dc:title>Surface Wind Speed (Ascending, DMSP-F16 / SSMIS)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-CERES_Combined_TOA_Window_Region_Flux_Clear_Sky_Monthly</dc:identifier>
-        <dc:title>TOA Window-Region Flux Clear-Sky (Monthly, CERES, Aqua+Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SMAP_L3_Passive_Brightness_Temp_H</dc:identifier>
-        <dc:title>Corrected Brightness Temperature (L3, Passive, H Polarization, Radiometer, SMAP)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SSMI_DMSP_F16_Wind_Speed_Over_Oceans_Descending</dc:identifier>
-        <dc:title>Surface Wind Speed (Descending, DMSP-F16 / SSMIS)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-AMSRE_Sea_Ice_Concentration_25km</dc:identifier>
-        <dc:title>Sea Ice Concentration (25 km, AMSR-E, Aqua)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Terra_Sea_Ice</dc:identifier>
-        <dc:title>Sea Ice Extent (MODIS, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-AMSRE_Brightness_Temp_89V_Night</dc:identifier>
-        <dc:title>Brightness Temperature (89V Ghz B Scan, Night, AMSR-E, Aqua)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SSMI_DMSP_F11_Cloud_Liquid_Water_Over_Oceans_Descending</dc:identifier>
-        <dc:title>Cloud Liquid Water (Descending, Local AM, DMSP-F11 / SSMI)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Terra_Cloud_Top_Height_Day</dc:identifier>
-        <dc:title>Cloud Top Height (Day, MODIS, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-Landsat_WELD_CorrectedReflectance_TrueColor_CONUS_Seasonal</dc:identifier>
-        <dc:title>Corrected Reflectance (True Color, CONUS Seasonal, Landsat)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-AIRS_Precipitation_Night</dc:identifier>
-        <dc:title>Precipitation (Night, AIRS, Aqua)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-AMSRE_Brightness_Temp_89H_Night</dc:identifier>
-        <dc:title>Brightness Temperature (89H Ghz B Scan, Night, AMSR-E, Aqua)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SMAP_L3_Passive_Brightness_Temp_V</dc:identifier>
-        <dc:title>Corrected Brightness Temperature (L3, Passive, V Polarization, Radiometer, SMAP)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Terra_Cloud_Top_Height_Night</dc:identifier>
-        <dc:title>Cloud Top Height (Night, MODIS, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-GMI_Brightness_Temp_Dsc</dc:identifier>
-        <dc:title>Brightness Temperature (Descending, GMI, GPM)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SMAP_L3_Active_Sigma0_XPOL_QA</dc:identifier>
-        <dc:title>Sigma0 QA (L3, Active, XPOL Polarization, Radar, SMAP)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-AMSRE_Surface_Precipitation_Rate_Night</dc:identifier>
-        <dc:title>Surface Precipitation Rate (Night, AMSR-E, Aqua)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-GMI_Snow_Rate_Dsc</dc:identifier>
-        <dc:title>Snow Rate (Descending, GMI, GPM)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-CERES_Combined_TOA_Longwave_Flux_Clear_Sky_Monthly</dc:identifier>
-        <dc:title>TOA Longwave Flux Clear-Sky (Monthly, CERES, Aqua+Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SMAP_L3_Active_Passive_Soil_Moisture</dc:identifier>
-        <dc:title>Soil Moisture (L3, Active/Passive, Radar/Radiometer, SMAP)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SSMI_DMSP_F17_Water_Vapor_Over_Oceans_Ascending</dc:identifier>
-        <dc:title>Water Vapor (Ascending, Local PM, DMSP-F17 / SSMIS)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Aqua_Aerosol_Optical_Depth_3km</dc:identifier>
-        <dc:title>Aerosol Optical Depth (3km, MODIS, Aqua)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-Landsat_WELD_CorrectedReflectance_TrueColor_Alaska_Annual</dc:identifier>
-        <dc:title>Corrected Reflectance (True Color, Alaska Annual, Best Available, Landsat)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MISR_Aerosol_Optical_Depth_Avg_Green_Monthly</dc:identifier>
-        <dc:title>Aerosol Optical Depth Average (Green, Monthly, MISR)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-Landsat_WELD_CorrectedReflectance_TrueColor_CONUS_Monthly</dc:identifier>
-        <dc:title>Corrected Reflectance (True Color, CONUS Monthly, Best Available, Landsat)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-GMI_Rain_Rate_Asc</dc:identifier>
-        <dc:title>Rain Rate (Ascending, GMI, GPM)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Terra_SurfaceReflectance_Bands721</dc:identifier>
-        <dc:title>Land Surface Reflectance (Bands 7-2-1, MODIS, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-LIS_High_Resolution_Full_Climatology_Combined_Flash_Rate_Climatology</dc:identifier>
-        <dc:title>Lightning Flash Rate (Combined, TRMM / LIS, OrbView-1 / OTD)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Terra_Water_Vapor_5km_Day</dc:identifier>
-        <dc:title>Water Vapor Infrared (Day, MODIS, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Aqua_Cloud_Fraction_Night</dc:identifier>
-        <dc:title>Cloud Fraction (Night, MODIS, Aqua)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Aqua_Aerosol</dc:identifier>
-        <dc:title>Dark Target Aerosol Optical Depth (Land and Ocean, MODIS, Aqua)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-AMSR2_Wind_Speed_Day</dc:identifier>
-        <dc:title>Wind Speed (Day, AMSR2, GCOM-W1)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-CERES_EBAF_TOA_CRE_Shortwave_Flux_Monthly</dc:identifier>
-        <dc:title>TOA CRE Shortwave Flux (Monthly, CERES, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-OMI_Cloud_Pressure</dc:identifier>
-        <dc:title>Cloud Pressure (OMI, Aura)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MLS_H2O_46hPa_Day</dc:identifier>
-        <dc:title>Water Vapor (46 hPa, Day, MLS, Aura)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MLS_CO_215hPa_Night</dc:identifier>
-        <dc:title>Carbon Monoxide (215 hPa, Night, MLS, Aura)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Terra_Cloud_Water_Path</dc:identifier>
-        <dc:title>Cloud Water Path (MODIS, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SMAP_L1_Passive_Brightness_Temp_Aft_H_RFI</dc:identifier>
-        <dc:title>Uncorrected Brightness Temperature RFI (L1, Passive, Aft, H Polarization, Radiometer, SMAP)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-AMSRE_Sea_Ice_Brightness_Temp_89V</dc:identifier>
-        <dc:title>Brightness Temperature for Sea Ice (89V Ghz, AMSR-E, Aqua)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Aqua_AOD_Deep_Blue_Combined</dc:identifier>
-        <dc:title>Merged Aerosol Optical Depth (Deep Blue, Land and Ocean, MODIS, Aqua)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-AMSRE_Sea_Ice_Brightness_Temp_89H</dc:identifier>
-        <dc:title>Brightness Temperature for Sea Ice (89H Ghz, AMSR-E, Aqua)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-AMSR2_Wind_Speed_Night</dc:identifier>
-        <dc:title>Wind Speed (Night, AMSR2, GCOM-W1)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SMAP_L3_Active_Sigma0_VV_QA</dc:identifier>
-        <dc:title>Sigma0 QA (L3, Active, VV Polarization, Radar, SMAP)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-AIRS_Temperature_500hPa_Night</dc:identifier>
-        <dc:title>Air Temperature (500 hPa, Night, AIRS, Aqua)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-AIRS_RelativeHumidity_700hPa_Night</dc:identifier>
-        <dc:title>Relative Humidity (700 hPa, Night, AIRS, Aqua)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-AMSR2_Cloud_Liquid_Water_Day</dc:identifier>
-        <dc:title>Columnar Cloud Liquid Water (Day, AMSR2, GCOM-W1)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-Aquarius_Soil_Moisture_Weekly</dc:identifier>
-        <dc:title>Soil Moisture (Weekly, Radiometer, Aquarius, SAC-D)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Aqua_Cloud_Water_Path</dc:identifier>
-        <dc:title>Cloud Water Path (MODIS, Aqua)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Aqua_Cloud_Effective_Radius_37_PCL</dc:identifier>
-        <dc:title>Cloud Effective Radius (3.7 micron PCL, MODIS, Aqua)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SMAP_L1_Passive_Brightness_Temp_Aft_H</dc:identifier>
-        <dc:title>Uncorrected Brightness Temperature (L1, Passive, Aft, H Polarization, Radiometer, SMAP)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-AMSRE_Surface_Rain_Rate_Night</dc:identifier>
-        <dc:title>Surface Rain Rate (Night, AMSR-E, Aqua)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SSMI_DMSP_F17_Water_Vapor_Over_Oceans_Descending</dc:identifier>
-        <dc:title>Water Vapor (Descending, Local AM, DMSP-F17 / SSMIS)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-Landsat_WELD_CorrectedReflectance_TrueColor_Global_Annual</dc:identifier>
-        <dc:title>Corrected Reflectance (True Color, Global Annual, Best Available, NEX, Landsat)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-AMSRE_Snow_Depth_Over_Ice</dc:identifier>
-        <dc:title>Snow Depth Over Ice (12 km, AMSR-E, Aqua)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-Aquarius_Soil_Moisture_Daily</dc:identifier>
-        <dc:title>Soil Moisture (Daily, Radiometer, Aquarius, SAC-D)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SSMI_DMSP_F11_Cloud_Liquid_Water_Over_Oceans_Ascending</dc:identifier>
-        <dc:title>Cloud Liquid Water (Ascending, Local PM, DMSP-F11 / SSMI)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-AIRS_Dust_Score_Ocean_Day</dc:identifier>
-        <dc:title>Dust Score Ocean (Day, AIRS, Aqua)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-AIRS_RelativeHumidity_600hPa_Day</dc:identifier>
-        <dc:title>Relative Humidity (600 hPa, Day, AIRS, Aqua)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Aqua_Cloud_Top_Pressure_Day</dc:identifier>
-        <dc:title>Cloud Top Pressure (Day, MODIS, Aqua)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-AMSR2_Sea_Ice_Concentration_12km</dc:identifier>
-        <dc:title>Sea Ice Concentration (12 km, AMSR2, GCOM-W1)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-OSM_Land_Water_Map</dc:identifier>
-        <dc:title>Land Water Map (OSM)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-AMSR2_Surface_Precipitation_Rate_Day</dc:identifier>
-        <dc:title>Surface Precipitation Rate (Day, AMSR2, GCOM-W1)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SRTM_Color_Index</dc:identifier>
-        <dc:title>Digital Elevation Model (Color Index, SRTM)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-CERES_EBAF_TOA_CRE_Net_Flux_Monthly</dc:identifier>
-        <dc:title>TOA CRE Net Flux (Monthly, CERES, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-AIRS_Dust_Score_Ocean_Night</dc:identifier>
-        <dc:title>Dust Score Ocean (Night, AIRS, Aqua)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-Landsat_WELD_CorrectedReflectance_TrueColor_CONUS_Annual</dc:identifier>
-        <dc:title>Corrected Reflectance (True Color, CONUS Annual, Landsat)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-SSMI_DMSP_F17_Rain_Rate_Over_Oceans_Descending</dc:identifier>
-        <dc:title>Rain Rate (Descending, DMSP-F17 / SSMIS)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Aqua_Cloud_Effective_Radius_37</dc:identifier>
-        <dc:title>Cloud Effective Radius (3.7 micron, MODIS, Aqua)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-CERES_EBAF_Surface_CRE_Net_Longwave_Flux_Monthly</dc:identifier>
-        <dc:title>Surface CRE Net Longwave Flux (Monthly, CERES, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-ASTER_GDEM_Greyscale_Shaded_Relief</dc:identifier>
-        <dc:title>Digital Elevation Model (Greyscale Shaded Relief, ASTER, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MLS_SO2_147hPa_Night</dc:identifier>
-        <dc:title>Sulfur Dioxide (147 hPa, Night, MLS, Aura)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Terra_Cloud_Water_Path_PCL</dc:identifier>
-        <dc:title>Cloud Water Path (PCL, MODIS, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Aqua_Data_No_Data</dc:identifier>
-        <dc:title>Data/No Data Mask (MODIS, Aqua)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-CERES_EBAF_TOA_Incoming_Solar_Flux_Monthly</dc:identifier>
-        <dc:title>Incoming Solar Flux (Monthly, CERES, Terra)</dc:title>
-      </csw:BriefRecord>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-MODIS_Aqua_Water_Vapor_5km_Night</dc:identifier>
-        <dc:title>Water Vapor Infrared (Night, MODIS, Aqua)</dc:title>
-      </csw:BriefRecord>
-    </csw:InsertResult>
-  </csw:TransactionResponse>
-</csw:HarvestResponse>
diff --git a/tests/expected/suites_harvesting_post_Harvest-wps.xml b/tests/expected/suites_harvesting_post_Harvest-wps.xml
deleted file mode 100644
index d4da1a5..0000000
--- a/tests/expected/suites_harvesting_post_Harvest-wps.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- PYCSW_VERSION -->
-<csw:HarvestResponse xmlns:csw="http://www.opengis.net/cat/csw/2.0.2" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dct="http://purl.org/dc/terms/" xmlns:gmd="http://www.isotc211.org/2005/gmd" xmlns:gml="http://www.opengis.net/gml" xmlns:ows="http://www.opengis.net/ows" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/cat/csw/2.0.2 http://schemas.opengis.net/csw/2.0.2/CSW-publication.xsd">
-  <csw:TransactionResponse version="2.0.2">
-    <csw:TransactionSummary>
-      <csw:totalInserted>1</csw:totalInserted>
-      <csw:totalUpdated>0</csw:totalUpdated>
-      <csw:totalDeleted>0</csw:totalDeleted>
-    </csw:TransactionSummary>
-    <csw:InsertResult>
-      <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER</dc:identifier>
-        <dc:title>Geo Data Portal WPS Implementation</dc:title>
-      </csw:BriefRecord>
-    </csw:InsertResult>
-  </csw:TransactionResponse>
-</csw:HarvestResponse>
diff --git a/tests/expected/suites_harvesting_post_Harvest-zzz-post-GetRecords-filter-wfs-iso.xml b/tests/expected/suites_harvesting_post_Harvest-zzz-post-GetRecords-filter-wfs-iso.xml
deleted file mode 100644
index 5078cd1..0000000
--- a/tests/expected/suites_harvesting_post_Harvest-zzz-post-GetRecords-filter-wfs-iso.xml
+++ /dev/null
@@ -1,370 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- PYCSW_VERSION -->
-<csw:GetRecordsResponse xmlns:csw="http://www.opengis.net/cat/csw/2.0.2" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dct="http://purl.org/dc/terms/" xmlns:gco="http://www.isotc211.org/2005/gco" xmlns:gmd="http://www.isotc211.org/2005/gmd" xmlns:gml="http://www.opengis.net/gml" xmlns:ows="http://www.opengis.net/ows" xmlns:srv="http://www.isotc211.org/2005/srv" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XML [...]
-  <csw:SearchStatus timestamp="PYCSW_TIMESTAMP"/>
-  <csw:SearchResults nextRecord="0" numberOfRecordsMatched="1" numberOfRecordsReturned="1" recordSchema="http://www.isotc211.org/2005/gmd" elementSet="full">
-    <gmd:MD_Metadata xsi:schemaLocation="http://www.isotc211.org/2005/gmd http://schemas.opengis.net/csw/2.0.2/profiles/apiso/1.0.0/apiso.xsd">
-      <gmd:fileIdentifier>
-        <gco:CharacterString>PYCSW_IDENTIFIER</gco:CharacterString>
-      </gmd:fileIdentifier>
-      <gmd:language>
-        <gco:CharacterString/>
-      </gmd:language>
-      <gmd:hierarchyLevel>
-        <gmd:MD_ScopeCode codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#MD_ScopeCode" codeListValue="service" codeSpace="ISOTC211/19115">service</gmd:MD_ScopeCode>
-      </gmd:hierarchyLevel>
-      <gmd:contact>
-        <gmd:CI_ResponsibleParty>
-          <gmd:individualName>
-            <gco:CharacterString>Matt Austin</gco:CharacterString>
-          </gmd:individualName>
-          <gmd:organisationName>
-            <gco:CharacterString>National Oceanic and Atmospheric Administration</gco:CharacterString>
-          </gmd:organisationName>
-          <gmd:positionName>
-            <gco:CharacterString/>
-          </gmd:positionName>
-          <gmd:contactInfo>
-            <gmd:CI_Contact>
-              <gmd:phone>
-                <gmd:CI_Telephone>
-                  <gmd:voice>
-                    <gco:CharacterString/>
-                  </gmd:voice>
-                  <gmd:facsimile>
-                    <gco:CharacterString/>
-                  </gmd:facsimile>
-                </gmd:CI_Telephone>
-              </gmd:phone>
-              <gmd:address>
-                <gmd:CI_Address>
-                  <gmd:deliveryPoint>
-                    <gco:CharacterString/>
-                  </gmd:deliveryPoint>
-                  <gmd:city>
-                    <gco:CharacterString>Silver Spring</gco:CharacterString>
-                  </gmd:city>
-                  <gmd:administrativeArea>
-                    <gco:CharacterString>Maryland</gco:CharacterString>
-                  </gmd:administrativeArea>
-                  <gmd:postalCode>
-                    <gco:CharacterString>20910</gco:CharacterString>
-                  </gmd:postalCode>
-                  <gmd:country>
-                    <gco:CharacterString>USA</gco:CharacterString>
-                  </gmd:country>
-                  <gmd:electronicMailAddress>
-                    <gco:CharacterString/>
-                  </gmd:electronicMailAddress>
-                </gmd:CI_Address>
-              </gmd:address>
-            </gmd:CI_Contact>
-          </gmd:contactInfo>
-          <gmd:role>
-            <gmd:CI_RoleCode codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#CI_RoleCode" codeListValue="pointOfContact">pointOfContact</gmd:CI_RoleCode>
-          </gmd:role>
-        </gmd:CI_ResponsibleParty>
-      </gmd:contact>
-      <gmd:dateStamp>
-        <gco:Date/>
-      </gmd:dateStamp>
-      <gmd:metadataStandardName>
-        <gco:CharacterString>ISO19119</gco:CharacterString>
-      </gmd:metadataStandardName>
-      <gmd:metadataStandardVersion>
-        <gco:CharacterString>2005/PDAM 1</gco:CharacterString>
-      </gmd:metadataStandardVersion>
-      <gmd:identificationInfo>
-        <srv:SV_ServiceIdentification id="PYCSW_IDENTIFIER">
-          <gmd:citation>
-            <gmd:CI_Citation>
-              <gmd:title>
-                <gco:CharacterString>GeoServer Web Feature Service</gco:CharacterString>
-              </gmd:title>
-            </gmd:CI_Citation>
-          </gmd:citation>
-          <gmd:abstract>
-            <gco:CharacterString>This is the reference implementation of WFS 1.0.0 and WFS 1.1.0, supports all WFS operations including Transaction.</gco:CharacterString>
-          </gmd:abstract>
-          <gmd:descriptiveKeywords>
-            <gmd:MD_Keywords>
-              <gmd:keyword>
-                <gco:CharacterString>WFS</gco:CharacterString>
-              </gmd:keyword>
-              <gmd:keyword>
-                <gco:CharacterString>WMS</gco:CharacterString>
-              </gmd:keyword>
-              <gmd:keyword>
-                <gco:CharacterString>GEOSERVER</gco:CharacterString>
-              </gmd:keyword>
-            </gmd:MD_Keywords>
-          </gmd:descriptiveKeywords>
-          <gmd:language>
-            <gco:CharacterString/>
-          </gmd:language>
-          <srv:serviceType>
-            <gco:LocalName>OGC:WFS</gco:LocalName>
-          </srv:serviceType>
-          <srv:serviceTypeVersion>
-            <gco:CharacterString>1.1.0</gco:CharacterString>
-          </srv:serviceTypeVersion>
-          <srv:keywords>
-            <gmd:MD_Keywords>
-              <gmd:keyword>
-                <gco:CharacterString>WFS</gco:CharacterString>
-              </gmd:keyword>
-              <gmd:keyword>
-                <gco:CharacterString>WMS</gco:CharacterString>
-              </gmd:keyword>
-              <gmd:keyword>
-                <gco:CharacterString>GEOSERVER</gco:CharacterString>
-              </gmd:keyword>
-            </gmd:MD_Keywords>
-          </srv:keywords>
-          <srv:extent>
-            <gmd:EX_Extent>
-              <gmd:geographicElement>
-                <gmd:EX_GeographicBoundingBox>
-                  <gmd:westBoundLongitude>
-                    <gco:Decimal>-179.87</gco:Decimal>
-                  </gmd:westBoundLongitude>
-                  <gmd:eastBoundLongitude>
-                    <gco:Decimal>179.99</gco:Decimal>
-                  </gmd:eastBoundLongitude>
-                  <gmd:southBoundLatitude>
-                    <gco:Decimal>-54.61</gco:Decimal>
-                  </gmd:southBoundLatitude>
-                  <gmd:northBoundLatitude>
-                    <gco:Decimal>83.46</gco:Decimal>
-                  </gmd:northBoundLatitude>
-                </gmd:EX_GeographicBoundingBox>
-              </gmd:geographicElement>
-            </gmd:EX_Extent>
-          </srv:extent>
-          <srv:couplingType>
-            <srv:SV_CouplingType codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#SV_CouplingType" codeListValue="tight">tight</srv:SV_CouplingType>
-          </srv:couplingType>
-          <srv:coupledResource>
-            <srv:SV_CoupledResource>
-              <srv:operationName>
-                <gco:CharacterString>GetFeature</gco:CharacterString>
-              </srv:operationName>
-              <srv:identifier>
-                <gco:CharacterString>geoss_water_sba:Reservoir</gco:CharacterString>
-              </srv:identifier>
-            </srv:SV_CoupledResource>
-          </srv:coupledResource>
-          <srv:coupledResource>
-            <srv:SV_CoupledResource>
-              <srv:operationName>
-                <gco:CharacterString>GetFeature</gco:CharacterString>
-              </srv:operationName>
-              <srv:identifier>
-                <gco:CharacterString>geoss_water_sba:glwd_1</gco:CharacterString>
-              </srv:identifier>
-            </srv:SV_CoupledResource>
-          </srv:coupledResource>
-          <srv:coupledResource>
-            <srv:SV_CoupledResource>
-              <srv:operationName>
-                <gco:CharacterString>GetFeature</gco:CharacterString>
-              </srv:operationName>
-              <srv:identifier>
-                <gco:CharacterString>geoss_water_sba:Dams</gco:CharacterString>
-              </srv:identifier>
-            </srv:SV_CoupledResource>
-          </srv:coupledResource>
-          <srv:coupledResource>
-            <srv:SV_CoupledResource>
-              <srv:operationName>
-                <gco:CharacterString>GetFeature</gco:CharacterString>
-              </srv:operationName>
-              <srv:identifier>
-                <gco:CharacterString>geoss_water_sba:glwd_2</gco:CharacterString>
-              </srv:identifier>
-            </srv:SV_CoupledResource>
-          </srv:coupledResource>
-          <srv:coupledResource>
-            <srv:SV_CoupledResource>
-              <srv:operationName>
-                <gco:CharacterString>GetFeature</gco:CharacterString>
-              </srv:operationName>
-              <srv:identifier>
-                <gco:CharacterString>geoss_water_sba:Lakes</gco:CharacterString>
-              </srv:identifier>
-            </srv:SV_CoupledResource>
-          </srv:coupledResource>
-          <srv:containsOperations>
-            <srv:SV_OperationMetadata>
-              <srv:operationName>
-                <gco:CharacterString>GetCapabilities</gco:CharacterString>
-              </srv:operationName>
-              <srv:DCP>
-                <srv:DCPList codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#DCPList" codeListValue="HTTPGet">HTTPGet</srv:DCPList>
-              </srv:DCP>
-              <srv:DCP>
-                <srv:DCPList codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#DCPList" codeListValue="HTTPPost">HTTPPost</srv:DCPList>
-              </srv:DCP>
-              <srv:connectPoint>
-                <gmd:CI_OnlineResource>
-                  <gmd:linkage>
-                    <gmd:URL>http://services.ogc.noaa.gov/geoserver/geoss_water_sba/wfs</gmd:URL>
-                  </gmd:linkage>
-                </gmd:CI_OnlineResource>
-              </srv:connectPoint>
-            </srv:SV_OperationMetadata>
-          </srv:containsOperations>
-          <srv:containsOperations>
-            <srv:SV_OperationMetadata>
-              <srv:operationName>
-                <gco:CharacterString>DescribeFeatureType</gco:CharacterString>
-              </srv:operationName>
-              <srv:DCP>
-                <srv:DCPList codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#DCPList" codeListValue="HTTPGet">HTTPGet</srv:DCPList>
-              </srv:DCP>
-              <srv:DCP>
-                <srv:DCPList codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#DCPList" codeListValue="HTTPPost">HTTPPost</srv:DCPList>
-              </srv:DCP>
-              <srv:connectPoint>
-                <gmd:CI_OnlineResource>
-                  <gmd:linkage>
-                    <gmd:URL>http://services.ogc.noaa.gov/geoserver/geoss_water_sba/wfs</gmd:URL>
-                  </gmd:linkage>
-                </gmd:CI_OnlineResource>
-              </srv:connectPoint>
-            </srv:SV_OperationMetadata>
-          </srv:containsOperations>
-          <srv:containsOperations>
-            <srv:SV_OperationMetadata>
-              <srv:operationName>
-                <gco:CharacterString>GetFeature</gco:CharacterString>
-              </srv:operationName>
-              <srv:DCP>
-                <srv:DCPList codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#DCPList" codeListValue="HTTPGet">HTTPGet</srv:DCPList>
-              </srv:DCP>
-              <srv:DCP>
-                <srv:DCPList codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#DCPList" codeListValue="HTTPPost">HTTPPost</srv:DCPList>
-              </srv:DCP>
-              <srv:connectPoint>
-                <gmd:CI_OnlineResource>
-                  <gmd:linkage>
-                    <gmd:URL>http://services.ogc.noaa.gov/geoserver/geoss_water_sba/wfs</gmd:URL>
-                  </gmd:linkage>
-                </gmd:CI_OnlineResource>
-              </srv:connectPoint>
-            </srv:SV_OperationMetadata>
-          </srv:containsOperations>
-          <srv:containsOperations>
-            <srv:SV_OperationMetadata>
-              <srv:operationName>
-                <gco:CharacterString>GetGmlObject</gco:CharacterString>
-              </srv:operationName>
-              <srv:DCP>
-                <srv:DCPList codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#DCPList" codeListValue="HTTPGet">HTTPGet</srv:DCPList>
-              </srv:DCP>
-              <srv:DCP>
-                <srv:DCPList codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#DCPList" codeListValue="HTTPPost">HTTPPost</srv:DCPList>
-              </srv:DCP>
-              <srv:connectPoint>
-                <gmd:CI_OnlineResource>
-                  <gmd:linkage>
-                    <gmd:URL>http://services.ogc.noaa.gov/geoserver/geoss_water_sba/wfs</gmd:URL>
-                  </gmd:linkage>
-                </gmd:CI_OnlineResource>
-              </srv:connectPoint>
-            </srv:SV_OperationMetadata>
-          </srv:containsOperations>
-          <srv:containsOperations>
-            <srv:SV_OperationMetadata>
-              <srv:operationName>
-                <gco:CharacterString>LockFeature</gco:CharacterString>
-              </srv:operationName>
-              <srv:DCP>
-                <srv:DCPList codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#DCPList" codeListValue="HTTPGet">HTTPGet</srv:DCPList>
-              </srv:DCP>
-              <srv:DCP>
-                <srv:DCPList codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#DCPList" codeListValue="HTTPPost">HTTPPost</srv:DCPList>
-              </srv:DCP>
-              <srv:connectPoint>
-                <gmd:CI_OnlineResource>
-                  <gmd:linkage>
-                    <gmd:URL>http://services.ogc.noaa.gov/geoserver/geoss_water_sba/wfs</gmd:URL>
-                  </gmd:linkage>
-                </gmd:CI_OnlineResource>
-              </srv:connectPoint>
-            </srv:SV_OperationMetadata>
-          </srv:containsOperations>
-          <srv:containsOperations>
-            <srv:SV_OperationMetadata>
-              <srv:operationName>
-                <gco:CharacterString>GetFeatureWithLock</gco:CharacterString>
-              </srv:operationName>
-              <srv:DCP>
-                <srv:DCPList codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#DCPList" codeListValue="HTTPGet">HTTPGet</srv:DCPList>
-              </srv:DCP>
-              <srv:DCP>
-                <srv:DCPList codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#DCPList" codeListValue="HTTPPost">HTTPPost</srv:DCPList>
-              </srv:DCP>
-              <srv:connectPoint>
-                <gmd:CI_OnlineResource>
-                  <gmd:linkage>
-                    <gmd:URL>http://services.ogc.noaa.gov/geoserver/geoss_water_sba/wfs</gmd:URL>
-                  </gmd:linkage>
-                </gmd:CI_OnlineResource>
-              </srv:connectPoint>
-            </srv:SV_OperationMetadata>
-          </srv:containsOperations>
-          <srv:containsOperations>
-            <srv:SV_OperationMetadata>
-              <srv:operationName>
-                <gco:CharacterString>Transaction</gco:CharacterString>
-              </srv:operationName>
-              <srv:DCP>
-                <srv:DCPList codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#DCPList" codeListValue="HTTPGet">HTTPGet</srv:DCPList>
-              </srv:DCP>
-              <srv:DCP>
-                <srv:DCPList codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#DCPList" codeListValue="HTTPPost">HTTPPost</srv:DCPList>
-              </srv:DCP>
-              <srv:connectPoint>
-                <gmd:CI_OnlineResource>
-                  <gmd:linkage>
-                    <gmd:URL>http://services.ogc.noaa.gov/geoserver/geoss_water_sba/wfs</gmd:URL>
-                  </gmd:linkage>
-                </gmd:CI_OnlineResource>
-              </srv:connectPoint>
-            </srv:SV_OperationMetadata>
-          </srv:containsOperations>
-          <srv:operatesOn uuidref="geoss_water_sba:Reservoir" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/harvesting/default.cfg&service=CSW&version=2.0.2&request=GetRecordById&outputschema=http://www.isotc211.org/2005/gmd&id=PYCSW_IDENTIFIER-geoss_water_sba:Reservoir"/>
-          <srv:operatesOn uuidref="geoss_water_sba:glwd_1" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/harvesting/default.cfg&service=CSW&version=2.0.2&request=GetRecordById&outputschema=http://www.isotc211.org/2005/gmd&id=PYCSW_IDENTIFIER-geoss_water_sba:glwd_1"/>
-          <srv:operatesOn uuidref="geoss_water_sba:Dams" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/harvesting/default.cfg&service=CSW&version=2.0.2&request=GetRecordById&outputschema=http://www.isotc211.org/2005/gmd&id=PYCSW_IDENTIFIER-geoss_water_sba:Dams"/>
-          <srv:operatesOn uuidref="geoss_water_sba:glwd_2" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/harvesting/default.cfg&service=CSW&version=2.0.2&request=GetRecordById&outputschema=http://www.isotc211.org/2005/gmd&id=PYCSW_IDENTIFIER-geoss_water_sba:glwd_2"/>
-          <srv:operatesOn uuidref="geoss_water_sba:Lakes" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/harvesting/default.cfg&service=CSW&version=2.0.2&request=GetRecordById&outputschema=http://www.isotc211.org/2005/gmd&id=PYCSW_IDENTIFIER-geoss_water_sba:Lakes"/>
-        </srv:SV_ServiceIdentification>
-      </gmd:identificationInfo>
-      <gmd:distributionInfo>
-        <gmd:MD_Distribution>
-          <gmd:transferOptions>
-            <gmd:MD_DigitalTransferOptions>
-              <gmd:onLine>
-                <gmd:CI_OnlineResource>
-                  <gmd:linkage>
-                    <gmd:URL>http://services.ogc.noaa.gov/geoserver/geoss_water_sba/wfs</gmd:URL>
-                  </gmd:linkage>
-                  <gmd:protocol>
-                    <gco:CharacterString>OGC:WFS</gco:CharacterString>
-                  </gmd:protocol>
-                  <gmd:name>
-                    <gco:CharacterString>PYCSW_IDENTIFIER</gco:CharacterString>
-                  </gmd:name>
-                  <gmd:description>
-                    <gco:CharacterString>OGC-WFS Web Feature Service</gco:CharacterString>
-                  </gmd:description>
-                </gmd:CI_OnlineResource>
-              </gmd:onLine>
-            </gmd:MD_DigitalTransferOptions>
-          </gmd:transferOptions>
-        </gmd:MD_Distribution>
-      </gmd:distributionInfo>
-    </gmd:MD_Metadata>
-  </csw:SearchResults>
-</csw:GetRecordsResponse>
diff --git a/tests/functionaltests/conftest.py b/tests/functionaltests/conftest.py
new file mode 100644
index 0000000..d2949a8
--- /dev/null
+++ b/tests/functionaltests/conftest.py
@@ -0,0 +1,570 @@
+# =================================================================
+#
+# Authors: Ricardo Garcia Silva <ricardo.garcia.silva at gmail.com>
+#
+# Copyright (c) 2016 Ricardo Garcia Silva
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation
+# files (the "Software"), to deal in the Software without
+# restriction, including without limitation the rights to use,
+# copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following
+# conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+#
+# =================================================================
+"""pytest configuration file for functional tests"""
+
+import codecs
+from collections import namedtuple
+import logging
+import os
+import re
+from six.moves import configparser
+
+import apipkg
+import pytest
+
+from pycsw.core import admin
+from pycsw.core.config import StaticContext
+
+apipkg.initpkg("optionaldependencies", {
+    "psycopg2": "psycopg2",
+})
+
+from optionaldependencies import psycopg2  # NOQA: E402
+
+TESTS_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+
+SuiteDirs = namedtuple("SuiteDirs", [
+    "get_tests_dir",
+    "post_tests_dir",
+    "data_tests_dir",
+    "expected_results_dir",
+])
+
+
+def pytest_generate_tests(metafunc):
+    """Parametrize tests programmatically.
+
+    This function scans the filesystem directories under
+    ``tests/functionaltests/suites`` and automatically generates pytest tests
+    based on the available test suites. Each suite directory has the
+    following structure:
+
+    * A mandatory ``default.cfg`` file specifying the configuration for the
+      pycsw instance to use in the tests of the suite.
+
+    * An optional ``get/`` subdirectory containing a ``requests.txt`` file
+      with any HTTP GET requests for which to generate tests for. Each request
+      is specified in a new line, with the following pattern:
+
+      * <test_name>,<request_query_string>
+
+    * An optional ``post/`` subdirectory containing files that are used as the
+      payload for HTTP POST requests. The name of each file is used as the name
+      of the test (without the file's extension);
+
+    * An optional ``data/`` subdirectory. This directory, if present, indicates
+      that the suite uses a custom database. The database is populated with any
+      additional files that are contained inside this directory. If the
+      ``data`` directory does not exist then the suite's tests will use the
+      CITE database;
+
+    * An ``expected/`` subdirectory containing a file for each of the expected
+      test outcomes.
+
+    The tests are autogenerated by parametrizing the
+    ``tests/functionaltests/test_suites_functional::test_suites`` function
+
+    Notes
+    -----
+
+    Check pytest's documentation for information on autogenerating
+    parametrized tests for further details on how the
+    ``pytest_generate_tests`` function can be used:
+
+    http://pytest.org/latest/parametrize.html#basic-pytest-generate-tests-example
+
+    """
+
+    global TESTS_ROOT
+    if metafunc.function.__name__ == "test_suites":
+        suites_root_dir = os.path.join(TESTS_ROOT, "functionaltests", "suites")
+        suite_names = os.listdir(suites_root_dir)
+        arg_values = []
+        test_ids = []
+        logging.basicConfig(level=getattr(
+            logging, metafunc.config.getoption("--pycsw-loglevel").upper()))
+        if metafunc.config.getoption("--database-backend") == "postgresql":
+            _recreate_postgresql_database(metafunc.config)
+        for suite in suite_names:
+            suite_dir = os.path.join(suites_root_dir, suite)
+            config_path = os.path.join(suite_dir, "default.cfg")
+            if not os.path.isfile(config_path):
+                print("Directory {0!r} does not have a suite "
+                      "configuration file".format(suite_dir))
+                continue
+            print("Generating tests for suite {0!r}...".format(suite))
+            normalize_ids = True if suite in ("harvesting",
+                                              "manager") else False
+            suite_dirs = _get_suite_dirs(suite)
+            if suite_dirs.post_tests_dir is not None:
+                post_argvalues, post_ids = _get_post_parameters(
+                    post_tests_dir=suite_dirs.post_tests_dir,
+                    expected_tests_dir=suite_dirs.expected_results_dir,
+                    config_path=config_path,
+                    suite_name=suite,
+                    normalize_ids=normalize_ids,
+                )
+                arg_values.extend(post_argvalues)
+                test_ids.extend(post_ids)
+            if suite_dirs.get_tests_dir is not None:
+                get_argvalues, get_ids = _get_get_parameters(
+                    get_tests_dir=suite_dirs.get_tests_dir,
+                    expected_tests_dir=suite_dirs.expected_results_dir,
+                    config_path=config_path,
+                    suite_name=suite,
+                    normalize_ids=normalize_ids,
+                )
+                arg_values.extend(get_argvalues)
+                test_ids.extend(get_ids)
+        metafunc.parametrize(
+            argnames=["configuration", "request_method", "request_data",
+                      "expected_result", "normalize_identifier_fields",],
+            argvalues=arg_values,
+            indirect=["configuration"],
+            ids=test_ids,
+        )
+
+ at pytest.fixture()
+def test_identifier(request):
+    """Extract a meaningful identifier from the request's node."""
+    return re.search(r"[\w_]+\[(.*)\]", request.node.name).group(1)
+
+
+ at pytest.fixture()
+def use_xml_canonicalisation(request):
+    return not request.config.getoption("--functional-prefer-diffs")
+
+
+ at pytest.fixture()
+def save_results_directory(request):
+    return request.config.getoption("--functional-save-results-directory")
+
+
+ at pytest.fixture()
+def configuration(request, tests_directory, log_level):
+    """Configure a suite for execution in tests.
+
+    This function is executed once for each individual test request, after
+    tests have been collected.
+
+    The configuration file for each test suite is read into memory. Some
+    configuration parameters, like the repository's url and table name are
+    adjusted. The suite's repository is also created, if needed.
+
+    Parameters
+    ----------
+    request: pytest.fixtures.FixtureRequest
+    tests_directory: py.path.local
+        Directory created by pytest where any test artifacts are to be saved
+    log_level: str
+        Log level for the pycsw server instance that will be created during
+        tests.
+
+    """
+
+    config_path = request.param
+    config = configparser.SafeConfigParser()
+    with codecs.open(config_path, encoding="utf-8") as fh:
+        config.readfp(fh)
+    suite_name = config_path.split(os.path.sep)[-2]
+    suite_dirs = _get_suite_dirs(suite_name)
+    data_dir = suite_dirs.data_tests_dir
+    if data_dir is not None:  # suite has its own database
+        repository_url = _get_repository_url(request.config, suite_name,
+                                             tests_directory)
+    else:  # suite uses the CITE database
+        data_dir = _get_cite_suite_data_dir()
+        repository_url = _get_repository_url(request.config, "cite",
+                                             tests_directory)
+    table_name = _get_table_name(suite_name, config, repository_url)
+    if not _repository_exists(repository_url, table_name):
+        _initialize_database(repository_url=repository_url,
+                             table_name=table_name,
+                             data_dir=data_dir,
+                             test_dir=tests_directory)
+    config.set("server", "loglevel", log_level)
+    config.set("server", "logfile", "")
+    config.set("repository", "database", repository_url)
+    config.set("repository", "table", table_name)
+    return config
+
+
+ at pytest.fixture(scope="session", name="tests_directory")
+def fixture_tests_directory(tmpdir_factory):
+    """Create a temporary directory for each test session.
+
+    This directory is typically situated under ``/tmp`` and is used to create
+    eventual sqlite databases for each suite.
+
+    This functionality is mostly provided by pytest's built-in
+    ``tmpdir_factory`` fixture. More information on this is available at:
+
+    http://doc.pytest.org/en/2.9.0/tmpdir.html#the-tmpdir-factory-fixture
+
+    """
+
+    tests_dir = tmpdir_factory.mktemp("functional_tests")
+    return tests_dir
+
+
+def _get_cite_suite_data_dir():
+    """Return the path to the data directory of the CITE test suite."""
+    global TESTS_ROOT
+    suites_root_dir = os.path.join(TESTS_ROOT, "functionaltests", "suites")
+    suite_dir = os.path.join(suites_root_dir, "cite")
+    data_tests_dir = os.path.join(suite_dir, "data")
+    data_dir = data_tests_dir if os.path.isdir(data_tests_dir) else None
+    return data_dir
+
+
+def _get_get_parameters(get_tests_dir, expected_tests_dir, config_path,
+                        suite_name, normalize_ids):
+    """Return the parameters suitable for parametrizing HTTP GET tests."""
+    method = "GET"
+    test_argvalues = []
+    test_ids = []
+    requests_file_path = os.path.join(get_tests_dir, "requests.txt")
+    with open(requests_file_path) as fh:
+        for line in fh:
+            test_name, test_params = [i.strip() for i in
+                                      line.partition(",")[::2]]
+            expected_result_path = os.path.join(
+                expected_tests_dir,
+                "{method}_{name}.xml".format(method=method.lower(),
+                                             name=test_name)
+            )
+            test_argvalues.append(
+                (config_path, method, test_params, expected_result_path,
+                 normalize_ids)
+            )
+            test_ids.append(
+                "{suite}_{http_method}_{name}".format(
+                    suite=suite_name, http_method=method.lower(),
+                    name=test_name)
+            )
+    return test_argvalues, test_ids
+
+
+def _get_post_parameters(post_tests_dir, expected_tests_dir, config_path,
+                         suite_name, normalize_ids):
+    """Return the parameters suitable for parametrizing HTTP POST tests."""
+    method = "POST"
+    test_argvalues = []
+    test_ids = []
+    # we are sorting the directory contents because the
+    # `harvesting` suite requires tests to be executed in alphabetical order
+    directory_contents = sorted(os.listdir(post_tests_dir))
+    for request_file_name in directory_contents:
+        request_path = os.path.join(post_tests_dir,
+                                    request_file_name)
+        expected_result_path = os.path.join(
+            expected_tests_dir,
+            "{method}_{filename}".format(
+                method=method.lower(),
+                filename=request_file_name
+            )
+        )
+        test_argvalues.append(
+            (config_path, method, request_path,
+             expected_result_path, normalize_ids)
+        )
+        test_ids.append(
+            "{suite}_{http_method}_{file_name}".format(
+                suite=suite_name,
+                http_method=method.lower(),
+                file_name=os.path.splitext(
+                    request_file_name)[0])
+        )
+    return test_argvalues, test_ids
+
+
+def _get_repository_url(conf, suite_name, test_dir):
+    """Return the repository_url for the input parameters.
+
+    Returns
+    -------
+    repository_url: str
+        SQLAlchemy URL for the repository in use.
+
+    """
+
+    db_type = conf.getoption("--database-backend")
+    if db_type == "sqlite":
+        repository_url = "sqlite:///{test_dir}/{suite}.db".format(
+            test_dir=test_dir, suite=suite_name)
+    elif db_type == "postgresql":
+        repository_url = (
+            "postgresql://{user}:{password}@{host}:{port}/{database}".format(
+                user=conf.getoption("--database-user-postgresql"),
+                password=conf.getoption("--database-password-postgresql"),
+                host=conf.getoption("--database-host-postgresql"),
+                port=conf.getoption("--database-port-postgresql"),
+                database=conf.getoption("--database-name-postgresql"))
+        )
+    else:
+        raise NotImplementedError
+    return repository_url
+
+
+def _get_suite_dirs(suite_name):
+    """Get the paths to relevant suite directories.
+
+    Parameters
+    ----------
+    suite_name: str
+        Name of the site
+
+    Returns
+    -------
+    SuiteDirs
+        A four element named tuple with the input suite's relevant test
+        directories.
+
+    """
+
+    global TESTS_ROOT
+    suites_root_dir = os.path.join(TESTS_ROOT, "functionaltests", "suites")
+    suite_dir = os.path.join(suites_root_dir, suite_name)
+    data_tests_dir = os.path.join(suite_dir, "data")
+    post_tests_dir = os.path.join(suite_dir, "post")
+    get_tests_dir = os.path.join(suite_dir, "get")
+    expected_results_dir = os.path.join(suite_dir, "expected")
+    data_dir = data_tests_dir if os.path.isdir(data_tests_dir) else None
+    posts_dir = post_tests_dir if os.path.isdir(post_tests_dir) else None
+    gets_dir = get_tests_dir if os.path.isdir(get_tests_dir) else None
+    expected_dir = (expected_results_dir if os.path.isdir(
+        expected_results_dir) else None)
+    return SuiteDirs(get_tests_dir=gets_dir,
+                     post_tests_dir=posts_dir,
+                     data_tests_dir=data_dir,
+                     expected_results_dir=expected_dir)
+
+
+def _get_table_name(suite, config, repository_url):
+    """Get the name of the table used to store records in the database.
+
+    Parameters
+    ----------
+    suite: str
+        Name of the suite.
+    config: SafeConfigParser
+        Configuration for the suite.
+    repository_url: str
+        SQLAlchemy URL for the repository in use.
+
+    Returns
+    -------
+    str
+        Name of the table to use in the database
+
+    """
+
+    if repository_url.startswith("sqlite"):
+        result = config.get("repository", "table")
+    elif repository_url.startswith("postgresql"):
+        result = "{suite}_records".format(suite=suite)
+    else:
+        raise NotImplementedError
+    return result
+
+
+def _initialize_database(repository_url, table_name, data_dir, test_dir):
+    """Initialize database for tests.
+
+    This function will create the database and load any test data that
+    the suite may require.
+
+    Parameters
+    ----------
+    repository_url: str
+        URL for the repository, as used by SQLAlchemy engines
+    table_name: str
+        Name of the table that is to be used to store pycsw records
+    data_dir: str
+        Path to a directory that contains sample data records to be loaded
+        into the database
+    test_dir: str
+        Directory where the database is to be created, in case of sqlite.
+
+    """
+
+    print("Setting up {0!r} repository...".format(repository_url))
+    if repository_url.startswith("postgresql"):
+        extra_kwargs = {
+            "create_sfsql_tables": True,
+            "create_plpythonu_functions": False
+        }
+    else:
+        extra_kwargs = {}
+    admin.setup_db(database=repository_url, table=table_name, home=test_dir,
+                   **extra_kwargs)
+    if len(os.listdir(data_dir)) > 0:
+        print("Loading database data...")
+        admin.load_records(context=StaticContext(), database=repository_url,
+                           table=table_name, xml_dirpath=data_dir)
+
+
+def _parse_postgresql_repository_url(repository_url):
+    """Parse a SQLAlchemy engine URL describing a postgresql database.
+
+    Parameters
+    ----------
+    repository_url: str
+        SQLAlchemy URL for the repository in use.
+
+    Returns
+    -------
+    dict
+        A mapping with the database's connection parameters.
+
+    """
+
+    info_re = re.search(r"postgresql://(?P<user>[\w_]+):(?P<password>.*?)@"
+                        r"(?P<host>[\w_.]+):(?P<port>\d+)/"
+                        r"(?P<database>[\w_]+)",
+                        repository_url,
+                        flags=re.UNICODE)
+    try:
+        db_info = info_re.groupdict()
+    except AttributeError:
+        raise RuntimeError("Could not parse repository url {0!r}".format(
+            repository_url))
+    else:
+        return db_info
+
+
+def _recreate_postgresql_database(configuration):
+    """Recreate a postgresql database.
+
+    This function will try to create a new postgresql database for testing
+    purposes. If the database already exists it is deleted and then recreated.
+
+    Parameters
+    ----------
+    configuration: _pytest.config.Config
+        The configuration object used by pytest
+
+    Raises
+    ------
+    RuntimeError
+        If a connection to the postgresql server cannot be made
+
+    """
+
+    connection = psycopg2.connect(
+        database="postgres",
+        user=configuration.getoption("--database-user-postgresql"),
+        password=configuration.getoption("--database-password-postgresql"),
+        host=configuration.getoption("--database-host-postgresql"),
+        port=configuration.getoption("--database-port-postgresql")
+    )
+    connection.set_isolation_level(
+        psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT)
+    cursor = connection.cursor()
+    db_name = configuration.getoption("--database-name-postgresql")
+    cursor.execute("DROP DATABASE IF EXISTS {database}".format(
+        database=db_name))
+    cursor.execute("CREATE DATABASE {database}".format(database=db_name))
+    cursor.execute(
+        "SELECT COUNT(1) FROM pg_available_extensions WHERE name='postgis'")
+    postgis_available = bool(cursor.fetchone()[0])
+    cursor.close()
+    connection.close()
+    if postgis_available:
+        _create_postgresql_extension(configuration, extension="postgis")
+    else:
+        _create_postgresql_extension(configuration, extension="plpythonu")
+
+
+def _create_postgresql_extension(configuration, extension):
+    """Create a postgresql extension in a previously created database.
+
+    Parameters
+    ----------
+    configuration: _pytest.config.Config
+        The configuration object used by pytest
+    extension: str
+        Name of the extension to be created
+
+    """
+
+    connection = psycopg2.connect(
+        database=configuration.getoption("--database-name-postgresql"),
+        user=configuration.getoption("--database-user-postgresql"),
+        password=configuration.getoption("--database-password-postgresql"),
+        host=configuration.getoption("--database-host-postgresql"),
+        port=configuration.getoption("--database-port-postgresql")
+    )
+    connection.set_isolation_level(
+        psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT)
+    cursor = connection.cursor()
+    cursor.execute("CREATE EXTENSION {0}".format(extension))
+    cursor.close()
+    connection.close()
+
+
+def _repository_exists(repository_url, table_name):
+    """Test if the database already exists.
+
+    Parameters
+    ----------
+    repository_url: str
+        URL for the repository, as used by SQLAlchemy engines
+    table_name: str
+        Name of the table that is to be used to store pycsw records
+
+    Returns
+    -------
+    bool
+        Whether the repository exists or not.
+
+    """
+
+    if repository_url.startswith("sqlite"):
+        repository_path = repository_url.replace("sqlite:///", "")
+        result = os.path.isfile(repository_path)
+    elif repository_url.startswith("postgresql"):
+        db_info = _parse_postgresql_repository_url(repository_url)
+        try:
+            connection = psycopg2.connect(user=db_info["user"],
+                                          password=db_info["password"],
+                                          host=db_info["host"],
+                                          port=db_info["port"],
+                                          database=db_info["database"])
+            cursor = connection.cursor()
+            cursor.execute("SELECT COUNT(1) FROM {table_name}".format(
+                table_name=table_name))
+        except (psycopg2.OperationalError, psycopg2.ProgrammingError):
+            # database or table does not exist yet
+            result = False
+        else:
+            result = True
+    else:
+        raise NotImplementedError
+    return result
diff --git a/tests/suites/apiso-inspire/default.cfg b/tests/functionaltests/suites/apiso-inspire/default.cfg
similarity index 100%
rename from tests/suites/apiso-inspire/default.cfg
rename to tests/functionaltests/suites/apiso-inspire/default.cfg
diff --git a/tests/expected/suites_apiso-inspire_get_GetCapabilities-lang.xml b/tests/functionaltests/suites/apiso-inspire/expected/get_GetCapabilities-lang.xml
similarity index 100%
rename from tests/expected/suites_apiso-inspire_get_GetCapabilities-lang.xml
rename to tests/functionaltests/suites/apiso-inspire/expected/get_GetCapabilities-lang.xml
diff --git a/tests/expected/suites_apiso-inspire_get_GetCapabilities.xml b/tests/functionaltests/suites/apiso-inspire/expected/get_GetCapabilities.xml
similarity index 100%
rename from tests/expected/suites_apiso-inspire_get_GetCapabilities.xml
rename to tests/functionaltests/suites/apiso-inspire/expected/get_GetCapabilities.xml
diff --git a/tests/functionaltests/suites/apiso-inspire/get/requests.txt b/tests/functionaltests/suites/apiso-inspire/get/requests.txt
new file mode 100644
index 0000000..09816a2
--- /dev/null
+++ b/tests/functionaltests/suites/apiso-inspire/get/requests.txt
@@ -0,0 +1,2 @@
+GetCapabilities,service=CSW&version=2.0.2&request=GetCapabilities
+GetCapabilities-lang,service=CSW&version=2.0.2&request=GetCapabilities&lang=gre
diff --git a/tests/suites/apiso/data/3e9a8c05.xml b/tests/functionaltests/suites/apiso/data/3e9a8c05.xml
similarity index 100%
rename from tests/suites/apiso/data/3e9a8c05.xml
rename to tests/functionaltests/suites/apiso/data/3e9a8c05.xml
diff --git a/tests/suites/apiso/data/README.txt b/tests/functionaltests/suites/apiso/data/README.txt
similarity index 100%
rename from tests/suites/apiso/data/README.txt
rename to tests/functionaltests/suites/apiso/data/README.txt
diff --git a/tests/suites/apiso/data/T_aerfo_RAS_1991_GR800P001800000012.xml b/tests/functionaltests/suites/apiso/data/T_aerfo_RAS_1991_GR800P001800000012.xml
similarity index 100%
rename from tests/suites/apiso/data/T_aerfo_RAS_1991_GR800P001800000012.xml
rename to tests/functionaltests/suites/apiso/data/T_aerfo_RAS_1991_GR800P001800000012.xml
diff --git a/tests/suites/apiso/data/T_aerfo_RAS_1991_GR800P001800000013.xml b/tests/functionaltests/suites/apiso/data/T_aerfo_RAS_1991_GR800P001800000013.xml
similarity index 100%
rename from tests/suites/apiso/data/T_aerfo_RAS_1991_GR800P001800000013.xml
rename to tests/functionaltests/suites/apiso/data/T_aerfo_RAS_1991_GR800P001800000013.xml
diff --git a/tests/suites/apiso/data/T_aerfo_RAS_1991_GR800P001800000014.xml b/tests/functionaltests/suites/apiso/data/T_aerfo_RAS_1991_GR800P001800000014.xml
similarity index 100%
rename from tests/suites/apiso/data/T_aerfo_RAS_1991_GR800P001800000014.xml
rename to tests/functionaltests/suites/apiso/data/T_aerfo_RAS_1991_GR800P001800000014.xml
diff --git a/tests/suites/apiso/data/T_aerfo_RAS_1991_GR800P001800000015.xml b/tests/functionaltests/suites/apiso/data/T_aerfo_RAS_1991_GR800P001800000015.xml
similarity index 100%
rename from tests/suites/apiso/data/T_aerfo_RAS_1991_GR800P001800000015.xml
rename to tests/functionaltests/suites/apiso/data/T_aerfo_RAS_1991_GR800P001800000015.xml
diff --git a/tests/suites/apiso/data/T_ortho_RAS_1998_284404.xml b/tests/functionaltests/suites/apiso/data/T_ortho_RAS_1998_284404.xml
similarity index 100%
rename from tests/suites/apiso/data/T_ortho_RAS_1998_284404.xml
rename to tests/functionaltests/suites/apiso/data/T_ortho_RAS_1998_284404.xml
diff --git a/tests/suites/apiso/data/T_ortho_RAS_1998_288395.xml b/tests/functionaltests/suites/apiso/data/T_ortho_RAS_1998_288395.xml
similarity index 100%
rename from tests/suites/apiso/data/T_ortho_RAS_1998_288395.xml
rename to tests/functionaltests/suites/apiso/data/T_ortho_RAS_1998_288395.xml
diff --git a/tests/suites/apiso/data/T_ortho_RAS_1998_288398.xml b/tests/functionaltests/suites/apiso/data/T_ortho_RAS_1998_288398.xml
similarity index 100%
rename from tests/suites/apiso/data/T_ortho_RAS_1998_288398.xml
rename to tests/functionaltests/suites/apiso/data/T_ortho_RAS_1998_288398.xml
diff --git a/tests/suites/apiso/data/T_ortho_RAS_1998_288401.xml b/tests/functionaltests/suites/apiso/data/T_ortho_RAS_1998_288401.xml
similarity index 100%
rename from tests/suites/apiso/data/T_ortho_RAS_1998_288401.xml
rename to tests/functionaltests/suites/apiso/data/T_ortho_RAS_1998_288401.xml
diff --git a/tests/suites/apiso/data/T_ortho_RAS_1998_288404.xml b/tests/functionaltests/suites/apiso/data/T_ortho_RAS_1998_288404.xml
similarity index 100%
rename from tests/suites/apiso/data/T_ortho_RAS_1998_288404.xml
rename to tests/functionaltests/suites/apiso/data/T_ortho_RAS_1998_288404.xml
diff --git a/tests/suites/apiso/data/T_pmoed_DTM_1996_276395.xml b/tests/functionaltests/suites/apiso/data/T_pmoed_DTM_1996_276395.xml
similarity index 100%
rename from tests/suites/apiso/data/T_pmoed_DTM_1996_276395.xml
rename to tests/functionaltests/suites/apiso/data/T_pmoed_DTM_1996_276395.xml
diff --git a/tests/suites/apiso/data/T_pmoed_DTM_1996_276398.xml b/tests/functionaltests/suites/apiso/data/T_pmoed_DTM_1996_276398.xml
similarity index 100%
rename from tests/suites/apiso/data/T_pmoed_DTM_1996_276398.xml
rename to tests/functionaltests/suites/apiso/data/T_pmoed_DTM_1996_276398.xml
diff --git a/tests/suites/apiso/data/T_pmoed_DTM_1996_276401.xml b/tests/functionaltests/suites/apiso/data/T_pmoed_DTM_1996_276401.xml
similarity index 100%
rename from tests/suites/apiso/data/T_pmoed_DTM_1996_276401.xml
rename to tests/functionaltests/suites/apiso/data/T_pmoed_DTM_1996_276401.xml
diff --git a/tests/suites/apiso/data/T_pmoed_DTM_1996_276404.xml b/tests/functionaltests/suites/apiso/data/T_pmoed_DTM_1996_276404.xml
similarity index 100%
rename from tests/suites/apiso/data/T_pmoed_DTM_1996_276404.xml
rename to tests/functionaltests/suites/apiso/data/T_pmoed_DTM_1996_276404.xml
diff --git a/tests/suites/apiso/data/T_pmoed_DTM_1996_280395.xml b/tests/functionaltests/suites/apiso/data/T_pmoed_DTM_1996_280395.xml
similarity index 100%
rename from tests/suites/apiso/data/T_pmoed_DTM_1996_280395.xml
rename to tests/functionaltests/suites/apiso/data/T_pmoed_DTM_1996_280395.xml
diff --git a/tests/suites/apiso/data/pacioos-NS06agg.xml b/tests/functionaltests/suites/apiso/data/pacioos-NS06agg.xml
similarity index 100%
rename from tests/suites/apiso/data/pacioos-NS06agg.xml
rename to tests/functionaltests/suites/apiso/data/pacioos-NS06agg.xml
diff --git a/tests/suites/apiso/data/test.xml b/tests/functionaltests/suites/apiso/data/test.xml
similarity index 100%
rename from tests/suites/apiso/data/test.xml
rename to tests/functionaltests/suites/apiso/data/test.xml
diff --git a/tests/suites/apiso/default.cfg b/tests/functionaltests/suites/apiso/default.cfg
similarity index 100%
rename from tests/suites/apiso/default.cfg
rename to tests/functionaltests/suites/apiso/default.cfg
diff --git a/tests/expected/suites_apiso_post_DescribeRecord.xml b/tests/functionaltests/suites/apiso/expected/post_DescribeRecord.xml
similarity index 100%
rename from tests/expected/suites_apiso_post_DescribeRecord.xml
rename to tests/functionaltests/suites/apiso/expected/post_DescribeRecord.xml
diff --git a/tests/expected/suites_apiso_post_GetCapabilities.xml b/tests/functionaltests/suites/apiso/expected/post_GetCapabilities.xml
similarity index 100%
rename from tests/expected/suites_apiso_post_GetCapabilities.xml
rename to tests/functionaltests/suites/apiso/expected/post_GetCapabilities.xml
diff --git a/tests/expected/suites_apiso_post_GetDomain-property.xml b/tests/functionaltests/suites/apiso/expected/post_GetDomain-property.xml
similarity index 100%
rename from tests/expected/suites_apiso_post_GetDomain-property.xml
rename to tests/functionaltests/suites/apiso/expected/post_GetDomain-property.xml
diff --git a/tests/expected/suites_apiso_post_GetRecordById-brief.xml b/tests/functionaltests/suites/apiso/expected/post_GetRecordById-brief.xml
similarity index 100%
rename from tests/expected/suites_apiso_post_GetRecordById-brief.xml
rename to tests/functionaltests/suites/apiso/expected/post_GetRecordById-brief.xml
diff --git a/tests/expected/suites_apiso_post_GetRecordById-full-dc.xml b/tests/functionaltests/suites/apiso/expected/post_GetRecordById-full-dc.xml
similarity index 100%
rename from tests/expected/suites_apiso_post_GetRecordById-full-dc.xml
rename to tests/functionaltests/suites/apiso/expected/post_GetRecordById-full-dc.xml
diff --git a/tests/expected/suites_apiso_post_GetRecordById-full.xml b/tests/functionaltests/suites/apiso/expected/post_GetRecordById-full.xml
similarity index 100%
rename from tests/expected/suites_apiso_post_GetRecordById-full.xml
rename to tests/functionaltests/suites/apiso/expected/post_GetRecordById-full.xml
diff --git a/tests/expected/suites_apiso_post_GetRecordById-srv-brief.xml b/tests/functionaltests/suites/apiso/expected/post_GetRecordById-srv-brief.xml
similarity index 100%
rename from tests/expected/suites_apiso_post_GetRecordById-srv-brief.xml
rename to tests/functionaltests/suites/apiso/expected/post_GetRecordById-srv-brief.xml
diff --git a/tests/expected/suites_apiso_post_GetRecords-all-csw-output.xml b/tests/functionaltests/suites/apiso/expected/post_GetRecords-all-csw-output.xml
similarity index 100%
rename from tests/expected/suites_apiso_post_GetRecords-all-csw-output.xml
rename to tests/functionaltests/suites/apiso/expected/post_GetRecords-all-csw-output.xml
diff --git a/tests/expected/suites_apiso_post_GetRecords-all.xml b/tests/functionaltests/suites/apiso/expected/post_GetRecords-all.xml
similarity index 100%
rename from tests/expected/suites_apiso_post_GetRecords-all.xml
rename to tests/functionaltests/suites/apiso/expected/post_GetRecords-all.xml
diff --git a/tests/expected/suites_apiso_post_GetRecords-cql-title.xml b/tests/functionaltests/suites/apiso/expected/post_GetRecords-cql-title.xml
similarity index 100%
rename from tests/expected/suites_apiso_post_GetRecords-cql-title.xml
rename to tests/functionaltests/suites/apiso/expected/post_GetRecords-cql-title.xml
diff --git a/tests/expected/suites_apiso_post_GetRecords-elementname.xml b/tests/functionaltests/suites/apiso/expected/post_GetRecords-elementname.xml
similarity index 100%
rename from tests/expected/suites_apiso_post_GetRecords-elementname.xml
rename to tests/functionaltests/suites/apiso/expected/post_GetRecords-elementname.xml
diff --git a/tests/expected/suites_apiso_post_GetRecords-filter-and-nested-spatial-or-dateline.xml b/tests/functionaltests/suites/apiso/expected/post_GetRecords-filter-and-nested-spatial-or-dateline.xml
similarity index 100%
rename from tests/expected/suites_apiso_post_GetRecords-filter-and-nested-spatial-or-dateline.xml
rename to tests/functionaltests/suites/apiso/expected/post_GetRecords-filter-and-nested-spatial-or-dateline.xml
diff --git a/tests/expected/suites_apiso_post_GetRecords-filter-anytext.xml b/tests/functionaltests/suites/apiso/expected/post_GetRecords-filter-anytext.xml
similarity index 100%
rename from tests/expected/suites_apiso_post_GetRecords-filter-anytext.xml
rename to tests/functionaltests/suites/apiso/expected/post_GetRecords-filter-anytext.xml
diff --git a/tests/expected/suites_apiso_post_GetRecords-filter-bbox-csw-output.xml b/tests/functionaltests/suites/apiso/expected/post_GetRecords-filter-bbox-csw-output.xml
similarity index 100%
rename from tests/expected/suites_apiso_post_GetRecords-filter-bbox-csw-output.xml
rename to tests/functionaltests/suites/apiso/expected/post_GetRecords-filter-bbox-csw-output.xml
diff --git a/tests/expected/suites_apiso_post_GetRecords-filter-bbox.xml b/tests/functionaltests/suites/apiso/expected/post_GetRecords-filter-bbox.xml
similarity index 100%
rename from tests/expected/suites_apiso_post_GetRecords-filter-bbox.xml
rename to tests/functionaltests/suites/apiso/expected/post_GetRecords-filter-bbox.xml
diff --git a/tests/expected/suites_apiso_post_GetRecords-filter-servicetype.xml b/tests/functionaltests/suites/apiso/expected/post_GetRecords-filter-servicetype.xml
similarity index 100%
rename from tests/expected/suites_apiso_post_GetRecords-filter-servicetype.xml
rename to tests/functionaltests/suites/apiso/expected/post_GetRecords-filter-servicetype.xml
diff --git a/tests/suites/apiso/post/DescribeRecord.xml b/tests/functionaltests/suites/apiso/post/DescribeRecord.xml
similarity index 100%
rename from tests/suites/apiso/post/DescribeRecord.xml
rename to tests/functionaltests/suites/apiso/post/DescribeRecord.xml
diff --git a/tests/suites/apiso/post/GetCapabilities.xml b/tests/functionaltests/suites/apiso/post/GetCapabilities.xml
similarity index 100%
rename from tests/suites/apiso/post/GetCapabilities.xml
rename to tests/functionaltests/suites/apiso/post/GetCapabilities.xml
diff --git a/tests/suites/apiso/post/GetDomain-property.xml b/tests/functionaltests/suites/apiso/post/GetDomain-property.xml
similarity index 100%
rename from tests/suites/apiso/post/GetDomain-property.xml
rename to tests/functionaltests/suites/apiso/post/GetDomain-property.xml
diff --git a/tests/suites/apiso/post/GetRecordById-brief.xml b/tests/functionaltests/suites/apiso/post/GetRecordById-brief.xml
similarity index 100%
rename from tests/suites/apiso/post/GetRecordById-brief.xml
rename to tests/functionaltests/suites/apiso/post/GetRecordById-brief.xml
diff --git a/tests/suites/apiso/post/GetRecordById-full-dc.xml b/tests/functionaltests/suites/apiso/post/GetRecordById-full-dc.xml
similarity index 100%
rename from tests/suites/apiso/post/GetRecordById-full-dc.xml
rename to tests/functionaltests/suites/apiso/post/GetRecordById-full-dc.xml
diff --git a/tests/suites/apiso/post/GetRecordById-full.xml b/tests/functionaltests/suites/apiso/post/GetRecordById-full.xml
similarity index 100%
rename from tests/suites/apiso/post/GetRecordById-full.xml
rename to tests/functionaltests/suites/apiso/post/GetRecordById-full.xml
diff --git a/tests/suites/apiso/post/GetRecordById-srv-brief.xml b/tests/functionaltests/suites/apiso/post/GetRecordById-srv-brief.xml
similarity index 100%
rename from tests/suites/apiso/post/GetRecordById-srv-brief.xml
rename to tests/functionaltests/suites/apiso/post/GetRecordById-srv-brief.xml
diff --git a/tests/suites/apiso/post/GetRecords-all-csw-output.xml b/tests/functionaltests/suites/apiso/post/GetRecords-all-csw-output.xml
similarity index 100%
rename from tests/suites/apiso/post/GetRecords-all-csw-output.xml
rename to tests/functionaltests/suites/apiso/post/GetRecords-all-csw-output.xml
diff --git a/tests/suites/apiso/post/GetRecords-all.xml b/tests/functionaltests/suites/apiso/post/GetRecords-all.xml
similarity index 100%
rename from tests/suites/apiso/post/GetRecords-all.xml
rename to tests/functionaltests/suites/apiso/post/GetRecords-all.xml
diff --git a/tests/suites/apiso/post/GetRecords-cql-title.xml b/tests/functionaltests/suites/apiso/post/GetRecords-cql-title.xml
similarity index 100%
rename from tests/suites/apiso/post/GetRecords-cql-title.xml
rename to tests/functionaltests/suites/apiso/post/GetRecords-cql-title.xml
diff --git a/tests/suites/apiso/post/GetRecords-elementname.xml b/tests/functionaltests/suites/apiso/post/GetRecords-elementname.xml
similarity index 100%
rename from tests/suites/apiso/post/GetRecords-elementname.xml
rename to tests/functionaltests/suites/apiso/post/GetRecords-elementname.xml
diff --git a/tests/suites/apiso/post/GetRecords-filter-and-nested-spatial-or-dateline.xml b/tests/functionaltests/suites/apiso/post/GetRecords-filter-and-nested-spatial-or-dateline.xml
similarity index 100%
rename from tests/suites/apiso/post/GetRecords-filter-and-nested-spatial-or-dateline.xml
rename to tests/functionaltests/suites/apiso/post/GetRecords-filter-and-nested-spatial-or-dateline.xml
diff --git a/tests/suites/apiso/post/GetRecords-filter-anytext.xml b/tests/functionaltests/suites/apiso/post/GetRecords-filter-anytext.xml
similarity index 100%
rename from tests/suites/apiso/post/GetRecords-filter-anytext.xml
rename to tests/functionaltests/suites/apiso/post/GetRecords-filter-anytext.xml
diff --git a/tests/suites/apiso/post/GetRecords-filter-bbox-csw-output.xml b/tests/functionaltests/suites/apiso/post/GetRecords-filter-bbox-csw-output.xml
similarity index 100%
rename from tests/suites/apiso/post/GetRecords-filter-bbox-csw-output.xml
rename to tests/functionaltests/suites/apiso/post/GetRecords-filter-bbox-csw-output.xml
diff --git a/tests/suites/apiso/post/GetRecords-filter-bbox.xml b/tests/functionaltests/suites/apiso/post/GetRecords-filter-bbox.xml
similarity index 100%
rename from tests/suites/apiso/post/GetRecords-filter-bbox.xml
rename to tests/functionaltests/suites/apiso/post/GetRecords-filter-bbox.xml
diff --git a/tests/suites/apiso/post/GetRecords-filter-servicetype.xml b/tests/functionaltests/suites/apiso/post/GetRecords-filter-servicetype.xml
similarity index 100%
rename from tests/suites/apiso/post/GetRecords-filter-servicetype.xml
rename to tests/functionaltests/suites/apiso/post/GetRecords-filter-servicetype.xml
diff --git a/tests/suites/atom/default.cfg b/tests/functionaltests/suites/atom/default.cfg
similarity index 100%
rename from tests/suites/atom/default.cfg
rename to tests/functionaltests/suites/atom/default.cfg
diff --git a/tests/expected/suites_atom_get_opensearch-description.xml b/tests/functionaltests/suites/atom/expected/get_opensearch-description.xml
similarity index 100%
rename from tests/expected/suites_atom_get_opensearch-description.xml
rename to tests/functionaltests/suites/atom/expected/get_opensearch-description.xml
diff --git a/tests/expected/suites_atom_get_opensearch-ogc-bbox-and-time.xml b/tests/functionaltests/suites/atom/expected/get_opensearch-ogc-bbox-and-time.xml
similarity index 100%
rename from tests/expected/suites_atom_get_opensearch-ogc-bbox-and-time.xml
rename to tests/functionaltests/suites/atom/expected/get_opensearch-ogc-bbox-and-time.xml
diff --git a/tests/expected/suites_atom_get_opensearch-ogc-bbox.xml b/tests/functionaltests/suites/atom/expected/get_opensearch-ogc-bbox.xml
similarity index 100%
rename from tests/expected/suites_atom_get_opensearch-ogc-bbox.xml
rename to tests/functionaltests/suites/atom/expected/get_opensearch-ogc-bbox.xml
diff --git a/tests/expected/suites_atom_get_opensearch-ogc-count-and-page1.xml b/tests/functionaltests/suites/atom/expected/get_opensearch-ogc-count-and-page1.xml
similarity index 100%
rename from tests/expected/suites_atom_get_opensearch-ogc-count-and-page1.xml
rename to tests/functionaltests/suites/atom/expected/get_opensearch-ogc-count-and-page1.xml
diff --git a/tests/expected/suites_atom_get_opensearch-ogc-count-and-page2.xml b/tests/functionaltests/suites/atom/expected/get_opensearch-ogc-count-and-page2.xml
similarity index 100%
rename from tests/expected/suites_atom_get_opensearch-ogc-count-and-page2.xml
rename to tests/functionaltests/suites/atom/expected/get_opensearch-ogc-count-and-page2.xml
diff --git a/tests/expected/suites_atom_get_opensearch-ogc-q-and-bbox.xml b/tests/functionaltests/suites/atom/expected/get_opensearch-ogc-q-and-bbox.xml
similarity index 100%
rename from tests/expected/suites_atom_get_opensearch-ogc-q-and-bbox.xml
rename to tests/functionaltests/suites/atom/expected/get_opensearch-ogc-q-and-bbox.xml
diff --git a/tests/expected/suites_atom_get_opensearch-ogc-q-and-time.xml b/tests/functionaltests/suites/atom/expected/get_opensearch-ogc-q-and-time.xml
similarity index 100%
rename from tests/expected/suites_atom_get_opensearch-ogc-q-and-time.xml
rename to tests/functionaltests/suites/atom/expected/get_opensearch-ogc-q-and-time.xml
diff --git a/tests/expected/suites_atom_get_opensearch-ogc-q.xml b/tests/functionaltests/suites/atom/expected/get_opensearch-ogc-q.xml
similarity index 100%
rename from tests/expected/suites_atom_get_opensearch-ogc-q.xml
rename to tests/functionaltests/suites/atom/expected/get_opensearch-ogc-q.xml
diff --git a/tests/expected/suites_atom_get_opensearch-ogc-time.xml b/tests/functionaltests/suites/atom/expected/get_opensearch-ogc-time.xml
similarity index 100%
rename from tests/expected/suites_atom_get_opensearch-ogc-time.xml
rename to tests/functionaltests/suites/atom/expected/get_opensearch-ogc-time.xml
diff --git a/tests/expected/suites_atom_get_opensearch-ogc-timeend.xml b/tests/functionaltests/suites/atom/expected/get_opensearch-ogc-timeend.xml
similarity index 100%
rename from tests/expected/suites_atom_get_opensearch-ogc-timeend.xml
rename to tests/functionaltests/suites/atom/expected/get_opensearch-ogc-timeend.xml
diff --git a/tests/expected/suites_atom_get_opensearch-ogc-timestart.xml b/tests/functionaltests/suites/atom/expected/get_opensearch-ogc-timestart.xml
similarity index 100%
rename from tests/expected/suites_atom_get_opensearch-ogc-timestart.xml
rename to tests/functionaltests/suites/atom/expected/get_opensearch-ogc-timestart.xml
diff --git a/tests/expected/suites_atom_get_opensearch.xml b/tests/functionaltests/suites/atom/expected/get_opensearch.xml
similarity index 100%
rename from tests/expected/suites_atom_get_opensearch.xml
rename to tests/functionaltests/suites/atom/expected/get_opensearch.xml
diff --git a/tests/expected/suites_atom_post_DescribeRecord.xml b/tests/functionaltests/suites/atom/expected/post_DescribeRecord.xml
similarity index 100%
rename from tests/expected/suites_atom_post_DescribeRecord.xml
rename to tests/functionaltests/suites/atom/expected/post_DescribeRecord.xml
diff --git a/tests/expected/suites_atom_post_GetCapabilities.xml b/tests/functionaltests/suites/atom/expected/post_GetCapabilities.xml
similarity index 100%
rename from tests/expected/suites_atom_post_GetCapabilities.xml
rename to tests/functionaltests/suites/atom/expected/post_GetCapabilities.xml
diff --git a/tests/expected/suites_atom_post_GetRecords-filter-bbox.xml b/tests/functionaltests/suites/atom/expected/post_GetRecords-filter-bbox.xml
similarity index 100%
rename from tests/expected/suites_atom_post_GetRecords-filter-bbox.xml
rename to tests/functionaltests/suites/atom/expected/post_GetRecords-filter-bbox.xml
diff --git a/tests/functionaltests/suites/atom/get/requests.txt b/tests/functionaltests/suites/atom/get/requests.txt
new file mode 100644
index 0000000..6734cd5
--- /dev/null
+++ b/tests/functionaltests/suites/atom/get/requests.txt
@@ -0,0 +1,12 @@
+opensearch,mode=opensearch&service=CSW&version=2.0.2&request=GetRecords&typenames=csw:Record&resulttype=results&elementsetname=brief
+opensearch-description,mode=opensearch&service=CSW&version=2.0.2&request=GetCapabilities
+opensearch-ogc-q,mode=opensearch&service=CSW&version=2.0.2&request=GetRecords&elementsetname=full&resulttype=results&typenames=csw:Record&q=greece
+opensearch-ogc-bbox,mode=opensearch&service=CSW&version=2.0.2&request=GetRecords&elementsetname=full&resulttype=results&typenames=csw:Record&bbox=-180,-90,180,90
+opensearch-ogc-time,mode=opensearch&service=CSW&version=2.0.2&request=GetRecords&elementsetname=full&resulttype=results&typenames=csw:Record&time=2001/2004
+opensearch-ogc-timestart,mode=opensearch&service=CSW&version=2.0.2&request=GetRecords&elementsetname=full&resulttype=results&typenames=csw:Record&time=2004/
+opensearch-ogc-timeend,mode=opensearch&service=CSW&version=2.0.2&request=GetRecords&elementsetname=full&resulttype=results&typenames=csw:Record&time=/2004
+opensearch-ogc-q-and-time,mode=opensearch&service=CSW&version=2.0.2&request=GetRecords&elementsetname=full&resulttype=results&typenames=csw:Record&time=2001/2007&q=vitae
+opensearch-ogc-bbox-and-time,mode=opensearch&service=CSW&version=2.0.2&request=GetRecords&elementsetname=full&resulttype=results&typenames=csw:Record&time=2001/2007&bbox=-180,-90,180,90
+opensearch-ogc-q-and-bbox,mode=opensearch&service=CSW&version=2.0.2&request=GetRecords&elementsetname=full&resulttype=results&typenames=csw:Record&q=vegetation&bbox=-180,-90,180,90
+opensearch-ogc-count-and-page1,mode=opensearch&service=CSW&version=2.0.2&request=GetRecords&elementsetname=full&resulttype=results&typenames=csw:Record&q=vegetation&startposition=1
+opensearch-ogc-count-and-page2,mode=opensearch&service=CSW&version=2.0.2&request=GetRecords&elementsetname=full&resulttype=results&typenames=csw:Record&q=vegetation&startposition=1&maxrecords=1
diff --git a/tests/suites/atom/post/DescribeRecord.xml b/tests/functionaltests/suites/atom/post/DescribeRecord.xml
similarity index 100%
rename from tests/suites/atom/post/DescribeRecord.xml
rename to tests/functionaltests/suites/atom/post/DescribeRecord.xml
diff --git a/tests/suites/atom/post/GetCapabilities.xml b/tests/functionaltests/suites/atom/post/GetCapabilities.xml
similarity index 100%
rename from tests/suites/atom/post/GetCapabilities.xml
rename to tests/functionaltests/suites/atom/post/GetCapabilities.xml
diff --git a/tests/suites/atom/post/GetRecords-filter-bbox.xml b/tests/functionaltests/suites/atom/post/GetRecords-filter-bbox.xml
similarity index 100%
rename from tests/suites/atom/post/GetRecords-filter-bbox.xml
rename to tests/functionaltests/suites/atom/post/GetRecords-filter-bbox.xml
diff --git a/tests/suites/cite/data/README.txt b/tests/functionaltests/suites/cite/data/README.txt
similarity index 100%
rename from tests/suites/cite/data/README.txt
rename to tests/functionaltests/suites/cite/data/README.txt
diff --git a/tests/suites/cite/data/Record_19887a8a-f6b0-4a63-ae56-7fba0e17801f.xml b/tests/functionaltests/suites/cite/data/Record_19887a8a-f6b0-4a63-ae56-7fba0e17801f.xml
similarity index 100%
rename from tests/suites/cite/data/Record_19887a8a-f6b0-4a63-ae56-7fba0e17801f.xml
rename to tests/functionaltests/suites/cite/data/Record_19887a8a-f6b0-4a63-ae56-7fba0e17801f.xml
diff --git a/tests/suites/cite/data/Record_1ef30a8b-876d-4828-9246-c37ab4510bbd.xml b/tests/functionaltests/suites/cite/data/Record_1ef30a8b-876d-4828-9246-c37ab4510bbd.xml
similarity index 100%
rename from tests/suites/cite/data/Record_1ef30a8b-876d-4828-9246-c37ab4510bbd.xml
rename to tests/functionaltests/suites/cite/data/Record_1ef30a8b-876d-4828-9246-c37ab4510bbd.xml
diff --git a/tests/suites/cite/data/Record_66ae76b7-54ba-489b-a582-0f0633d96493.xml b/tests/functionaltests/suites/cite/data/Record_66ae76b7-54ba-489b-a582-0f0633d96493.xml
similarity index 100%
rename from tests/suites/cite/data/Record_66ae76b7-54ba-489b-a582-0f0633d96493.xml
rename to tests/functionaltests/suites/cite/data/Record_66ae76b7-54ba-489b-a582-0f0633d96493.xml
diff --git a/tests/suites/cite/data/Record_6a3de50b-fa66-4b58-a0e6-ca146fdd18d4.xml b/tests/functionaltests/suites/cite/data/Record_6a3de50b-fa66-4b58-a0e6-ca146fdd18d4.xml
similarity index 100%
rename from tests/suites/cite/data/Record_6a3de50b-fa66-4b58-a0e6-ca146fdd18d4.xml
rename to tests/functionaltests/suites/cite/data/Record_6a3de50b-fa66-4b58-a0e6-ca146fdd18d4.xml
diff --git a/tests/suites/cite/data/Record_784e2afd-a9fd-44a6-9a92-a3848371c8ec.xml b/tests/functionaltests/suites/cite/data/Record_784e2afd-a9fd-44a6-9a92-a3848371c8ec.xml
similarity index 100%
rename from tests/suites/cite/data/Record_784e2afd-a9fd-44a6-9a92-a3848371c8ec.xml
rename to tests/functionaltests/suites/cite/data/Record_784e2afd-a9fd-44a6-9a92-a3848371c8ec.xml
diff --git a/tests/suites/cite/data/Record_829babb0-b2f1-49e1-8cd5-7b489fe71a1e.xml b/tests/functionaltests/suites/cite/data/Record_829babb0-b2f1-49e1-8cd5-7b489fe71a1e.xml
similarity index 100%
rename from tests/suites/cite/data/Record_829babb0-b2f1-49e1-8cd5-7b489fe71a1e.xml
rename to tests/functionaltests/suites/cite/data/Record_829babb0-b2f1-49e1-8cd5-7b489fe71a1e.xml
diff --git a/tests/suites/cite/data/Record_88247b56-4cbc-4df9-9860-db3f8042e357.xml b/tests/functionaltests/suites/cite/data/Record_88247b56-4cbc-4df9-9860-db3f8042e357.xml
similarity index 100%
rename from tests/suites/cite/data/Record_88247b56-4cbc-4df9-9860-db3f8042e357.xml
rename to tests/functionaltests/suites/cite/data/Record_88247b56-4cbc-4df9-9860-db3f8042e357.xml
diff --git a/tests/suites/cite/data/Record_94bc9c83-97f6-4b40-9eb8-a8e8787a5c63.xml b/tests/functionaltests/suites/cite/data/Record_94bc9c83-97f6-4b40-9eb8-a8e8787a5c63.xml
similarity index 100%
rename from tests/suites/cite/data/Record_94bc9c83-97f6-4b40-9eb8-a8e8787a5c63.xml
rename to tests/functionaltests/suites/cite/data/Record_94bc9c83-97f6-4b40-9eb8-a8e8787a5c63.xml
diff --git a/tests/suites/cite/data/Record_9a669547-b69b-469f-a11f-2d875366bbdc.xml b/tests/functionaltests/suites/cite/data/Record_9a669547-b69b-469f-a11f-2d875366bbdc.xml
similarity index 100%
rename from tests/suites/cite/data/Record_9a669547-b69b-469f-a11f-2d875366bbdc.xml
rename to tests/functionaltests/suites/cite/data/Record_9a669547-b69b-469f-a11f-2d875366bbdc.xml
diff --git a/tests/suites/cite/data/Record_a06af396-3105-442d-8b40-22b57a90d2f2.xml b/tests/functionaltests/suites/cite/data/Record_a06af396-3105-442d-8b40-22b57a90d2f2.xml
similarity index 100%
rename from tests/suites/cite/data/Record_a06af396-3105-442d-8b40-22b57a90d2f2.xml
rename to tests/functionaltests/suites/cite/data/Record_a06af396-3105-442d-8b40-22b57a90d2f2.xml
diff --git a/tests/suites/cite/data/Record_ab42a8c4-95e8-4630-bf79-33e59241605a.xml b/tests/functionaltests/suites/cite/data/Record_ab42a8c4-95e8-4630-bf79-33e59241605a.xml
similarity index 100%
rename from tests/suites/cite/data/Record_ab42a8c4-95e8-4630-bf79-33e59241605a.xml
rename to tests/functionaltests/suites/cite/data/Record_ab42a8c4-95e8-4630-bf79-33e59241605a.xml
diff --git a/tests/suites/cite/data/Record_e9330592-0932-474b-be34-c3a3bb67c7db.xml b/tests/functionaltests/suites/cite/data/Record_e9330592-0932-474b-be34-c3a3bb67c7db.xml
similarity index 100%
rename from tests/suites/cite/data/Record_e9330592-0932-474b-be34-c3a3bb67c7db.xml
rename to tests/functionaltests/suites/cite/data/Record_e9330592-0932-474b-be34-c3a3bb67c7db.xml
diff --git a/tests/suites/cite/data/cite.db b/tests/functionaltests/suites/cite/data/cite.db
similarity index 100%
rename from tests/suites/cite/data/cite.db
rename to tests/functionaltests/suites/cite/data/cite.db
diff --git a/tests/suites/cite/default.cfg b/tests/functionaltests/suites/cite/default.cfg
similarity index 100%
rename from tests/suites/cite/default.cfg
rename to tests/functionaltests/suites/cite/default.cfg
diff --git a/tests/expected/suites_cite_get_27e17158-c57a-4493-92ac-dba8934cf462.xml b/tests/functionaltests/suites/cite/expected/get_27e17158-c57a-4493-92ac-dba8934cf462.xml
similarity index 99%
copy from tests/expected/suites_cite_get_27e17158-c57a-4493-92ac-dba8934cf462.xml
copy to tests/functionaltests/suites/cite/expected/get_27e17158-c57a-4493-92ac-dba8934cf462.xml
index b3c13e3..e382295 100644
--- a/tests/expected/suites_cite_get_27e17158-c57a-4493-92ac-dba8934cf462.xml
+++ b/tests/functionaltests/suites/cite/expected/get_27e17158-c57a-4493-92ac-dba8934cf462.xml
@@ -203,6 +203,7 @@
         <ows:Value>http://www.opengis.net/sos/2.0</ows:Value>
         <ows:Value>http://www.opengis.net/wcs</ows:Value>
         <ows:Value>http://www.opengis.net/wfs</ows:Value>
+        <ows:Value>http://www.opengis.net/wfs/2.0</ows:Value>
         <ows:Value>http://www.opengis.net/wms</ows:Value>
         <ows:Value>http://www.opengis.net/wmts/1.0</ows:Value>
         <ows:Value>http://www.opengis.net/wps/1.0.0</ows:Value>
@@ -226,6 +227,7 @@
         <ows:Value>http://www.opengis.net/sos/2.0</ows:Value>
         <ows:Value>http://www.opengis.net/wcs</ows:Value>
         <ows:Value>http://www.opengis.net/wfs</ows:Value>
+        <ows:Value>http://www.opengis.net/wfs/2.0</ows:Value>
         <ows:Value>http://www.opengis.net/wms</ows:Value>
         <ows:Value>http://www.opengis.net/wmts/1.0</ows:Value>
         <ows:Value>http://www.opengis.net/wps/1.0.0</ows:Value>
diff --git a/tests/expected/suites_cite_get_27f69b66-5f05-4311-a89c-73ca55c2686b.xml b/tests/functionaltests/suites/cite/expected/get_27f69b66-5f05-4311-a89c-73ca55c2686b.xml
similarity index 100%
rename from tests/expected/suites_cite_get_27f69b66-5f05-4311-a89c-73ca55c2686b.xml
rename to tests/functionaltests/suites/cite/expected/get_27f69b66-5f05-4311-a89c-73ca55c2686b.xml
diff --git a/tests/expected/suites_cite_get_ba5fc729-3b71-47a0-b7d0-42ec565cd185.xml b/tests/functionaltests/suites/cite/expected/get_2ab7d1fa-885b-459f-80e4-b6282eab4f8c.xml
similarity index 99%
rename from tests/expected/suites_cite_get_ba5fc729-3b71-47a0-b7d0-42ec565cd185.xml
rename to tests/functionaltests/suites/cite/expected/get_2ab7d1fa-885b-459f-80e4-b6282eab4f8c.xml
index b3c13e3..e382295 100644
--- a/tests/expected/suites_cite_get_ba5fc729-3b71-47a0-b7d0-42ec565cd185.xml
+++ b/tests/functionaltests/suites/cite/expected/get_2ab7d1fa-885b-459f-80e4-b6282eab4f8c.xml
@@ -203,6 +203,7 @@
         <ows:Value>http://www.opengis.net/sos/2.0</ows:Value>
         <ows:Value>http://www.opengis.net/wcs</ows:Value>
         <ows:Value>http://www.opengis.net/wfs</ows:Value>
+        <ows:Value>http://www.opengis.net/wfs/2.0</ows:Value>
         <ows:Value>http://www.opengis.net/wms</ows:Value>
         <ows:Value>http://www.opengis.net/wmts/1.0</ows:Value>
         <ows:Value>http://www.opengis.net/wps/1.0.0</ows:Value>
@@ -226,6 +227,7 @@
         <ows:Value>http://www.opengis.net/sos/2.0</ows:Value>
         <ows:Value>http://www.opengis.net/wcs</ows:Value>
         <ows:Value>http://www.opengis.net/wfs</ows:Value>
+        <ows:Value>http://www.opengis.net/wfs/2.0</ows:Value>
         <ows:Value>http://www.opengis.net/wms</ows:Value>
         <ows:Value>http://www.opengis.net/wmts/1.0</ows:Value>
         <ows:Value>http://www.opengis.net/wps/1.0.0</ows:Value>
diff --git a/tests/expected/suites_cite_get_37aa90e2-6ff0-420c-af15-8b9463099a73.xml b/tests/functionaltests/suites/cite/expected/get_37aa90e2-6ff0-420c-af15-8b9463099a73.xml
similarity index 100%
rename from tests/expected/suites_cite_get_37aa90e2-6ff0-420c-af15-8b9463099a73.xml
rename to tests/functionaltests/suites/cite/expected/get_37aa90e2-6ff0-420c-af15-8b9463099a73.xml
diff --git a/tests/expected/suites_cite_get_3a8a3c47-455f-4f49-9078-03119f3e70b3.xml b/tests/functionaltests/suites/cite/expected/get_3a8a3c47-455f-4f49-9078-03119f3e70b3.xml
similarity index 100%
rename from tests/expected/suites_cite_get_3a8a3c47-455f-4f49-9078-03119f3e70b3.xml
rename to tests/functionaltests/suites/cite/expected/get_3a8a3c47-455f-4f49-9078-03119f3e70b3.xml
diff --git a/tests/expected/suites_cite_get_4515831f-834a-4699-95f6-ab0c2cbfcfd0.xml b/tests/functionaltests/suites/cite/expected/get_4515831f-834a-4699-95f6-ab0c2cbfcfd0.xml
similarity index 100%
rename from tests/expected/suites_cite_get_4515831f-834a-4699-95f6-ab0c2cbfcfd0.xml
rename to tests/functionaltests/suites/cite/expected/get_4515831f-834a-4699-95f6-ab0c2cbfcfd0.xml
diff --git a/tests/expected/suites_cite_get_80f31def-4185-48b9-983a-960566918eae.xml b/tests/functionaltests/suites/cite/expected/get_477b23a3-baa9-47c8-9541-5fe27735ed49.xml
similarity index 99%
rename from tests/expected/suites_cite_get_80f31def-4185-48b9-983a-960566918eae.xml
rename to tests/functionaltests/suites/cite/expected/get_477b23a3-baa9-47c8-9541-5fe27735ed49.xml
index b900ce5..2d54cf8 100644
--- a/tests/expected/suites_cite_get_80f31def-4185-48b9-983a-960566918eae.xml
+++ b/tests/functionaltests/suites/cite/expected/get_477b23a3-baa9-47c8-9541-5fe27735ed49.xml
@@ -134,6 +134,7 @@
       </ows20:Parameter>
       <ows20:Parameter name="typeNames">
         <ows20:AllowedValues>
+          <ows20:Value>csw30:Record</ows20:Value>
           <ows20:Value>csw:Record</ows20:Value>
         </ows20:AllowedValues>
       </ows20:Parameter>
@@ -206,6 +207,7 @@
           <ows20:Value>http://www.opengis.net/sos/2.0</ows20:Value>
           <ows20:Value>http://www.opengis.net/wcs</ows20:Value>
           <ows20:Value>http://www.opengis.net/wfs</ows20:Value>
+          <ows20:Value>http://www.opengis.net/wfs/2.0</ows20:Value>
           <ows20:Value>http://www.opengis.net/wms</ows20:Value>
           <ows20:Value>http://www.opengis.net/wmts/1.0</ows20:Value>
           <ows20:Value>http://www.opengis.net/wps/1.0.0</ows20:Value>
@@ -231,6 +233,7 @@
           <ows20:Value>http://www.opengis.net/sos/2.0</ows20:Value>
           <ows20:Value>http://www.opengis.net/wcs</ows20:Value>
           <ows20:Value>http://www.opengis.net/wfs</ows20:Value>
+          <ows20:Value>http://www.opengis.net/wfs/2.0</ows20:Value>
           <ows20:Value>http://www.opengis.net/wms</ows20:Value>
           <ows20:Value>http://www.opengis.net/wmts/1.0</ows20:Value>
           <ows20:Value>http://www.opengis.net/wps/1.0.0</ows20:Value>
diff --git a/tests/expected/suites_cite_get_48f26761-3a9d-48db-bee1-da089f5fb857.xml b/tests/functionaltests/suites/cite/expected/get_48f26761-3a9d-48db-bee1-da089f5fb857.xml
similarity index 99%
rename from tests/expected/suites_cite_get_48f26761-3a9d-48db-bee1-da089f5fb857.xml
rename to tests/functionaltests/suites/cite/expected/get_48f26761-3a9d-48db-bee1-da089f5fb857.xml
index b3c13e3..e382295 100644
--- a/tests/expected/suites_cite_get_48f26761-3a9d-48db-bee1-da089f5fb857.xml
+++ b/tests/functionaltests/suites/cite/expected/get_48f26761-3a9d-48db-bee1-da089f5fb857.xml
@@ -203,6 +203,7 @@
         <ows:Value>http://www.opengis.net/sos/2.0</ows:Value>
         <ows:Value>http://www.opengis.net/wcs</ows:Value>
         <ows:Value>http://www.opengis.net/wfs</ows:Value>
+        <ows:Value>http://www.opengis.net/wfs/2.0</ows:Value>
         <ows:Value>http://www.opengis.net/wms</ows:Value>
         <ows:Value>http://www.opengis.net/wmts/1.0</ows:Value>
         <ows:Value>http://www.opengis.net/wps/1.0.0</ows:Value>
@@ -226,6 +227,7 @@
         <ows:Value>http://www.opengis.net/sos/2.0</ows:Value>
         <ows:Value>http://www.opengis.net/wcs</ows:Value>
         <ows:Value>http://www.opengis.net/wfs</ows:Value>
+        <ows:Value>http://www.opengis.net/wfs/2.0</ows:Value>
         <ows:Value>http://www.opengis.net/wms</ows:Value>
         <ows:Value>http://www.opengis.net/wmts/1.0</ows:Value>
         <ows:Value>http://www.opengis.net/wps/1.0.0</ows:Value>
diff --git a/tests/expected/suites_cite_get_4e38092f-1586-44b8-988e-0acfa5855916.xml b/tests/functionaltests/suites/cite/expected/get_4e38092f-1586-44b8-988e-0acfa5855916.xml
similarity index 100%
rename from tests/expected/suites_cite_get_4e38092f-1586-44b8-988e-0acfa5855916.xml
rename to tests/functionaltests/suites/cite/expected/get_4e38092f-1586-44b8-988e-0acfa5855916.xml
diff --git a/tests/expected/suites_cite_get_55c38f00-2553-42c1-99ab-33edbb561ad7.xml b/tests/functionaltests/suites/cite/expected/get_55c38f00-2553-42c1-99ab-33edbb561ad7.xml
similarity index 98%
rename from tests/expected/suites_cite_get_55c38f00-2553-42c1-99ab-33edbb561ad7.xml
rename to tests/functionaltests/suites/cite/expected/get_55c38f00-2553-42c1-99ab-33edbb561ad7.xml
index 51bf2e7..a02408b 100644
--- a/tests/expected/suites_cite_get_55c38f00-2553-42c1-99ab-33edbb561ad7.xml
+++ b/tests/functionaltests/suites/cite/expected/get_55c38f00-2553-42c1-99ab-33edbb561ad7.xml
@@ -108,6 +108,7 @@
       </ows20:Parameter>
       <ows20:Parameter name="typeNames">
         <ows20:AllowedValues>
+          <ows20:Value>csw30:Record</ows20:Value>
           <ows20:Value>csw:Record</ows20:Value>
         </ows20:AllowedValues>
       </ows20:Parameter>
@@ -180,6 +181,7 @@
           <ows20:Value>http://www.opengis.net/sos/2.0</ows20:Value>
           <ows20:Value>http://www.opengis.net/wcs</ows20:Value>
           <ows20:Value>http://www.opengis.net/wfs</ows20:Value>
+          <ows20:Value>http://www.opengis.net/wfs/2.0</ows20:Value>
           <ows20:Value>http://www.opengis.net/wms</ows20:Value>
           <ows20:Value>http://www.opengis.net/wmts/1.0</ows20:Value>
           <ows20:Value>http://www.opengis.net/wps/1.0.0</ows20:Value>
@@ -205,6 +207,7 @@
           <ows20:Value>http://www.opengis.net/sos/2.0</ows20:Value>
           <ows20:Value>http://www.opengis.net/wcs</ows20:Value>
           <ows20:Value>http://www.opengis.net/wfs</ows20:Value>
+          <ows20:Value>http://www.opengis.net/wfs/2.0</ows20:Value>
           <ows20:Value>http://www.opengis.net/wms</ows20:Value>
           <ows20:Value>http://www.opengis.net/wmts/1.0</ows20:Value>
           <ows20:Value>http://www.opengis.net/wps/1.0.0</ows20:Value>
diff --git a/tests/expected/suites_cite_get_5ab5db18-c87a-4fbf-a8d8-b7289b09ac81.xml b/tests/functionaltests/suites/cite/expected/get_5ab5db18-c87a-4fbf-a8d8-b7289b09ac81.xml
similarity index 100%
rename from tests/expected/suites_cite_get_5ab5db18-c87a-4fbf-a8d8-b7289b09ac81.xml
rename to tests/functionaltests/suites/cite/expected/get_5ab5db18-c87a-4fbf-a8d8-b7289b09ac81.xml
diff --git a/tests/expected/suites_cite_get_6a4f57ca-a1bd-4802-89c2-44860dbdb0f0.xml b/tests/functionaltests/suites/cite/expected/get_6a4f57ca-a1bd-4802-89c2-44860dbdb0f0.xml
similarity index 100%
rename from tests/expected/suites_cite_get_6a4f57ca-a1bd-4802-89c2-44860dbdb0f0.xml
rename to tests/functionaltests/suites/cite/expected/get_6a4f57ca-a1bd-4802-89c2-44860dbdb0f0.xml
diff --git a/tests/expected/suites_cite_get_6c375703-9c00-4aef-bec7-d2e964f849eb.xml b/tests/functionaltests/suites/cite/expected/get_6c375703-9c00-4aef-bec7-d2e964f849eb.xml
similarity index 100%
rename from tests/expected/suites_cite_get_6c375703-9c00-4aef-bec7-d2e964f849eb.xml
rename to tests/functionaltests/suites/cite/expected/get_6c375703-9c00-4aef-bec7-d2e964f849eb.xml
diff --git a/tests/expected/suites_cite_get_9697f0aa-3b6a-4125-83a5-61e8826127c4.xml b/tests/functionaltests/suites/cite/expected/get_80f31def-4185-48b9-983a-960566918eae.xml
similarity index 99%
rename from tests/expected/suites_cite_get_9697f0aa-3b6a-4125-83a5-61e8826127c4.xml
rename to tests/functionaltests/suites/cite/expected/get_80f31def-4185-48b9-983a-960566918eae.xml
index b900ce5..2d54cf8 100644
--- a/tests/expected/suites_cite_get_9697f0aa-3b6a-4125-83a5-61e8826127c4.xml
+++ b/tests/functionaltests/suites/cite/expected/get_80f31def-4185-48b9-983a-960566918eae.xml
@@ -134,6 +134,7 @@
       </ows20:Parameter>
       <ows20:Parameter name="typeNames">
         <ows20:AllowedValues>
+          <ows20:Value>csw30:Record</ows20:Value>
           <ows20:Value>csw:Record</ows20:Value>
         </ows20:AllowedValues>
       </ows20:Parameter>
@@ -206,6 +207,7 @@
           <ows20:Value>http://www.opengis.net/sos/2.0</ows20:Value>
           <ows20:Value>http://www.opengis.net/wcs</ows20:Value>
           <ows20:Value>http://www.opengis.net/wfs</ows20:Value>
+          <ows20:Value>http://www.opengis.net/wfs/2.0</ows20:Value>
           <ows20:Value>http://www.opengis.net/wms</ows20:Value>
           <ows20:Value>http://www.opengis.net/wmts/1.0</ows20:Value>
           <ows20:Value>http://www.opengis.net/wps/1.0.0</ows20:Value>
@@ -231,6 +233,7 @@
           <ows20:Value>http://www.opengis.net/sos/2.0</ows20:Value>
           <ows20:Value>http://www.opengis.net/wcs</ows20:Value>
           <ows20:Value>http://www.opengis.net/wfs</ows20:Value>
+          <ows20:Value>http://www.opengis.net/wfs/2.0</ows20:Value>
           <ows20:Value>http://www.opengis.net/wms</ows20:Value>
           <ows20:Value>http://www.opengis.net/wmts/1.0</ows20:Value>
           <ows20:Value>http://www.opengis.net/wps/1.0.0</ows20:Value>
diff --git a/tests/expected/suites_cite_get_8e2232ed-05d9-44ae-8b04-0911cbe6a507.xml b/tests/functionaltests/suites/cite/expected/get_8e2232ed-05d9-44ae-8b04-0911cbe6a507.xml
similarity index 100%
rename from tests/expected/suites_cite_get_8e2232ed-05d9-44ae-8b04-0911cbe6a507.xml
rename to tests/functionaltests/suites/cite/expected/get_8e2232ed-05d9-44ae-8b04-0911cbe6a507.xml
diff --git a/tests/expected/suites_cite_get_477b23a3-baa9-47c8-9541-5fe27735ed49.xml b/tests/functionaltests/suites/cite/expected/get_9697f0aa-3b6a-4125-83a5-61e8826127c4.xml
similarity index 99%
rename from tests/expected/suites_cite_get_477b23a3-baa9-47c8-9541-5fe27735ed49.xml
rename to tests/functionaltests/suites/cite/expected/get_9697f0aa-3b6a-4125-83a5-61e8826127c4.xml
index b900ce5..2d54cf8 100644
--- a/tests/expected/suites_cite_get_477b23a3-baa9-47c8-9541-5fe27735ed49.xml
+++ b/tests/functionaltests/suites/cite/expected/get_9697f0aa-3b6a-4125-83a5-61e8826127c4.xml
@@ -134,6 +134,7 @@
       </ows20:Parameter>
       <ows20:Parameter name="typeNames">
         <ows20:AllowedValues>
+          <ows20:Value>csw30:Record</ows20:Value>
           <ows20:Value>csw:Record</ows20:Value>
         </ows20:AllowedValues>
       </ows20:Parameter>
@@ -206,6 +207,7 @@
           <ows20:Value>http://www.opengis.net/sos/2.0</ows20:Value>
           <ows20:Value>http://www.opengis.net/wcs</ows20:Value>
           <ows20:Value>http://www.opengis.net/wfs</ows20:Value>
+          <ows20:Value>http://www.opengis.net/wfs/2.0</ows20:Value>
           <ows20:Value>http://www.opengis.net/wms</ows20:Value>
           <ows20:Value>http://www.opengis.net/wmts/1.0</ows20:Value>
           <ows20:Value>http://www.opengis.net/wps/1.0.0</ows20:Value>
@@ -231,6 +233,7 @@
           <ows20:Value>http://www.opengis.net/sos/2.0</ows20:Value>
           <ows20:Value>http://www.opengis.net/wcs</ows20:Value>
           <ows20:Value>http://www.opengis.net/wfs</ows20:Value>
+          <ows20:Value>http://www.opengis.net/wfs/2.0</ows20:Value>
           <ows20:Value>http://www.opengis.net/wms</ows20:Value>
           <ows20:Value>http://www.opengis.net/wmts/1.0</ows20:Value>
           <ows20:Value>http://www.opengis.net/wps/1.0.0</ows20:Value>
diff --git a/tests/expected/suites_cite_get_9bfd17fa-15dc-4a10-8fa7-b3cff7013dd7.xml b/tests/functionaltests/suites/cite/expected/get_9bfd17fa-15dc-4a10-8fa7-b3cff7013dd7.xml
similarity index 100%
rename from tests/expected/suites_cite_get_9bfd17fa-15dc-4a10-8fa7-b3cff7013dd7.xml
rename to tests/functionaltests/suites/cite/expected/get_9bfd17fa-15dc-4a10-8fa7-b3cff7013dd7.xml
diff --git a/tests/expected/suites_cite_get_b81c3595-06d6-4693-82ea-1ff8650755ac.xml b/tests/functionaltests/suites/cite/expected/get_b81c3595-06d6-4693-82ea-1ff8650755ac.xml
similarity index 100%
rename from tests/expected/suites_cite_get_b81c3595-06d6-4693-82ea-1ff8650755ac.xml
rename to tests/functionaltests/suites/cite/expected/get_b81c3595-06d6-4693-82ea-1ff8650755ac.xml
diff --git a/tests/expected/suites_cite_get_2ab7d1fa-885b-459f-80e4-b6282eab4f8c.xml b/tests/functionaltests/suites/cite/expected/get_ba5fc729-3b71-47a0-b7d0-42ec565cd185.xml
similarity index 99%
rename from tests/expected/suites_cite_get_2ab7d1fa-885b-459f-80e4-b6282eab4f8c.xml
rename to tests/functionaltests/suites/cite/expected/get_ba5fc729-3b71-47a0-b7d0-42ec565cd185.xml
index b3c13e3..e382295 100644
--- a/tests/expected/suites_cite_get_2ab7d1fa-885b-459f-80e4-b6282eab4f8c.xml
+++ b/tests/functionaltests/suites/cite/expected/get_ba5fc729-3b71-47a0-b7d0-42ec565cd185.xml
@@ -203,6 +203,7 @@
         <ows:Value>http://www.opengis.net/sos/2.0</ows:Value>
         <ows:Value>http://www.opengis.net/wcs</ows:Value>
         <ows:Value>http://www.opengis.net/wfs</ows:Value>
+        <ows:Value>http://www.opengis.net/wfs/2.0</ows:Value>
         <ows:Value>http://www.opengis.net/wms</ows:Value>
         <ows:Value>http://www.opengis.net/wmts/1.0</ows:Value>
         <ows:Value>http://www.opengis.net/wps/1.0.0</ows:Value>
@@ -226,6 +227,7 @@
         <ows:Value>http://www.opengis.net/sos/2.0</ows:Value>
         <ows:Value>http://www.opengis.net/wcs</ows:Value>
         <ows:Value>http://www.opengis.net/wfs</ows:Value>
+        <ows:Value>http://www.opengis.net/wfs/2.0</ows:Value>
         <ows:Value>http://www.opengis.net/wms</ows:Value>
         <ows:Value>http://www.opengis.net/wmts/1.0</ows:Value>
         <ows:Value>http://www.opengis.net/wps/1.0.0</ows:Value>
diff --git a/tests/expected/suites_cite_get_c4ea754f-c158-4d8d-8253-dc8f86021b52.xml b/tests/functionaltests/suites/cite/expected/get_c4ea754f-c158-4d8d-8253-dc8f86021b52.xml
similarity index 100%
rename from tests/expected/suites_cite_get_c4ea754f-c158-4d8d-8253-dc8f86021b52.xml
rename to tests/functionaltests/suites/cite/expected/get_c4ea754f-c158-4d8d-8253-dc8f86021b52.xml
diff --git a/tests/expected/suites_cite_get_27e17158-c57a-4493-92ac-dba8934cf462.xml b/tests/functionaltests/suites/cite/expected/get_f4692ec5-9547-4a05-88ab-e6154af2640a.xml
similarity index 99%
rename from tests/expected/suites_cite_get_27e17158-c57a-4493-92ac-dba8934cf462.xml
rename to tests/functionaltests/suites/cite/expected/get_f4692ec5-9547-4a05-88ab-e6154af2640a.xml
index b3c13e3..e382295 100644
--- a/tests/expected/suites_cite_get_27e17158-c57a-4493-92ac-dba8934cf462.xml
+++ b/tests/functionaltests/suites/cite/expected/get_f4692ec5-9547-4a05-88ab-e6154af2640a.xml
@@ -203,6 +203,7 @@
         <ows:Value>http://www.opengis.net/sos/2.0</ows:Value>
         <ows:Value>http://www.opengis.net/wcs</ows:Value>
         <ows:Value>http://www.opengis.net/wfs</ows:Value>
+        <ows:Value>http://www.opengis.net/wfs/2.0</ows:Value>
         <ows:Value>http://www.opengis.net/wms</ows:Value>
         <ows:Value>http://www.opengis.net/wmts/1.0</ows:Value>
         <ows:Value>http://www.opengis.net/wps/1.0.0</ows:Value>
@@ -226,6 +227,7 @@
         <ows:Value>http://www.opengis.net/sos/2.0</ows:Value>
         <ows:Value>http://www.opengis.net/wcs</ows:Value>
         <ows:Value>http://www.opengis.net/wfs</ows:Value>
+        <ows:Value>http://www.opengis.net/wfs/2.0</ows:Value>
         <ows:Value>http://www.opengis.net/wms</ows:Value>
         <ows:Value>http://www.opengis.net/wmts/1.0</ows:Value>
         <ows:Value>http://www.opengis.net/wps/1.0.0</ows:Value>
diff --git a/tests/expected/suites_cite_get_f997f25e-c865-4d53-a362-0ed1846337f2.xml b/tests/functionaltests/suites/cite/expected/get_f997f25e-c865-4d53-a362-0ed1846337f2.xml
similarity index 100%
rename from tests/expected/suites_cite_get_f997f25e-c865-4d53-a362-0ed1846337f2.xml
rename to tests/functionaltests/suites/cite/expected/get_f997f25e-c865-4d53-a362-0ed1846337f2.xml
diff --git a/tests/expected/suites_cite_post_0c976d98-c896-4b10-b1fe-a22ef50434e7.xml b/tests/functionaltests/suites/cite/expected/post_0c976d98-c896-4b10-b1fe-a22ef50434e7.xml
similarity index 100%
rename from tests/expected/suites_cite_post_0c976d98-c896-4b10-b1fe-a22ef50434e7.xml
rename to tests/functionaltests/suites/cite/expected/post_0c976d98-c896-4b10-b1fe-a22ef50434e7.xml
diff --git a/tests/expected/suites_cite_post_19d2a6ed-be28-4866-ae15-e3bb634486cb.xml b/tests/functionaltests/suites/cite/expected/post_19d2a6ed-be28-4866-ae15-e3bb634486cb.xml
similarity index 100%
rename from tests/expected/suites_cite_post_19d2a6ed-be28-4866-ae15-e3bb634486cb.xml
rename to tests/functionaltests/suites/cite/expected/post_19d2a6ed-be28-4866-ae15-e3bb634486cb.xml
diff --git a/tests/expected/suites_cite_post_1ab55aa3-6685-4595-8ecd-45987a7b8b59.xml b/tests/functionaltests/suites/cite/expected/post_1ab55aa3-6685-4595-8ecd-45987a7b8b59.xml
similarity index 100%
rename from tests/expected/suites_cite_post_1ab55aa3-6685-4595-8ecd-45987a7b8b59.xml
rename to tests/functionaltests/suites/cite/expected/post_1ab55aa3-6685-4595-8ecd-45987a7b8b59.xml
diff --git a/tests/expected/suites_cite_post_1c958b7a-ca09-4c38-98bd-ef1d1d28cc14.xml b/tests/functionaltests/suites/cite/expected/post_1c958b7a-ca09-4c38-98bd-ef1d1d28cc14.xml
similarity index 100%
rename from tests/expected/suites_cite_post_1c958b7a-ca09-4c38-98bd-ef1d1d28cc14.xml
rename to tests/functionaltests/suites/cite/expected/post_1c958b7a-ca09-4c38-98bd-ef1d1d28cc14.xml
diff --git a/tests/expected/suites_cite_post_1c97fc1a-61cd-4c1d-8054-933e17a6c5ee.xml b/tests/functionaltests/suites/cite/expected/post_1c97fc1a-61cd-4c1d-8054-933e17a6c5ee.xml
similarity index 100%
rename from tests/expected/suites_cite_post_1c97fc1a-61cd-4c1d-8054-933e17a6c5ee.xml
rename to tests/functionaltests/suites/cite/expected/post_1c97fc1a-61cd-4c1d-8054-933e17a6c5ee.xml
diff --git a/tests/expected/suites_cite_post_2102a460-5d62-465f-9668-d70b3faafbfa.xml b/tests/functionaltests/suites/cite/expected/post_2102a460-5d62-465f-9668-d70b3faafbfa.xml
similarity index 100%
rename from tests/expected/suites_cite_post_2102a460-5d62-465f-9668-d70b3faafbfa.xml
rename to tests/functionaltests/suites/cite/expected/post_2102a460-5d62-465f-9668-d70b3faafbfa.xml
diff --git a/tests/expected/suites_cite_post_225f455a-0035-486b-a94e-fee7ae881b2b.xml b/tests/functionaltests/suites/cite/expected/post_225f455a-0035-486b-a94e-fee7ae881b2b.xml
similarity index 100%
rename from tests/expected/suites_cite_post_225f455a-0035-486b-a94e-fee7ae881b2b.xml
rename to tests/functionaltests/suites/cite/expected/post_225f455a-0035-486b-a94e-fee7ae881b2b.xml
diff --git a/tests/expected/suites_cite_post_2d53ffea-60e4-4652-abf5-36eb23042fd5.xml b/tests/functionaltests/suites/cite/expected/post_2d53ffea-60e4-4652-abf5-36eb23042fd5.xml
similarity index 100%
rename from tests/expected/suites_cite_post_2d53ffea-60e4-4652-abf5-36eb23042fd5.xml
rename to tests/functionaltests/suites/cite/expected/post_2d53ffea-60e4-4652-abf5-36eb23042fd5.xml
diff --git a/tests/expected/suites_cite_post_34a019a9-1581-42cb-9827-fbfdda2773b7.xml b/tests/functionaltests/suites/cite/expected/post_34a019a9-1581-42cb-9827-fbfdda2773b7.xml
similarity index 100%
rename from tests/expected/suites_cite_post_34a019a9-1581-42cb-9827-fbfdda2773b7.xml
rename to tests/functionaltests/suites/cite/expected/post_34a019a9-1581-42cb-9827-fbfdda2773b7.xml
diff --git a/tests/expected/suites_cite_post_3e76fd38-e035-41c9-83dc-61356f680c97.xml b/tests/functionaltests/suites/cite/expected/post_3e76fd38-e035-41c9-83dc-61356f680c97.xml
similarity index 100%
rename from tests/expected/suites_cite_post_3e76fd38-e035-41c9-83dc-61356f680c97.xml
rename to tests/functionaltests/suites/cite/expected/post_3e76fd38-e035-41c9-83dc-61356f680c97.xml
diff --git a/tests/expected/suites_cite_post_418a6fb0-a89c-4a94-afc9-3f8168eb2980.xml b/tests/functionaltests/suites/cite/expected/post_418a6fb0-a89c-4a94-afc9-3f8168eb2980.xml
similarity index 100%
rename from tests/expected/suites_cite_post_418a6fb0-a89c-4a94-afc9-3f8168eb2980.xml
rename to tests/functionaltests/suites/cite/expected/post_418a6fb0-a89c-4a94-afc9-3f8168eb2980.xml
diff --git a/tests/expected/suites_cite_post_420b745e-0c4b-404e-9f2d-61fa580ff05a.xml b/tests/functionaltests/suites/cite/expected/post_420b745e-0c4b-404e-9f2d-61fa580ff05a.xml
similarity index 100%
rename from tests/expected/suites_cite_post_420b745e-0c4b-404e-9f2d-61fa580ff05a.xml
rename to tests/functionaltests/suites/cite/expected/post_420b745e-0c4b-404e-9f2d-61fa580ff05a.xml
diff --git a/tests/expected/suites_cite_post_4735d649-a2b1-42fd-a101-14e1d7e4607f.xml b/tests/functionaltests/suites/cite/expected/post_4735d649-a2b1-42fd-a101-14e1d7e4607f.xml
similarity index 100%
rename from tests/expected/suites_cite_post_4735d649-a2b1-42fd-a101-14e1d7e4607f.xml
rename to tests/functionaltests/suites/cite/expected/post_4735d649-a2b1-42fd-a101-14e1d7e4607f.xml
diff --git a/tests/expected/suites_cite_post_5c5861bc-f742-40a5-9998-5342615d674b.xml b/tests/functionaltests/suites/cite/expected/post_5c5861bc-f742-40a5-9998-5342615d674b.xml
similarity index 100%
rename from tests/expected/suites_cite_post_5c5861bc-f742-40a5-9998-5342615d674b.xml
rename to tests/functionaltests/suites/cite/expected/post_5c5861bc-f742-40a5-9998-5342615d674b.xml
diff --git a/tests/expected/suites_cite_post_6e736fd0-c266-4852-9eb3-0656f5d0f5c4.xml b/tests/functionaltests/suites/cite/expected/post_6e736fd0-c266-4852-9eb3-0656f5d0f5c4.xml
similarity index 100%
rename from tests/expected/suites_cite_post_6e736fd0-c266-4852-9eb3-0656f5d0f5c4.xml
rename to tests/functionaltests/suites/cite/expected/post_6e736fd0-c266-4852-9eb3-0656f5d0f5c4.xml
diff --git a/tests/expected/suites_cite_post_73f1551c-e269-4ef9-9dae-e535b5eebfc7.xml b/tests/functionaltests/suites/cite/expected/post_73f1551c-e269-4ef9-9dae-e535b5eebfc7.xml
similarity index 100%
rename from tests/expected/suites_cite_post_73f1551c-e269-4ef9-9dae-e535b5eebfc7.xml
rename to tests/functionaltests/suites/cite/expected/post_73f1551c-e269-4ef9-9dae-e535b5eebfc7.xml
diff --git a/tests/expected/suites_cite_post_78297c88-4850-4927-adc6-511cd9a3d539.xml b/tests/functionaltests/suites/cite/expected/post_78297c88-4850-4927-adc6-511cd9a3d539.xml
similarity index 100%
rename from tests/expected/suites_cite_post_78297c88-4850-4927-adc6-511cd9a3d539.xml
rename to tests/functionaltests/suites/cite/expected/post_78297c88-4850-4927-adc6-511cd9a3d539.xml
diff --git a/tests/expected/suites_cite_post_7c89cdf5-0def-4cfb-8c55-2b8ffea5d92f.xml b/tests/functionaltests/suites/cite/expected/post_7c89cdf5-0def-4cfb-8c55-2b8ffea5d92f.xml
similarity index 100%
rename from tests/expected/suites_cite_post_7c89cdf5-0def-4cfb-8c55-2b8ffea5d92f.xml
rename to tests/functionaltests/suites/cite/expected/post_7c89cdf5-0def-4cfb-8c55-2b8ffea5d92f.xml
diff --git a/tests/expected/suites_cite_post_7e2cd105-daec-4d25-bc8e-d49d21364912.xml b/tests/functionaltests/suites/cite/expected/post_7e2cd105-daec-4d25-bc8e-d49d21364912.xml
similarity index 100%
rename from tests/expected/suites_cite_post_7e2cd105-daec-4d25-bc8e-d49d21364912.xml
rename to tests/functionaltests/suites/cite/expected/post_7e2cd105-daec-4d25-bc8e-d49d21364912.xml
diff --git a/tests/expected/suites_cite_post_87f2f670-9cd6-4907-b82c-1b46a7dd2a78.xml b/tests/functionaltests/suites/cite/expected/post_87f2f670-9cd6-4907-b82c-1b46a7dd2a78.xml
similarity index 100%
rename from tests/expected/suites_cite_post_87f2f670-9cd6-4907-b82c-1b46a7dd2a78.xml
rename to tests/functionaltests/suites/cite/expected/post_87f2f670-9cd6-4907-b82c-1b46a7dd2a78.xml
diff --git a/tests/expected/suites_cite_post_88b4e1ba-3bd4-4cbe-81e5-e004056d6ca3.xml b/tests/functionaltests/suites/cite/expected/post_88b4e1ba-3bd4-4cbe-81e5-e004056d6ca3.xml
similarity index 100%
rename from tests/expected/suites_cite_post_88b4e1ba-3bd4-4cbe-81e5-e004056d6ca3.xml
rename to tests/functionaltests/suites/cite/expected/post_88b4e1ba-3bd4-4cbe-81e5-e004056d6ca3.xml
diff --git a/tests/expected/suites_cite_post_898cd63b-2585-4ec0-8720-d554bd324174.xml b/tests/functionaltests/suites/cite/expected/post_898cd63b-2585-4ec0-8720-d554bd324174.xml
similarity index 100%
rename from tests/expected/suites_cite_post_898cd63b-2585-4ec0-8720-d554bd324174.xml
rename to tests/functionaltests/suites/cite/expected/post_898cd63b-2585-4ec0-8720-d554bd324174.xml
diff --git a/tests/expected/suites_cite_post_8fb13dc3-5818-45e2-9e29-46abc16e7d38.xml b/tests/functionaltests/suites/cite/expected/post_8fb13dc3-5818-45e2-9e29-46abc16e7d38.xml
similarity index 100%
rename from tests/expected/suites_cite_post_8fb13dc3-5818-45e2-9e29-46abc16e7d38.xml
rename to tests/functionaltests/suites/cite/expected/post_8fb13dc3-5818-45e2-9e29-46abc16e7d38.xml
diff --git a/tests/expected/suites_cite_post_928c1896-52d4-4ac7-9832-f98e3eb65f02.xml b/tests/functionaltests/suites/cite/expected/post_928c1896-52d4-4ac7-9832-f98e3eb65f02.xml
similarity index 100%
rename from tests/expected/suites_cite_post_928c1896-52d4-4ac7-9832-f98e3eb65f02.xml
rename to tests/functionaltests/suites/cite/expected/post_928c1896-52d4-4ac7-9832-f98e3eb65f02.xml
diff --git a/tests/expected/suites_cite_post_93bdbb9d-2734-4f01-92fb-48634cca41de.xml b/tests/functionaltests/suites/cite/expected/post_93bdbb9d-2734-4f01-92fb-48634cca41de.xml
similarity index 100%
rename from tests/expected/suites_cite_post_93bdbb9d-2734-4f01-92fb-48634cca41de.xml
rename to tests/functionaltests/suites/cite/expected/post_93bdbb9d-2734-4f01-92fb-48634cca41de.xml
diff --git a/tests/expected/suites_cite_post_948b39d5-bb4f-45b8-a8f2-4ff9501aaedd.xml b/tests/functionaltests/suites/cite/expected/post_948b39d5-bb4f-45b8-a8f2-4ff9501aaedd.xml
similarity index 100%
rename from tests/expected/suites_cite_post_948b39d5-bb4f-45b8-a8f2-4ff9501aaedd.xml
rename to tests/functionaltests/suites/cite/expected/post_948b39d5-bb4f-45b8-a8f2-4ff9501aaedd.xml
diff --git a/tests/expected/suites_cite_post_9fd64fcc-f69c-4626-b72e-5c7776a29aa9.xml b/tests/functionaltests/suites/cite/expected/post_9fd64fcc-f69c-4626-b72e-5c7776a29aa9.xml
similarity index 100%
rename from tests/expected/suites_cite_post_9fd64fcc-f69c-4626-b72e-5c7776a29aa9.xml
rename to tests/functionaltests/suites/cite/expected/post_9fd64fcc-f69c-4626-b72e-5c7776a29aa9.xml
diff --git a/tests/expected/suites_cite_post_a06d04ab-e0d0-4a86-bfe8-71460f41fe37.xml b/tests/functionaltests/suites/cite/expected/post_a06d04ab-e0d0-4a86-bfe8-71460f41fe37.xml
similarity index 100%
rename from tests/expected/suites_cite_post_a06d04ab-e0d0-4a86-bfe8-71460f41fe37.xml
rename to tests/functionaltests/suites/cite/expected/post_a06d04ab-e0d0-4a86-bfe8-71460f41fe37.xml
diff --git a/tests/expected/suites_cite_post_ad61686c-d304-42d1-b845-8c1f3070c83e.xml b/tests/functionaltests/suites/cite/expected/post_ad61686c-d304-42d1-b845-8c1f3070c83e.xml
similarity index 100%
rename from tests/expected/suites_cite_post_ad61686c-d304-42d1-b845-8c1f3070c83e.xml
rename to tests/functionaltests/suites/cite/expected/post_ad61686c-d304-42d1-b845-8c1f3070c83e.xml
diff --git a/tests/expected/suites_cite_post_af39c020-7b1d-429c-b474-f45c3164cb79.xml b/tests/functionaltests/suites/cite/expected/post_af39c020-7b1d-429c-b474-f45c3164cb79.xml
similarity index 100%
rename from tests/expected/suites_cite_post_af39c020-7b1d-429c-b474-f45c3164cb79.xml
rename to tests/functionaltests/suites/cite/expected/post_af39c020-7b1d-429c-b474-f45c3164cb79.xml
diff --git a/tests/expected/suites_cite_post_b90e2de6-3d25-4298-a13e-dc9492a8fc73.xml b/tests/functionaltests/suites/cite/expected/post_b90e2de6-3d25-4298-a13e-dc9492a8fc73.xml
similarity index 100%
rename from tests/expected/suites_cite_post_b90e2de6-3d25-4298-a13e-dc9492a8fc73.xml
rename to tests/functionaltests/suites/cite/expected/post_b90e2de6-3d25-4298-a13e-dc9492a8fc73.xml
diff --git a/tests/expected/suites_cite_post_ba9b0107-dcee-46ef-823a-a2e25a911a96.xml b/tests/functionaltests/suites/cite/expected/post_ba9b0107-dcee-46ef-823a-a2e25a911a96.xml
similarity index 100%
rename from tests/expected/suites_cite_post_ba9b0107-dcee-46ef-823a-a2e25a911a96.xml
rename to tests/functionaltests/suites/cite/expected/post_ba9b0107-dcee-46ef-823a-a2e25a911a96.xml
diff --git a/tests/expected/suites_cite_post_bb66ebc5-7121-48b5-9f53-b56537d9561b.xml b/tests/functionaltests/suites/cite/expected/post_bb66ebc5-7121-48b5-9f53-b56537d9561b.xml
similarity index 100%
rename from tests/expected/suites_cite_post_bb66ebc5-7121-48b5-9f53-b56537d9561b.xml
rename to tests/functionaltests/suites/cite/expected/post_bb66ebc5-7121-48b5-9f53-b56537d9561b.xml
diff --git a/tests/expected/suites_cite_post_c02d1c85-df9f-45ee-bea7-345c35e02a98.xml b/tests/functionaltests/suites/cite/expected/post_c02d1c85-df9f-45ee-bea7-345c35e02a98.xml
similarity index 100%
rename from tests/expected/suites_cite_post_c02d1c85-df9f-45ee-bea7-345c35e02a98.xml
rename to tests/functionaltests/suites/cite/expected/post_c02d1c85-df9f-45ee-bea7-345c35e02a98.xml
diff --git a/tests/expected/suites_cite_post_c311a342-72e3-4983-be39-868e6ed9740f.xml b/tests/functionaltests/suites/cite/expected/post_c311a342-72e3-4983-be39-868e6ed9740f.xml
similarity index 100%
rename from tests/expected/suites_cite_post_c311a342-72e3-4983-be39-868e6ed9740f.xml
rename to tests/functionaltests/suites/cite/expected/post_c311a342-72e3-4983-be39-868e6ed9740f.xml
diff --git a/tests/expected/suites_cite_post_c38916c2-4bc6-446d-b7aa-ab006d6ba31c.xml b/tests/functionaltests/suites/cite/expected/post_c38916c2-4bc6-446d-b7aa-ab006d6ba31c.xml
similarity index 100%
rename from tests/expected/suites_cite_post_c38916c2-4bc6-446d-b7aa-ab006d6ba31c.xml
rename to tests/functionaltests/suites/cite/expected/post_c38916c2-4bc6-446d-b7aa-ab006d6ba31c.xml
diff --git a/tests/expected/suites_cite_post_c8588f47-8e65-45f5-ad34-ff4524cad84d.xml b/tests/functionaltests/suites/cite/expected/post_c8588f47-8e65-45f5-ad34-ff4524cad84d.xml
similarity index 100%
rename from tests/expected/suites_cite_post_c8588f47-8e65-45f5-ad34-ff4524cad84d.xml
rename to tests/functionaltests/suites/cite/expected/post_c8588f47-8e65-45f5-ad34-ff4524cad84d.xml
diff --git a/tests/expected/suites_cite_post_da228d4c-e1be-43d7-9ccb-c3f27ee32541.xml b/tests/functionaltests/suites/cite/expected/post_da228d4c-e1be-43d7-9ccb-c3f27ee32541.xml
similarity index 100%
rename from tests/expected/suites_cite_post_da228d4c-e1be-43d7-9ccb-c3f27ee32541.xml
rename to tests/functionaltests/suites/cite/expected/post_da228d4c-e1be-43d7-9ccb-c3f27ee32541.xml
diff --git a/tests/expected/suites_cite_post_dc92c2c4-87d8-4a13-964e-ff9b0e0c27b3.xml b/tests/functionaltests/suites/cite/expected/post_dc92c2c4-87d8-4a13-964e-ff9b0e0c27b3.xml
similarity index 100%
rename from tests/expected/suites_cite_post_dc92c2c4-87d8-4a13-964e-ff9b0e0c27b3.xml
rename to tests/functionaltests/suites/cite/expected/post_dc92c2c4-87d8-4a13-964e-ff9b0e0c27b3.xml
diff --git a/tests/expected/suites_cite_post_dcb13791-379e-4739-bcd4-dbaa69f0efdb.xml b/tests/functionaltests/suites/cite/expected/post_dcb13791-379e-4739-bcd4-dbaa69f0efdb.xml
similarity index 100%
rename from tests/expected/suites_cite_post_dcb13791-379e-4739-bcd4-dbaa69f0efdb.xml
rename to tests/functionaltests/suites/cite/expected/post_dcb13791-379e-4739-bcd4-dbaa69f0efdb.xml
diff --git a/tests/expected/suites_cite_post_e308f030-c097-4036-a838-44bad74c9ef7.xml b/tests/functionaltests/suites/cite/expected/post_e308f030-c097-4036-a838-44bad74c9ef7.xml
similarity index 100%
rename from tests/expected/suites_cite_post_e308f030-c097-4036-a838-44bad74c9ef7.xml
rename to tests/functionaltests/suites/cite/expected/post_e308f030-c097-4036-a838-44bad74c9ef7.xml
diff --git a/tests/expected/suites_cite_post_e6e9efb2-e2b7-4b0a-a3a2-7deea3f9b8e2.xml b/tests/functionaltests/suites/cite/expected/post_e6e9efb2-e2b7-4b0a-a3a2-7deea3f9b8e2.xml
similarity index 100%
rename from tests/expected/suites_cite_post_e6e9efb2-e2b7-4b0a-a3a2-7deea3f9b8e2.xml
rename to tests/functionaltests/suites/cite/expected/post_e6e9efb2-e2b7-4b0a-a3a2-7deea3f9b8e2.xml
diff --git a/tests/expected/suites_cite_post_f7976c55-a156-4421-8199-bc0487da4b0f.xml b/tests/functionaltests/suites/cite/expected/post_f7976c55-a156-4421-8199-bc0487da4b0f.xml
similarity index 100%
rename from tests/expected/suites_cite_post_f7976c55-a156-4421-8199-bc0487da4b0f.xml
rename to tests/functionaltests/suites/cite/expected/post_f7976c55-a156-4421-8199-bc0487da4b0f.xml
diff --git a/tests/expected/suites_cite_post_f7d79701-f10b-4087-a33c-f62df0a04fd1.xml b/tests/functionaltests/suites/cite/expected/post_f7d79701-f10b-4087-a33c-f62df0a04fd1.xml
similarity index 100%
rename from tests/expected/suites_cite_post_f7d79701-f10b-4087-a33c-f62df0a04fd1.xml
rename to tests/functionaltests/suites/cite/expected/post_f7d79701-f10b-4087-a33c-f62df0a04fd1.xml
diff --git a/tests/expected/suites_cite_post_fc1bc094-88f1-4851-bc2b-dfc56be9f3c7.xml b/tests/functionaltests/suites/cite/expected/post_fc1bc094-88f1-4851-bc2b-dfc56be9f3c7.xml
similarity index 100%
rename from tests/expected/suites_cite_post_fc1bc094-88f1-4851-bc2b-dfc56be9f3c7.xml
rename to tests/functionaltests/suites/cite/expected/post_fc1bc094-88f1-4851-bc2b-dfc56be9f3c7.xml
diff --git a/tests/expected/suites_cite_post_fe20960f-a26c-4f13-852d-470a0d3233f9.xml b/tests/functionaltests/suites/cite/expected/post_fe20960f-a26c-4f13-852d-470a0d3233f9.xml
similarity index 100%
rename from tests/expected/suites_cite_post_fe20960f-a26c-4f13-852d-470a0d3233f9.xml
rename to tests/functionaltests/suites/cite/expected/post_fe20960f-a26c-4f13-852d-470a0d3233f9.xml
diff --git a/tests/functionaltests/suites/cite/get/requests.txt b/tests/functionaltests/suites/cite/get/requests.txt
new file mode 100644
index 0000000..2719828
--- /dev/null
+++ b/tests/functionaltests/suites/cite/get/requests.txt
@@ -0,0 +1,22 @@
+27e17158-c57a-4493-92ac-dba8934cf462,service=CSW&version=2.0.2&request=GetCapabilities
+27f69b66-5f05-4311-a89c-73ca55c2686b,Service=CSW&Version=2.0.2&Request=GetRecordById&ElementSetName=brief&ID=urn%3Auuid%3A19887a8a-f6b0-4a63-ae56-7fba0e17801f
+2ab7d1fa-885b-459f-80e4-b6282eab4f8c,service=CSW&request=GetCapabilities&acceptversions=2.0.2&date=2006-10-20
+37aa90e2-6ff0-420c-af15-8b9463099a73,service=CSW&version=2.0.2&request=GetRecordById&id=urn%3Auuid%3A9a669547-b69b-469f-a11f-2d875366bbdc
+3a8a3c47-455f-4f49-9078-03119f3e70b3,service=CSW&request=GetCapabilities&acceptformats=message/example
+4515831f-834a-4699-95f6-ab0c2cbfcfd0,service=CSW&version=2.0.2&request=GetRecordById
+477b23a3-baa9-47c8-9541-5fe27735ed49,service=CSW&request=GetCapabilities&sections=
+48f26761-3a9d-48db-bee1-da089f5fb857,sErViCe=CSW&REQUEST=GetCapabilities&version=2.0.2
+4e38092f-1586-44b8-988e-0acfa5855916,Service=CSW&Version=2.0.2&Request=GetRecordById&OutputFormat=application/bogus_xml&id=urn:uuid:a06af396-3105-442d-8b40-22b57a90d2f2,urn:uuid:19887a8a-f6b0-4a63-ae56-7fba0e17801f,urn:uuid:ab42a8c4-95e8-4630-bf79-33e59241605a
+55c38f00-2553-42c1-99ab-33edbb561ad7,service=CSW&request=GetCapabilities&sections=OperationsMetadata,ServiceIdentification
+5ab5db18-c87a-4fbf-a8d8-b7289b09ac81,service=FOO&request=GetCapabilities
+6a4f57ca-a1bd-4802-89c2-44860dbdb0f0,service=CSW&version=2.0.2&request=GetRecordById&id=urn:uuid:ce8627a0-685c-11db-bd13-0800200c9a66,urn:uuid:6a3de50b-fa66-4b58-a0e6-ca146fdd18d4
+6c375703-9c00-4aef-bec7-d2e964f849eb,Service=CSW&Version=2.0.2&Request=GetRecordById&OutputSchema=http://www.w3.org/2005/Atom&Id=urn:uuid:19887a8a-f6b0-4a63-ae56-7fba0e17801f
+80f31def-4185-48b9-983a-960566918eae,service=CSW&request=GetCapabilities
+8e2232ed-05d9-44ae-8b04-0911cbe6a507,SERVICE=CSW&REQUEST=GetCapabilities&ACCEPTVERSIONS=2006.10.29
+9697f0aa-3b6a-4125-83a5-61e8826127c4,service=CSW&request=GetCapabilities
+9bfd17fa-15dc-4a10-8fa7-b3cff7013dd7,Service=CSW&Version=2.0.2&Request=GetRecordById&ElementSetName=full&ID=urn%3Auuid%3Ae9330592-0932-474b-be34-c3a3bb67c7db
+b81c3595-06d6-4693-82ea-1ff8650755ac,service=CSW&version=2.0.2&request=GetRecordById&id=urn:uuid:ce8627a0-685c-11db-bd13-0800200c9a66
+ba5fc729-3b71-47a0-b7d0-42ec565cd185,SERVICE=CSW&REQUEST=GetCapabilities&ACCEPTVERSIONS=2.0.2,2.0.0
+c4ea754f-c158-4d8d-8253-dc8f86021b52,request=GetCapabilities
+f4692ec5-9547-4a05-88ab-e6154af2640a,service=CSW&version=2.0.2&request=GetCapabilities
+f997f25e-c865-4d53-a362-0ed1846337f2,service=CSW&version=2.0.2&request=GetRecordById&id=urn:uuid:94bc9c83-97f6-4b40-9eb8-a8e8787a5c63
diff --git a/tests/suites/cite/post/0c976d98-c896-4b10-b1fe-a22ef50434e7.xml b/tests/functionaltests/suites/cite/post/0c976d98-c896-4b10-b1fe-a22ef50434e7.xml
similarity index 100%
rename from tests/suites/cite/post/0c976d98-c896-4b10-b1fe-a22ef50434e7.xml
rename to tests/functionaltests/suites/cite/post/0c976d98-c896-4b10-b1fe-a22ef50434e7.xml
diff --git a/tests/suites/cite/post/19d2a6ed-be28-4866-ae15-e3bb634486cb.xml b/tests/functionaltests/suites/cite/post/19d2a6ed-be28-4866-ae15-e3bb634486cb.xml
similarity index 100%
rename from tests/suites/cite/post/19d2a6ed-be28-4866-ae15-e3bb634486cb.xml
rename to tests/functionaltests/suites/cite/post/19d2a6ed-be28-4866-ae15-e3bb634486cb.xml
diff --git a/tests/suites/cite/post/1ab55aa3-6685-4595-8ecd-45987a7b8b59.xml b/tests/functionaltests/suites/cite/post/1ab55aa3-6685-4595-8ecd-45987a7b8b59.xml
similarity index 100%
rename from tests/suites/cite/post/1ab55aa3-6685-4595-8ecd-45987a7b8b59.xml
rename to tests/functionaltests/suites/cite/post/1ab55aa3-6685-4595-8ecd-45987a7b8b59.xml
diff --git a/tests/suites/cite/post/1c958b7a-ca09-4c38-98bd-ef1d1d28cc14.xml b/tests/functionaltests/suites/cite/post/1c958b7a-ca09-4c38-98bd-ef1d1d28cc14.xml
similarity index 100%
rename from tests/suites/cite/post/1c958b7a-ca09-4c38-98bd-ef1d1d28cc14.xml
rename to tests/functionaltests/suites/cite/post/1c958b7a-ca09-4c38-98bd-ef1d1d28cc14.xml
diff --git a/tests/suites/cite/post/1c97fc1a-61cd-4c1d-8054-933e17a6c5ee.xml b/tests/functionaltests/suites/cite/post/1c97fc1a-61cd-4c1d-8054-933e17a6c5ee.xml
similarity index 100%
rename from tests/suites/cite/post/1c97fc1a-61cd-4c1d-8054-933e17a6c5ee.xml
rename to tests/functionaltests/suites/cite/post/1c97fc1a-61cd-4c1d-8054-933e17a6c5ee.xml
diff --git a/tests/suites/cite/post/2102a460-5d62-465f-9668-d70b3faafbfa.xml b/tests/functionaltests/suites/cite/post/2102a460-5d62-465f-9668-d70b3faafbfa.xml
similarity index 100%
rename from tests/suites/cite/post/2102a460-5d62-465f-9668-d70b3faafbfa.xml
rename to tests/functionaltests/suites/cite/post/2102a460-5d62-465f-9668-d70b3faafbfa.xml
diff --git a/tests/suites/cite/post/225f455a-0035-486b-a94e-fee7ae881b2b.xml b/tests/functionaltests/suites/cite/post/225f455a-0035-486b-a94e-fee7ae881b2b.xml
similarity index 100%
rename from tests/suites/cite/post/225f455a-0035-486b-a94e-fee7ae881b2b.xml
rename to tests/functionaltests/suites/cite/post/225f455a-0035-486b-a94e-fee7ae881b2b.xml
diff --git a/tests/suites/cite/post/2d53ffea-60e4-4652-abf5-36eb23042fd5.xml b/tests/functionaltests/suites/cite/post/2d53ffea-60e4-4652-abf5-36eb23042fd5.xml
similarity index 100%
rename from tests/suites/cite/post/2d53ffea-60e4-4652-abf5-36eb23042fd5.xml
rename to tests/functionaltests/suites/cite/post/2d53ffea-60e4-4652-abf5-36eb23042fd5.xml
diff --git a/tests/suites/cite/post/34a019a9-1581-42cb-9827-fbfdda2773b7.xml b/tests/functionaltests/suites/cite/post/34a019a9-1581-42cb-9827-fbfdda2773b7.xml
similarity index 100%
rename from tests/suites/cite/post/34a019a9-1581-42cb-9827-fbfdda2773b7.xml
rename to tests/functionaltests/suites/cite/post/34a019a9-1581-42cb-9827-fbfdda2773b7.xml
diff --git a/tests/suites/cite/post/3e76fd38-e035-41c9-83dc-61356f680c97.xml b/tests/functionaltests/suites/cite/post/3e76fd38-e035-41c9-83dc-61356f680c97.xml
similarity index 100%
rename from tests/suites/cite/post/3e76fd38-e035-41c9-83dc-61356f680c97.xml
rename to tests/functionaltests/suites/cite/post/3e76fd38-e035-41c9-83dc-61356f680c97.xml
diff --git a/tests/suites/cite/post/418a6fb0-a89c-4a94-afc9-3f8168eb2980.xml b/tests/functionaltests/suites/cite/post/418a6fb0-a89c-4a94-afc9-3f8168eb2980.xml
similarity index 100%
rename from tests/suites/cite/post/418a6fb0-a89c-4a94-afc9-3f8168eb2980.xml
rename to tests/functionaltests/suites/cite/post/418a6fb0-a89c-4a94-afc9-3f8168eb2980.xml
diff --git a/tests/suites/cite/post/420b745e-0c4b-404e-9f2d-61fa580ff05a.xml b/tests/functionaltests/suites/cite/post/420b745e-0c4b-404e-9f2d-61fa580ff05a.xml
similarity index 100%
rename from tests/suites/cite/post/420b745e-0c4b-404e-9f2d-61fa580ff05a.xml
rename to tests/functionaltests/suites/cite/post/420b745e-0c4b-404e-9f2d-61fa580ff05a.xml
diff --git a/tests/suites/cite/post/4735d649-a2b1-42fd-a101-14e1d7e4607f.xml b/tests/functionaltests/suites/cite/post/4735d649-a2b1-42fd-a101-14e1d7e4607f.xml
similarity index 100%
rename from tests/suites/cite/post/4735d649-a2b1-42fd-a101-14e1d7e4607f.xml
rename to tests/functionaltests/suites/cite/post/4735d649-a2b1-42fd-a101-14e1d7e4607f.xml
diff --git a/tests/suites/cite/post/5c5861bc-f742-40a5-9998-5342615d674b.xml b/tests/functionaltests/suites/cite/post/5c5861bc-f742-40a5-9998-5342615d674b.xml
similarity index 100%
rename from tests/suites/cite/post/5c5861bc-f742-40a5-9998-5342615d674b.xml
rename to tests/functionaltests/suites/cite/post/5c5861bc-f742-40a5-9998-5342615d674b.xml
diff --git a/tests/suites/cite/post/6e736fd0-c266-4852-9eb3-0656f5d0f5c4.xml b/tests/functionaltests/suites/cite/post/6e736fd0-c266-4852-9eb3-0656f5d0f5c4.xml
similarity index 100%
rename from tests/suites/cite/post/6e736fd0-c266-4852-9eb3-0656f5d0f5c4.xml
rename to tests/functionaltests/suites/cite/post/6e736fd0-c266-4852-9eb3-0656f5d0f5c4.xml
diff --git a/tests/suites/cite/post/73f1551c-e269-4ef9-9dae-e535b5eebfc7.xml b/tests/functionaltests/suites/cite/post/73f1551c-e269-4ef9-9dae-e535b5eebfc7.xml
similarity index 100%
rename from tests/suites/cite/post/73f1551c-e269-4ef9-9dae-e535b5eebfc7.xml
rename to tests/functionaltests/suites/cite/post/73f1551c-e269-4ef9-9dae-e535b5eebfc7.xml
diff --git a/tests/suites/cite/post/78297c88-4850-4927-adc6-511cd9a3d539.xml b/tests/functionaltests/suites/cite/post/78297c88-4850-4927-adc6-511cd9a3d539.xml
similarity index 100%
rename from tests/suites/cite/post/78297c88-4850-4927-adc6-511cd9a3d539.xml
rename to tests/functionaltests/suites/cite/post/78297c88-4850-4927-adc6-511cd9a3d539.xml
diff --git a/tests/suites/cite/post/7c89cdf5-0def-4cfb-8c55-2b8ffea5d92f.xml b/tests/functionaltests/suites/cite/post/7c89cdf5-0def-4cfb-8c55-2b8ffea5d92f.xml
similarity index 100%
rename from tests/suites/cite/post/7c89cdf5-0def-4cfb-8c55-2b8ffea5d92f.xml
rename to tests/functionaltests/suites/cite/post/7c89cdf5-0def-4cfb-8c55-2b8ffea5d92f.xml
diff --git a/tests/suites/cite/post/7e2cd105-daec-4d25-bc8e-d49d21364912.xml b/tests/functionaltests/suites/cite/post/7e2cd105-daec-4d25-bc8e-d49d21364912.xml
similarity index 100%
rename from tests/suites/cite/post/7e2cd105-daec-4d25-bc8e-d49d21364912.xml
rename to tests/functionaltests/suites/cite/post/7e2cd105-daec-4d25-bc8e-d49d21364912.xml
diff --git a/tests/suites/cite/post/87f2f670-9cd6-4907-b82c-1b46a7dd2a78.xml b/tests/functionaltests/suites/cite/post/87f2f670-9cd6-4907-b82c-1b46a7dd2a78.xml
similarity index 100%
rename from tests/suites/cite/post/87f2f670-9cd6-4907-b82c-1b46a7dd2a78.xml
rename to tests/functionaltests/suites/cite/post/87f2f670-9cd6-4907-b82c-1b46a7dd2a78.xml
diff --git a/tests/suites/cite/post/88b4e1ba-3bd4-4cbe-81e5-e004056d6ca3.xml b/tests/functionaltests/suites/cite/post/88b4e1ba-3bd4-4cbe-81e5-e004056d6ca3.xml
similarity index 100%
rename from tests/suites/cite/post/88b4e1ba-3bd4-4cbe-81e5-e004056d6ca3.xml
rename to tests/functionaltests/suites/cite/post/88b4e1ba-3bd4-4cbe-81e5-e004056d6ca3.xml
diff --git a/tests/suites/cite/post/898cd63b-2585-4ec0-8720-d554bd324174.xml b/tests/functionaltests/suites/cite/post/898cd63b-2585-4ec0-8720-d554bd324174.xml
similarity index 100%
rename from tests/suites/cite/post/898cd63b-2585-4ec0-8720-d554bd324174.xml
rename to tests/functionaltests/suites/cite/post/898cd63b-2585-4ec0-8720-d554bd324174.xml
diff --git a/tests/suites/cite/post/8fb13dc3-5818-45e2-9e29-46abc16e7d38.xml b/tests/functionaltests/suites/cite/post/8fb13dc3-5818-45e2-9e29-46abc16e7d38.xml
similarity index 100%
rename from tests/suites/cite/post/8fb13dc3-5818-45e2-9e29-46abc16e7d38.xml
rename to tests/functionaltests/suites/cite/post/8fb13dc3-5818-45e2-9e29-46abc16e7d38.xml
diff --git a/tests/suites/cite/post/928c1896-52d4-4ac7-9832-f98e3eb65f02.xml b/tests/functionaltests/suites/cite/post/928c1896-52d4-4ac7-9832-f98e3eb65f02.xml
similarity index 100%
rename from tests/suites/cite/post/928c1896-52d4-4ac7-9832-f98e3eb65f02.xml
rename to tests/functionaltests/suites/cite/post/928c1896-52d4-4ac7-9832-f98e3eb65f02.xml
diff --git a/tests/suites/cite/post/93bdbb9d-2734-4f01-92fb-48634cca41de.xml b/tests/functionaltests/suites/cite/post/93bdbb9d-2734-4f01-92fb-48634cca41de.xml
similarity index 100%
rename from tests/suites/cite/post/93bdbb9d-2734-4f01-92fb-48634cca41de.xml
rename to tests/functionaltests/suites/cite/post/93bdbb9d-2734-4f01-92fb-48634cca41de.xml
diff --git a/tests/suites/cite/post/948b39d5-bb4f-45b8-a8f2-4ff9501aaedd.xml b/tests/functionaltests/suites/cite/post/948b39d5-bb4f-45b8-a8f2-4ff9501aaedd.xml
similarity index 100%
rename from tests/suites/cite/post/948b39d5-bb4f-45b8-a8f2-4ff9501aaedd.xml
rename to tests/functionaltests/suites/cite/post/948b39d5-bb4f-45b8-a8f2-4ff9501aaedd.xml
diff --git a/tests/suites/cite/post/9fd64fcc-f69c-4626-b72e-5c7776a29aa9.xml b/tests/functionaltests/suites/cite/post/9fd64fcc-f69c-4626-b72e-5c7776a29aa9.xml
similarity index 100%
rename from tests/suites/cite/post/9fd64fcc-f69c-4626-b72e-5c7776a29aa9.xml
rename to tests/functionaltests/suites/cite/post/9fd64fcc-f69c-4626-b72e-5c7776a29aa9.xml
diff --git a/tests/suites/cite/post/a06d04ab-e0d0-4a86-bfe8-71460f41fe37.xml b/tests/functionaltests/suites/cite/post/a06d04ab-e0d0-4a86-bfe8-71460f41fe37.xml
similarity index 100%
rename from tests/suites/cite/post/a06d04ab-e0d0-4a86-bfe8-71460f41fe37.xml
rename to tests/functionaltests/suites/cite/post/a06d04ab-e0d0-4a86-bfe8-71460f41fe37.xml
diff --git a/tests/suites/cite/post/ad61686c-d304-42d1-b845-8c1f3070c83e.xml b/tests/functionaltests/suites/cite/post/ad61686c-d304-42d1-b845-8c1f3070c83e.xml
similarity index 100%
rename from tests/suites/cite/post/ad61686c-d304-42d1-b845-8c1f3070c83e.xml
rename to tests/functionaltests/suites/cite/post/ad61686c-d304-42d1-b845-8c1f3070c83e.xml
diff --git a/tests/suites/cite/post/af39c020-7b1d-429c-b474-f45c3164cb79.xml b/tests/functionaltests/suites/cite/post/af39c020-7b1d-429c-b474-f45c3164cb79.xml
similarity index 100%
rename from tests/suites/cite/post/af39c020-7b1d-429c-b474-f45c3164cb79.xml
rename to tests/functionaltests/suites/cite/post/af39c020-7b1d-429c-b474-f45c3164cb79.xml
diff --git a/tests/suites/cite/post/b90e2de6-3d25-4298-a13e-dc9492a8fc73.xml b/tests/functionaltests/suites/cite/post/b90e2de6-3d25-4298-a13e-dc9492a8fc73.xml
similarity index 100%
rename from tests/suites/cite/post/b90e2de6-3d25-4298-a13e-dc9492a8fc73.xml
rename to tests/functionaltests/suites/cite/post/b90e2de6-3d25-4298-a13e-dc9492a8fc73.xml
diff --git a/tests/suites/cite/post/ba9b0107-dcee-46ef-823a-a2e25a911a96.xml b/tests/functionaltests/suites/cite/post/ba9b0107-dcee-46ef-823a-a2e25a911a96.xml
similarity index 100%
rename from tests/suites/cite/post/ba9b0107-dcee-46ef-823a-a2e25a911a96.xml
rename to tests/functionaltests/suites/cite/post/ba9b0107-dcee-46ef-823a-a2e25a911a96.xml
diff --git a/tests/suites/cite/post/bb66ebc5-7121-48b5-9f53-b56537d9561b.xml b/tests/functionaltests/suites/cite/post/bb66ebc5-7121-48b5-9f53-b56537d9561b.xml
similarity index 100%
rename from tests/suites/cite/post/bb66ebc5-7121-48b5-9f53-b56537d9561b.xml
rename to tests/functionaltests/suites/cite/post/bb66ebc5-7121-48b5-9f53-b56537d9561b.xml
diff --git a/tests/suites/cite/post/c02d1c85-df9f-45ee-bea7-345c35e02a98.xml b/tests/functionaltests/suites/cite/post/c02d1c85-df9f-45ee-bea7-345c35e02a98.xml
similarity index 100%
rename from tests/suites/cite/post/c02d1c85-df9f-45ee-bea7-345c35e02a98.xml
rename to tests/functionaltests/suites/cite/post/c02d1c85-df9f-45ee-bea7-345c35e02a98.xml
diff --git a/tests/suites/cite/post/c311a342-72e3-4983-be39-868e6ed9740f.xml b/tests/functionaltests/suites/cite/post/c311a342-72e3-4983-be39-868e6ed9740f.xml
similarity index 100%
rename from tests/suites/cite/post/c311a342-72e3-4983-be39-868e6ed9740f.xml
rename to tests/functionaltests/suites/cite/post/c311a342-72e3-4983-be39-868e6ed9740f.xml
diff --git a/tests/suites/cite/post/c38916c2-4bc6-446d-b7aa-ab006d6ba31c.xml b/tests/functionaltests/suites/cite/post/c38916c2-4bc6-446d-b7aa-ab006d6ba31c.xml
similarity index 100%
rename from tests/suites/cite/post/c38916c2-4bc6-446d-b7aa-ab006d6ba31c.xml
rename to tests/functionaltests/suites/cite/post/c38916c2-4bc6-446d-b7aa-ab006d6ba31c.xml
diff --git a/tests/suites/cite/post/c8588f47-8e65-45f5-ad34-ff4524cad84d.xml b/tests/functionaltests/suites/cite/post/c8588f47-8e65-45f5-ad34-ff4524cad84d.xml
similarity index 100%
rename from tests/suites/cite/post/c8588f47-8e65-45f5-ad34-ff4524cad84d.xml
rename to tests/functionaltests/suites/cite/post/c8588f47-8e65-45f5-ad34-ff4524cad84d.xml
diff --git a/tests/suites/cite/post/da228d4c-e1be-43d7-9ccb-c3f27ee32541.xml b/tests/functionaltests/suites/cite/post/da228d4c-e1be-43d7-9ccb-c3f27ee32541.xml
similarity index 100%
rename from tests/suites/cite/post/da228d4c-e1be-43d7-9ccb-c3f27ee32541.xml
rename to tests/functionaltests/suites/cite/post/da228d4c-e1be-43d7-9ccb-c3f27ee32541.xml
diff --git a/tests/suites/cite/post/dc92c2c4-87d8-4a13-964e-ff9b0e0c27b3.xml b/tests/functionaltests/suites/cite/post/dc92c2c4-87d8-4a13-964e-ff9b0e0c27b3.xml
similarity index 100%
rename from tests/suites/cite/post/dc92c2c4-87d8-4a13-964e-ff9b0e0c27b3.xml
rename to tests/functionaltests/suites/cite/post/dc92c2c4-87d8-4a13-964e-ff9b0e0c27b3.xml
diff --git a/tests/suites/cite/post/dcb13791-379e-4739-bcd4-dbaa69f0efdb.xml b/tests/functionaltests/suites/cite/post/dcb13791-379e-4739-bcd4-dbaa69f0efdb.xml
similarity index 100%
rename from tests/suites/cite/post/dcb13791-379e-4739-bcd4-dbaa69f0efdb.xml
rename to tests/functionaltests/suites/cite/post/dcb13791-379e-4739-bcd4-dbaa69f0efdb.xml
diff --git a/tests/suites/cite/post/e308f030-c097-4036-a838-44bad74c9ef7.xml b/tests/functionaltests/suites/cite/post/e308f030-c097-4036-a838-44bad74c9ef7.xml
similarity index 100%
rename from tests/suites/cite/post/e308f030-c097-4036-a838-44bad74c9ef7.xml
rename to tests/functionaltests/suites/cite/post/e308f030-c097-4036-a838-44bad74c9ef7.xml
diff --git a/tests/suites/cite/post/e6e9efb2-e2b7-4b0a-a3a2-7deea3f9b8e2.xml b/tests/functionaltests/suites/cite/post/e6e9efb2-e2b7-4b0a-a3a2-7deea3f9b8e2.xml
similarity index 100%
rename from tests/suites/cite/post/e6e9efb2-e2b7-4b0a-a3a2-7deea3f9b8e2.xml
rename to tests/functionaltests/suites/cite/post/e6e9efb2-e2b7-4b0a-a3a2-7deea3f9b8e2.xml
diff --git a/tests/suites/cite/post/f7976c55-a156-4421-8199-bc0487da4b0f.xml b/tests/functionaltests/suites/cite/post/f7976c55-a156-4421-8199-bc0487da4b0f.xml
similarity index 100%
rename from tests/suites/cite/post/f7976c55-a156-4421-8199-bc0487da4b0f.xml
rename to tests/functionaltests/suites/cite/post/f7976c55-a156-4421-8199-bc0487da4b0f.xml
diff --git a/tests/suites/cite/post/f7d79701-f10b-4087-a33c-f62df0a04fd1.xml b/tests/functionaltests/suites/cite/post/f7d79701-f10b-4087-a33c-f62df0a04fd1.xml
similarity index 100%
rename from tests/suites/cite/post/f7d79701-f10b-4087-a33c-f62df0a04fd1.xml
rename to tests/functionaltests/suites/cite/post/f7d79701-f10b-4087-a33c-f62df0a04fd1.xml
diff --git a/tests/suites/cite/post/fc1bc094-88f1-4851-bc2b-dfc56be9f3c7.xml b/tests/functionaltests/suites/cite/post/fc1bc094-88f1-4851-bc2b-dfc56be9f3c7.xml
similarity index 100%
rename from tests/suites/cite/post/fc1bc094-88f1-4851-bc2b-dfc56be9f3c7.xml
rename to tests/functionaltests/suites/cite/post/fc1bc094-88f1-4851-bc2b-dfc56be9f3c7.xml
diff --git a/tests/suites/cite/post/fe20960f-a26c-4f13-852d-470a0d3233f9.xml b/tests/functionaltests/suites/cite/post/fe20960f-a26c-4f13-852d-470a0d3233f9.xml
similarity index 100%
rename from tests/suites/cite/post/fe20960f-a26c-4f13-852d-470a0d3233f9.xml
rename to tests/functionaltests/suites/cite/post/fe20960f-a26c-4f13-852d-470a0d3233f9.xml
diff --git a/tests/suites/csw30/default.cfg b/tests/functionaltests/suites/csw30/default.cfg
similarity index 100%
rename from tests/suites/csw30/default.cfg
rename to tests/functionaltests/suites/csw30/default.cfg
diff --git a/tests/expected/suites_csw30_get_002258f0-627f-457f-b2ad-025777c77ac8.xml b/tests/functionaltests/suites/csw30/expected/get_002258f0-627f-457f-b2ad-025777c77ac8.xml
similarity index 100%
rename from tests/expected/suites_csw30_get_002258f0-627f-457f-b2ad-025777c77ac8.xml
rename to tests/functionaltests/suites/csw30/expected/get_002258f0-627f-457f-b2ad-025777c77ac8.xml
diff --git a/tests/expected/suites_csw30_get_045c600d-973d-41eb-9f60-eba1b717b720.xml b/tests/functionaltests/suites/csw30/expected/get_045c600d-973d-41eb-9f60-eba1b717b720.xml
similarity index 100%
rename from tests/expected/suites_csw30_get_045c600d-973d-41eb-9f60-eba1b717b720.xml
rename to tests/functionaltests/suites/csw30/expected/get_045c600d-973d-41eb-9f60-eba1b717b720.xml
diff --git a/tests/expected/suites_csw30_get_0bbcf862-5211-4351-9988-63f8bec49c98.xml b/tests/functionaltests/suites/csw30/expected/get_0bbcf862-5211-4351-9988-63f8bec49c98.xml
similarity index 100%
rename from tests/expected/suites_csw30_get_0bbcf862-5211-4351-9988-63f8bec49c98.xml
rename to tests/functionaltests/suites/csw30/expected/get_0bbcf862-5211-4351-9988-63f8bec49c98.xml
diff --git a/tests/expected/suites_csw30_get_22f44168-2ccf-4801-ad96-204212566d56.xml b/tests/functionaltests/suites/csw30/expected/get_0bdf8457-971e-4ed1-be4a-5feca4dcd8fa.xml
similarity index 99%
copy from tests/expected/suites_csw30_get_22f44168-2ccf-4801-ad96-204212566d56.xml
copy to tests/functionaltests/suites/csw30/expected/get_0bdf8457-971e-4ed1-be4a-5feca4dcd8fa.xml
index c5cb70e..a68d7f2 100644
--- a/tests/expected/suites_csw30_get_22f44168-2ccf-4801-ad96-204212566d56.xml
+++ b/tests/functionaltests/suites/csw30/expected/get_0bdf8457-971e-4ed1-be4a-5feca4dcd8fa.xml
@@ -132,6 +132,7 @@
       </ows20:Parameter>
       <ows20:Parameter name="typeNames">
         <ows20:AllowedValues>
+          <ows20:Value>csw30:Record</ows20:Value>
           <ows20:Value>csw:Record</ows20:Value>
         </ows20:AllowedValues>
       </ows20:Parameter>
diff --git a/tests/expected/suites_csw30_get_0d8bbdec-0846-42ca-8dc8-b7f4cba41d67.xml b/tests/functionaltests/suites/csw30/expected/get_0d8bbdec-0846-42ca-8dc8-b7f4cba41d67.xml
similarity index 100%
rename from tests/expected/suites_csw30_get_0d8bbdec-0846-42ca-8dc8-b7f4cba41d67.xml
rename to tests/functionaltests/suites/csw30/expected/get_0d8bbdec-0846-42ca-8dc8-b7f4cba41d67.xml
diff --git a/tests/expected/suites_csw30_get_0e1dca37-477a-4060-99fe-7799b52d656c.xml b/tests/functionaltests/suites/csw30/expected/get_0e1dca37-477a-4060-99fe-7799b52d656c.xml
similarity index 100%
rename from tests/expected/suites_csw30_get_0e1dca37-477a-4060-99fe-7799b52d656c.xml
rename to tests/functionaltests/suites/csw30/expected/get_0e1dca37-477a-4060-99fe-7799b52d656c.xml
diff --git a/tests/expected/suites_csw30_get_13c87956-51a4-4780-a8e9-6e0b5c0bb473.xml b/tests/functionaltests/suites/csw30/expected/get_13c87956-51a4-4780-a8e9-6e0b5c0bb473.xml
similarity index 100%
rename from tests/expected/suites_csw30_get_13c87956-51a4-4780-a8e9-6e0b5c0bb473.xml
rename to tests/functionaltests/suites/csw30/expected/get_13c87956-51a4-4780-a8e9-6e0b5c0bb473.xml
diff --git a/tests/expected/suites_csw30_get_151d982f-ebd3-4cb2-b507-a667713a1e92.xml b/tests/functionaltests/suites/csw30/expected/get_151d982f-ebd3-4cb2-b507-a667713a1e92.xml
similarity index 100%
rename from tests/expected/suites_csw30_get_151d982f-ebd3-4cb2-b507-a667713a1e92.xml
rename to tests/functionaltests/suites/csw30/expected/get_151d982f-ebd3-4cb2-b507-a667713a1e92.xml
diff --git a/tests/expected/suites_csw30_get_1869e495-1a61-4713-8285-76d1336ee1a6.xml b/tests/functionaltests/suites/csw30/expected/get_1869e495-1a61-4713-8285-76d1336ee1a6.xml
similarity index 100%
rename from tests/expected/suites_csw30_get_1869e495-1a61-4713-8285-76d1336ee1a6.xml
rename to tests/functionaltests/suites/csw30/expected/get_1869e495-1a61-4713-8285-76d1336ee1a6.xml
diff --git a/tests/expected/suites_csw30_get_1bcb42a9-538c-4f0a-9d4c-d6f10b720aa6.xml b/tests/functionaltests/suites/csw30/expected/get_1bcb42a9-538c-4f0a-9d4c-d6f10b720aa6.xml
similarity index 100%
rename from tests/expected/suites_csw30_get_1bcb42a9-538c-4f0a-9d4c-d6f10b720aa6.xml
rename to tests/functionaltests/suites/csw30/expected/get_1bcb42a9-538c-4f0a-9d4c-d6f10b720aa6.xml
diff --git a/tests/expected/suites_csw30_get_0bdf8457-971e-4ed1-be4a-5feca4dcd8fa.xml b/tests/functionaltests/suites/csw30/expected/get_22f44168-2ccf-4801-ad96-204212566d56.xml
similarity index 99%
rename from tests/expected/suites_csw30_get_0bdf8457-971e-4ed1-be4a-5feca4dcd8fa.xml
rename to tests/functionaltests/suites/csw30/expected/get_22f44168-2ccf-4801-ad96-204212566d56.xml
index c5cb70e..a68d7f2 100644
--- a/tests/expected/suites_csw30_get_0bdf8457-971e-4ed1-be4a-5feca4dcd8fa.xml
+++ b/tests/functionaltests/suites/csw30/expected/get_22f44168-2ccf-4801-ad96-204212566d56.xml
@@ -132,6 +132,7 @@
       </ows20:Parameter>
       <ows20:Parameter name="typeNames">
         <ows20:AllowedValues>
+          <ows20:Value>csw30:Record</ows20:Value>
           <ows20:Value>csw:Record</ows20:Value>
         </ows20:AllowedValues>
       </ows20:Parameter>
diff --git a/tests/expected/suites_csw30_get_2499a9c9-8d33-449c-bc92-d494adfcc84d.xml b/tests/functionaltests/suites/csw30/expected/get_2499a9c9-8d33-449c-bc92-d494adfcc84d.xml
similarity index 99%
rename from tests/expected/suites_csw30_get_2499a9c9-8d33-449c-bc92-d494adfcc84d.xml
rename to tests/functionaltests/suites/csw30/expected/get_2499a9c9-8d33-449c-bc92-d494adfcc84d.xml
index c5cb70e..a68d7f2 100644
--- a/tests/expected/suites_csw30_get_2499a9c9-8d33-449c-bc92-d494adfcc84d.xml
+++ b/tests/functionaltests/suites/csw30/expected/get_2499a9c9-8d33-449c-bc92-d494adfcc84d.xml
@@ -132,6 +132,7 @@
       </ows20:Parameter>
       <ows20:Parameter name="typeNames">
         <ows20:AllowedValues>
+          <ows20:Value>csw30:Record</ows20:Value>
           <ows20:Value>csw:Record</ows20:Value>
         </ows20:AllowedValues>
       </ows20:Parameter>
diff --git a/tests/expected/suites_csw30_get_27f4f39c-d92a-4e3c-b961-c6aa8c24e513.xml b/tests/functionaltests/suites/csw30/expected/get_27f4f39c-d92a-4e3c-b961-c6aa8c24e513.xml
similarity index 99%
rename from tests/expected/suites_csw30_get_27f4f39c-d92a-4e3c-b961-c6aa8c24e513.xml
rename to tests/functionaltests/suites/csw30/expected/get_27f4f39c-d92a-4e3c-b961-c6aa8c24e513.xml
index c5cb70e..a68d7f2 100644
--- a/tests/expected/suites_csw30_get_27f4f39c-d92a-4e3c-b961-c6aa8c24e513.xml
+++ b/tests/functionaltests/suites/csw30/expected/get_27f4f39c-d92a-4e3c-b961-c6aa8c24e513.xml
@@ -132,6 +132,7 @@
       </ows20:Parameter>
       <ows20:Parameter name="typeNames">
         <ows20:AllowedValues>
+          <ows20:Value>csw30:Record</ows20:Value>
           <ows20:Value>csw:Record</ows20:Value>
         </ows20:AllowedValues>
       </ows20:Parameter>
diff --git a/tests/expected/suites_csw30_get_28e569df-8596-4128-8d9a-29ad03138915.xml b/tests/functionaltests/suites/csw30/expected/get_28e569df-8596-4128-8d9a-29ad03138915.xml
similarity index 100%
rename from tests/expected/suites_csw30_get_28e569df-8596-4128-8d9a-29ad03138915.xml
rename to tests/functionaltests/suites/csw30/expected/get_28e569df-8596-4128-8d9a-29ad03138915.xml
diff --git a/tests/expected/suites_csw30_get_22f44168-2ccf-4801-ad96-204212566d56.xml b/tests/functionaltests/suites/csw30/expected/get_2b06a5c8-0df2-4af1-8d2e-a425de11c845.xml
similarity index 99%
copy from tests/expected/suites_csw30_get_22f44168-2ccf-4801-ad96-204212566d56.xml
copy to tests/functionaltests/suites/csw30/expected/get_2b06a5c8-0df2-4af1-8d2e-a425de11c845.xml
index c5cb70e..a68d7f2 100644
--- a/tests/expected/suites_csw30_get_22f44168-2ccf-4801-ad96-204212566d56.xml
+++ b/tests/functionaltests/suites/csw30/expected/get_2b06a5c8-0df2-4af1-8d2e-a425de11c845.xml
@@ -132,6 +132,7 @@
       </ows20:Parameter>
       <ows20:Parameter name="typeNames">
         <ows20:AllowedValues>
+          <ows20:Value>csw30:Record</ows20:Value>
           <ows20:Value>csw:Record</ows20:Value>
         </ows20:AllowedValues>
       </ows20:Parameter>
diff --git a/tests/expected/suites_csw30_get_2ba1418a-444d-4cce-9cfe-4c94efcf8b55.xml b/tests/functionaltests/suites/csw30/expected/get_2ba1418a-444d-4cce-9cfe-4c94efcf8b55.xml
similarity index 100%
rename from tests/expected/suites_csw30_get_2ba1418a-444d-4cce-9cfe-4c94efcf8b55.xml
rename to tests/functionaltests/suites/csw30/expected/get_2ba1418a-444d-4cce-9cfe-4c94efcf8b55.xml
diff --git a/tests/expected/suites_csw30_get_397fe17a-d5b4-4f96-8cc4-4ce467ed4d0a.xml b/tests/functionaltests/suites/csw30/expected/get_397fe17a-d5b4-4f96-8cc4-4ce467ed4d0a.xml
similarity index 100%
rename from tests/expected/suites_csw30_get_397fe17a-d5b4-4f96-8cc4-4ce467ed4d0a.xml
rename to tests/functionaltests/suites/csw30/expected/get_397fe17a-d5b4-4f96-8cc4-4ce467ed4d0a.xml
diff --git a/tests/expected/suites_csw30_get_3dcd1b15-73d2-4b7d-a3e3-ff15bf14aae4.xml b/tests/functionaltests/suites/csw30/expected/get_3dcd1b15-73d2-4b7d-a3e3-ff15bf14aae4.xml
similarity index 100%
rename from tests/expected/suites_csw30_get_3dcd1b15-73d2-4b7d-a3e3-ff15bf14aae4.xml
rename to tests/functionaltests/suites/csw30/expected/get_3dcd1b15-73d2-4b7d-a3e3-ff15bf14aae4.xml
diff --git a/tests/expected/suites_csw30_get_405e1ff1-5c75-4846-a28b-cfaff2a6921a.xml b/tests/functionaltests/suites/csw30/expected/get_405e1ff1-5c75-4846-a28b-cfaff2a6921a.xml
similarity index 100%
rename from tests/expected/suites_csw30_get_405e1ff1-5c75-4846-a28b-cfaff2a6921a.xml
rename to tests/functionaltests/suites/csw30/expected/get_405e1ff1-5c75-4846-a28b-cfaff2a6921a.xml
diff --git a/tests/expected/suites_csw30_get_22f44168-2ccf-4801-ad96-204212566d56.xml b/tests/functionaltests/suites/csw30/expected/get_43cd6471-6ac7-45bd-8ff9-148cb2de9a52.xml
similarity index 99%
copy from tests/expected/suites_csw30_get_22f44168-2ccf-4801-ad96-204212566d56.xml
copy to tests/functionaltests/suites/csw30/expected/get_43cd6471-6ac7-45bd-8ff9-148cb2de9a52.xml
index c5cb70e..a68d7f2 100644
--- a/tests/expected/suites_csw30_get_22f44168-2ccf-4801-ad96-204212566d56.xml
+++ b/tests/functionaltests/suites/csw30/expected/get_43cd6471-6ac7-45bd-8ff9-148cb2de9a52.xml
@@ -132,6 +132,7 @@
       </ows20:Parameter>
       <ows20:Parameter name="typeNames">
         <ows20:AllowedValues>
+          <ows20:Value>csw30:Record</ows20:Value>
           <ows20:Value>csw:Record</ows20:Value>
         </ows20:AllowedValues>
       </ows20:Parameter>
diff --git a/tests/expected/suites_csw30_get_4566d2ec-1283-4a02-baed-a74fc5b47e37.xml b/tests/functionaltests/suites/csw30/expected/get_4566d2ec-1283-4a02-baed-a74fc5b47e37.xml
similarity index 100%
rename from tests/expected/suites_csw30_get_4566d2ec-1283-4a02-baed-a74fc5b47e37.xml
rename to tests/functionaltests/suites/csw30/expected/get_4566d2ec-1283-4a02-baed-a74fc5b47e37.xml
diff --git a/tests/expected/suites_csw30_get_461bd4c5-6623-490d-9036-d91a2201e87b.xml b/tests/functionaltests/suites/csw30/expected/get_461bd4c5-6623-490d-9036-d91a2201e87b.xml
similarity index 100%
rename from tests/expected/suites_csw30_get_461bd4c5-6623-490d-9036-d91a2201e87b.xml
rename to tests/functionaltests/suites/csw30/expected/get_461bd4c5-6623-490d-9036-d91a2201e87b.xml
diff --git a/tests/expected/suites_csw30_get_5496894a-3877-4f62-a20b-5d7126f94925.xml b/tests/functionaltests/suites/csw30/expected/get_5496894a-3877-4f62-a20b-5d7126f94925.xml
similarity index 100%
rename from tests/expected/suites_csw30_get_5496894a-3877-4f62-a20b-5d7126f94925.xml
rename to tests/functionaltests/suites/csw30/expected/get_5496894a-3877-4f62-a20b-5d7126f94925.xml
diff --git a/tests/expected/suites_csw30_get_5a015f6a-bf14-4977-b1e3-6577eb0223c8.xml b/tests/functionaltests/suites/csw30/expected/get_5a015f6a-bf14-4977-b1e3-6577eb0223c8.xml
similarity index 100%
rename from tests/expected/suites_csw30_get_5a015f6a-bf14-4977-b1e3-6577eb0223c8.xml
rename to tests/functionaltests/suites/csw30/expected/get_5a015f6a-bf14-4977-b1e3-6577eb0223c8.xml
diff --git a/tests/expected/suites_csw30_get_5c3a2390-1fb9-43f0-b96c-f48c7a69c990.xml b/tests/functionaltests/suites/csw30/expected/get_5c3a2390-1fb9-43f0-b96c-f48c7a69c990.xml
similarity index 100%
rename from tests/expected/suites_csw30_get_5c3a2390-1fb9-43f0-b96c-f48c7a69c990.xml
rename to tests/functionaltests/suites/csw30/expected/get_5c3a2390-1fb9-43f0-b96c-f48c7a69c990.xml
diff --git a/tests/expected/suites_csw30_get_5e9e67dc-18d6-4645-8111-c6263c88a61f.xml b/tests/functionaltests/suites/csw30/expected/get_5e9e67dc-18d6-4645-8111-c6263c88a61f.xml
similarity index 99%
rename from tests/expected/suites_csw30_get_5e9e67dc-18d6-4645-8111-c6263c88a61f.xml
rename to tests/functionaltests/suites/csw30/expected/get_5e9e67dc-18d6-4645-8111-c6263c88a61f.xml
index 2037f14..af7b63f 100644
--- a/tests/expected/suites_csw30_get_5e9e67dc-18d6-4645-8111-c6263c88a61f.xml
+++ b/tests/functionaltests/suites/csw30/expected/get_5e9e67dc-18d6-4645-8111-c6263c88a61f.xml
@@ -92,6 +92,7 @@
       </ows20:Parameter>
       <ows20:Parameter name="typeNames">
         <ows20:AllowedValues>
+          <ows20:Value>csw30:Record</ows20:Value>
           <ows20:Value>csw:Record</ows20:Value>
         </ows20:AllowedValues>
       </ows20:Parameter>
diff --git a/tests/expected/suites_csw30_get_604d9379-741c-42e5-b4cf-92e56c87fa64.xml b/tests/functionaltests/suites/csw30/expected/get_604d9379-741c-42e5-b4cf-92e56c87fa64.xml
similarity index 100%
rename from tests/expected/suites_csw30_get_604d9379-741c-42e5-b4cf-92e56c87fa64.xml
rename to tests/functionaltests/suites/csw30/expected/get_604d9379-741c-42e5-b4cf-92e56c87fa64.xml
diff --git a/tests/expected/suites_csw30_get_60e6af95-d5fc-465a-82e2-fd2e6d85e4af.xml b/tests/functionaltests/suites/csw30/expected/get_60e6af95-d5fc-465a-82e2-fd2e6d85e4af.xml
similarity index 100%
rename from tests/expected/suites_csw30_get_60e6af95-d5fc-465a-82e2-fd2e6d85e4af.xml
rename to tests/functionaltests/suites/csw30/expected/get_60e6af95-d5fc-465a-82e2-fd2e6d85e4af.xml
diff --git a/tests/expected/suites_csw30_get_62ad94c2-b558-4265-a427-23d6677975d6.xml b/tests/functionaltests/suites/csw30/expected/get_62ad94c2-b558-4265-a427-23d6677975d6.xml
similarity index 100%
rename from tests/expected/suites_csw30_get_62ad94c2-b558-4265-a427-23d6677975d6.xml
rename to tests/functionaltests/suites/csw30/expected/get_62ad94c2-b558-4265-a427-23d6677975d6.xml
diff --git a/tests/expected/suites_csw30_get_6a5e247b-0961-4b8a-a0d6-35a491d9cfe7.xml b/tests/functionaltests/suites/csw30/expected/get_6a5e247b-0961-4b8a-a0d6-35a491d9cfe7.xml
similarity index 100%
rename from tests/expected/suites_csw30_get_6a5e247b-0961-4b8a-a0d6-35a491d9cfe7.xml
rename to tests/functionaltests/suites/csw30/expected/get_6a5e247b-0961-4b8a-a0d6-35a491d9cfe7.xml
diff --git a/tests/expected/suites_csw30_get_22f44168-2ccf-4801-ad96-204212566d56.xml b/tests/functionaltests/suites/csw30/expected/get_6a9d0558-9d87-495b-b999-b49a3ef1cf99.xml
similarity index 99%
copy from tests/expected/suites_csw30_get_22f44168-2ccf-4801-ad96-204212566d56.xml
copy to tests/functionaltests/suites/csw30/expected/get_6a9d0558-9d87-495b-b999-b49a3ef1cf99.xml
index c5cb70e..a68d7f2 100644
--- a/tests/expected/suites_csw30_get_22f44168-2ccf-4801-ad96-204212566d56.xml
+++ b/tests/functionaltests/suites/csw30/expected/get_6a9d0558-9d87-495b-b999-b49a3ef1cf99.xml
@@ -132,6 +132,7 @@
       </ows20:Parameter>
       <ows20:Parameter name="typeNames">
         <ows20:AllowedValues>
+          <ows20:Value>csw30:Record</ows20:Value>
           <ows20:Value>csw:Record</ows20:Value>
         </ows20:AllowedValues>
       </ows20:Parameter>
diff --git a/tests/expected/suites_csw30_get_6bd790c9-6019-4652-9c91-330a894d6700.xml b/tests/functionaltests/suites/csw30/expected/get_6bd790c9-6019-4652-9c91-330a894d6700.xml
similarity index 100%
rename from tests/expected/suites_csw30_get_6bd790c9-6019-4652-9c91-330a894d6700.xml
rename to tests/functionaltests/suites/csw30/expected/get_6bd790c9-6019-4652-9c91-330a894d6700.xml
diff --git a/tests/expected/suites_csw30_get_22f44168-2ccf-4801-ad96-204212566d56.xml b/tests/functionaltests/suites/csw30/expected/get_6e9cba43-5e27-415d-adbd-a92851c2c173.xml
similarity index 99%
copy from tests/expected/suites_csw30_get_22f44168-2ccf-4801-ad96-204212566d56.xml
copy to tests/functionaltests/suites/csw30/expected/get_6e9cba43-5e27-415d-adbd-a92851c2c173.xml
index c5cb70e..a68d7f2 100644
--- a/tests/expected/suites_csw30_get_22f44168-2ccf-4801-ad96-204212566d56.xml
+++ b/tests/functionaltests/suites/csw30/expected/get_6e9cba43-5e27-415d-adbd-a92851c2c173.xml
@@ -132,6 +132,7 @@
       </ows20:Parameter>
       <ows20:Parameter name="typeNames">
         <ows20:AllowedValues>
+          <ows20:Value>csw30:Record</ows20:Value>
           <ows20:Value>csw:Record</ows20:Value>
         </ows20:AllowedValues>
       </ows20:Parameter>
diff --git a/tests/expected/suites_csw30_get_7630d230-e142-4a09-accf-f091000b90cd.xml b/tests/functionaltests/suites/csw30/expected/get_7630d230-e142-4a09-accf-f091000b90cd.xml
similarity index 100%
rename from tests/expected/suites_csw30_get_7630d230-e142-4a09-accf-f091000b90cd.xml
rename to tests/functionaltests/suites/csw30/expected/get_7630d230-e142-4a09-accf-f091000b90cd.xml
diff --git a/tests/expected/suites_csw30_get_22f44168-2ccf-4801-ad96-204212566d56.xml b/tests/functionaltests/suites/csw30/expected/get_7e82446a-b5dc-43fe-9a73-4cc1f2f2f0bf.xml
similarity index 99%
copy from tests/expected/suites_csw30_get_22f44168-2ccf-4801-ad96-204212566d56.xml
copy to tests/functionaltests/suites/csw30/expected/get_7e82446a-b5dc-43fe-9a73-4cc1f2f2f0bf.xml
index c5cb70e..a68d7f2 100644
--- a/tests/expected/suites_csw30_get_22f44168-2ccf-4801-ad96-204212566d56.xml
+++ b/tests/functionaltests/suites/csw30/expected/get_7e82446a-b5dc-43fe-9a73-4cc1f2f2f0bf.xml
@@ -132,6 +132,7 @@
       </ows20:Parameter>
       <ows20:Parameter name="typeNames">
         <ows20:AllowedValues>
+          <ows20:Value>csw30:Record</ows20:Value>
           <ows20:Value>csw:Record</ows20:Value>
         </ows20:AllowedValues>
       </ows20:Parameter>
diff --git a/tests/expected/suites_csw30_get_22f44168-2ccf-4801-ad96-204212566d56.xml b/tests/functionaltests/suites/csw30/expected/get_8025978e-1a35-4d70-80c2-e8329e0c7864.xml
similarity index 99%
copy from tests/expected/suites_csw30_get_22f44168-2ccf-4801-ad96-204212566d56.xml
copy to tests/functionaltests/suites/csw30/expected/get_8025978e-1a35-4d70-80c2-e8329e0c7864.xml
index c5cb70e..a68d7f2 100644
--- a/tests/expected/suites_csw30_get_22f44168-2ccf-4801-ad96-204212566d56.xml
+++ b/tests/functionaltests/suites/csw30/expected/get_8025978e-1a35-4d70-80c2-e8329e0c7864.xml
@@ -132,6 +132,7 @@
       </ows20:Parameter>
       <ows20:Parameter name="typeNames">
         <ows20:AllowedValues>
+          <ows20:Value>csw30:Record</ows20:Value>
           <ows20:Value>csw:Record</ows20:Value>
         </ows20:AllowedValues>
       </ows20:Parameter>
diff --git a/tests/expected/suites_csw30_get_8184ae4f-536d-4978-8b28-ad703be96967.xml b/tests/functionaltests/suites/csw30/expected/get_8184ae4f-536d-4978-8b28-ad703be96967.xml
similarity index 100%
rename from tests/expected/suites_csw30_get_8184ae4f-536d-4978-8b28-ad703be96967.xml
rename to tests/functionaltests/suites/csw30/expected/get_8184ae4f-536d-4978-8b28-ad703be96967.xml
diff --git a/tests/expected/suites_csw30_get_88f63a89-664f-4315-b4f8-04a0b33803a7.xml b/tests/functionaltests/suites/csw30/expected/get_88f63a89-664f-4315-b4f8-04a0b33803a7.xml
similarity index 100%
rename from tests/expected/suites_csw30_get_88f63a89-664f-4315-b4f8-04a0b33803a7.xml
rename to tests/functionaltests/suites/csw30/expected/get_88f63a89-664f-4315-b4f8-04a0b33803a7.xml
diff --git a/tests/expected/suites_csw30_get_8987f8f0-4d93-4481-968c-a2ccbd6b8be2.xml b/tests/functionaltests/suites/csw30/expected/get_8987f8f0-4d93-4481-968c-a2ccbd6b8be2.xml
similarity index 100%
rename from tests/expected/suites_csw30_get_8987f8f0-4d93-4481-968c-a2ccbd6b8be2.xml
rename to tests/functionaltests/suites/csw30/expected/get_8987f8f0-4d93-4481-968c-a2ccbd6b8be2.xml
diff --git a/tests/expected/suites_csw30_get_8e5fa0f6-3f29-4d1f-abe2-d9866f3def98.xml b/tests/functionaltests/suites/csw30/expected/get_8e5fa0f6-3f29-4d1f-abe2-d9866f3def98.xml
similarity index 100%
rename from tests/expected/suites_csw30_get_8e5fa0f6-3f29-4d1f-abe2-d9866f3def98.xml
rename to tests/functionaltests/suites/csw30/expected/get_8e5fa0f6-3f29-4d1f-abe2-d9866f3def98.xml
diff --git a/tests/expected/suites_csw30_get_9000ec29-5649-474e-b2d6-55c00f8a52c0.xml b/tests/functionaltests/suites/csw30/expected/get_9000ec29-5649-474e-b2d6-55c00f8a52c0.xml
similarity index 100%
rename from tests/expected/suites_csw30_get_9000ec29-5649-474e-b2d6-55c00f8a52c0.xml
rename to tests/functionaltests/suites/csw30/expected/get_9000ec29-5649-474e-b2d6-55c00f8a52c0.xml
diff --git a/tests/expected/suites_csw30_get_91914d35-7bbf-45e6-9b37-5ef484869a4e.xml b/tests/functionaltests/suites/csw30/expected/get_91914d35-7bbf-45e6-9b37-5ef484869a4e.xml
similarity index 100%
rename from tests/expected/suites_csw30_get_91914d35-7bbf-45e6-9b37-5ef484869a4e.xml
rename to tests/functionaltests/suites/csw30/expected/get_91914d35-7bbf-45e6-9b37-5ef484869a4e.xml
diff --git a/tests/expected/suites_csw30_get_92d4844d-57d5-4cf3-8f47-ba50e369dc04.xml b/tests/functionaltests/suites/csw30/expected/get_92d4844d-57d5-4cf3-8f47-ba50e369dc04.xml
similarity index 100%
rename from tests/expected/suites_csw30_get_92d4844d-57d5-4cf3-8f47-ba50e369dc04.xml
rename to tests/functionaltests/suites/csw30/expected/get_92d4844d-57d5-4cf3-8f47-ba50e369dc04.xml
diff --git a/tests/expected/suites_csw30_get_9c0e2a4b-b4e6-41c0-b630-c8c99fc89ff3.xml b/tests/functionaltests/suites/csw30/expected/get_9c0e2a4b-b4e6-41c0-b630-c8c99fc89ff3.xml
similarity index 100%
rename from tests/expected/suites_csw30_get_9c0e2a4b-b4e6-41c0-b630-c8c99fc89ff3.xml
rename to tests/functionaltests/suites/csw30/expected/get_9c0e2a4b-b4e6-41c0-b630-c8c99fc89ff3.xml
diff --git a/tests/expected/suites_csw30_get_9d7ffac8-9798-428d-8e27-3cd12497ee6b.xml b/tests/functionaltests/suites/csw30/expected/get_9d7ffac8-9798-428d-8e27-3cd12497ee6b.xml
similarity index 100%
rename from tests/expected/suites_csw30_get_9d7ffac8-9798-428d-8e27-3cd12497ee6b.xml
rename to tests/functionaltests/suites/csw30/expected/get_9d7ffac8-9798-428d-8e27-3cd12497ee6b.xml
diff --git a/tests/expected/suites_csw30_get_Exception-GetDomain-value-reference.xml b/tests/functionaltests/suites/csw30/expected/get_Exception-GetDomain-value-reference.xml
similarity index 100%
rename from tests/expected/suites_csw30_get_Exception-GetDomain-value-reference.xml
rename to tests/functionaltests/suites/csw30/expected/get_Exception-GetDomain-value-reference.xml
diff --git a/tests/expected/suites_csw30_get_Exception-GetDomain.xml b/tests/functionaltests/suites/csw30/expected/get_Exception-GetDomain.xml
similarity index 100%
rename from tests/expected/suites_csw30_get_Exception-GetDomain.xml
rename to tests/functionaltests/suites/csw30/expected/get_Exception-GetDomain.xml
diff --git a/tests/expected/suites_csw30_get_Exception-GetRecordById-404.xml b/tests/functionaltests/suites/csw30/expected/get_Exception-GetRecordById-404.xml
similarity index 100%
rename from tests/expected/suites_csw30_get_Exception-GetRecordById-404.xml
rename to tests/functionaltests/suites/csw30/expected/get_Exception-GetRecordById-404.xml
diff --git a/tests/expected/suites_csw30_get_Exception-GetRecordById-dc.xml.xml b/tests/functionaltests/suites/csw30/expected/get_Exception-GetRecordById-dc.xml.xml
similarity index 100%
rename from tests/expected/suites_csw30_get_Exception-GetRecordById-dc.xml.xml
rename to tests/functionaltests/suites/csw30/expected/get_Exception-GetRecordById-dc.xml.xml
diff --git a/tests/expected/suites_csw30_get_Exception-GetRepositoryItem-notfound.xml b/tests/functionaltests/suites/csw30/expected/get_Exception-GetRepositoryItem-notfound.xml
similarity index 100%
rename from tests/expected/suites_csw30_get_Exception-GetRepositoryItem-notfound.xml
rename to tests/functionaltests/suites/csw30/expected/get_Exception-GetRepositoryItem-notfound.xml
diff --git a/tests/expected/suites_csw30_get_Exception-invalid-request.xml b/tests/functionaltests/suites/csw30/expected/get_Exception-invalid-request.xml
similarity index 100%
rename from tests/expected/suites_csw30_get_Exception-invalid-request.xml
rename to tests/functionaltests/suites/csw30/expected/get_Exception-invalid-request.xml
diff --git a/tests/expected/suites_csw30_get_22f44168-2ccf-4801-ad96-204212566d56.xml b/tests/functionaltests/suites/csw30/expected/get_GetCapabilities-base-url.xml
similarity index 99%
copy from tests/expected/suites_csw30_get_22f44168-2ccf-4801-ad96-204212566d56.xml
copy to tests/functionaltests/suites/csw30/expected/get_GetCapabilities-base-url.xml
index c5cb70e..a68d7f2 100644
--- a/tests/expected/suites_csw30_get_22f44168-2ccf-4801-ad96-204212566d56.xml
+++ b/tests/functionaltests/suites/csw30/expected/get_GetCapabilities-base-url.xml
@@ -132,6 +132,7 @@
       </ows20:Parameter>
       <ows20:Parameter name="typeNames">
         <ows20:AllowedValues>
+          <ows20:Value>csw30:Record</ows20:Value>
           <ows20:Value>csw:Record</ows20:Value>
         </ows20:AllowedValues>
       </ows20:Parameter>
diff --git a/tests/expected/suites_csw30_get_22f44168-2ccf-4801-ad96-204212566d56.xml b/tests/functionaltests/suites/csw30/expected/get_GetCapabilities-no-version.xml
similarity index 99%
copy from tests/expected/suites_csw30_get_22f44168-2ccf-4801-ad96-204212566d56.xml
copy to tests/functionaltests/suites/csw30/expected/get_GetCapabilities-no-version.xml
index c5cb70e..a68d7f2 100644
--- a/tests/expected/suites_csw30_get_22f44168-2ccf-4801-ad96-204212566d56.xml
+++ b/tests/functionaltests/suites/csw30/expected/get_GetCapabilities-no-version.xml
@@ -132,6 +132,7 @@
       </ows20:Parameter>
       <ows20:Parameter name="typeNames">
         <ows20:AllowedValues>
+          <ows20:Value>csw30:Record</ows20:Value>
           <ows20:Value>csw:Record</ows20:Value>
         </ows20:AllowedValues>
       </ows20:Parameter>
diff --git a/tests/expected/suites_csw30_get_22f44168-2ccf-4801-ad96-204212566d56.xml b/tests/functionaltests/suites/csw30/expected/get_GetCapabilities.xml
similarity index 99%
copy from tests/expected/suites_csw30_get_22f44168-2ccf-4801-ad96-204212566d56.xml
copy to tests/functionaltests/suites/csw30/expected/get_GetCapabilities.xml
index c5cb70e..a68d7f2 100644
--- a/tests/expected/suites_csw30_get_22f44168-2ccf-4801-ad96-204212566d56.xml
+++ b/tests/functionaltests/suites/csw30/expected/get_GetCapabilities.xml
@@ -132,6 +132,7 @@
       </ows20:Parameter>
       <ows20:Parameter name="typeNames">
         <ows20:AllowedValues>
+          <ows20:Value>csw30:Record</ows20:Value>
           <ows20:Value>csw:Record</ows20:Value>
         </ows20:AllowedValues>
       </ows20:Parameter>
diff --git a/tests/expected/suites_csw30_get_GetDomain-parameter.xml b/tests/functionaltests/suites/csw30/expected/get_GetDomain-parameter.xml
similarity index 100%
rename from tests/expected/suites_csw30_get_GetDomain-parameter.xml
rename to tests/functionaltests/suites/csw30/expected/get_GetDomain-parameter.xml
diff --git a/tests/expected/suites_csw30_get_GetDomain-value-reference.xml b/tests/functionaltests/suites/csw30/expected/get_GetDomain-value-reference.xml
similarity index 100%
rename from tests/expected/suites_csw30_get_GetDomain-value-reference.xml
rename to tests/functionaltests/suites/csw30/expected/get_GetDomain-value-reference.xml
diff --git a/tests/expected/suites_csw30_get_GetRepositoryItem.xml b/tests/functionaltests/suites/csw30/expected/get_GetRepositoryItem.xml
similarity index 100%
rename from tests/expected/suites_csw30_get_GetRepositoryItem.xml
rename to tests/functionaltests/suites/csw30/expected/get_GetRepositoryItem.xml
diff --git a/tests/expected/suites_csw30_get_OpenSearch-description.xml b/tests/functionaltests/suites/csw30/expected/get_OpenSearch-description.xml
similarity index 100%
rename from tests/expected/suites_csw30_get_OpenSearch-description.xml
rename to tests/functionaltests/suites/csw30/expected/get_OpenSearch-description.xml
diff --git a/tests/expected/suites_csw30_get_a2f18643-e24e-4fa5-b780-6de4a2dbc814.xml b/tests/functionaltests/suites/csw30/expected/get_a2f18643-e24e-4fa5-b780-6de4a2dbc814.xml
similarity index 100%
rename from tests/expected/suites_csw30_get_a2f18643-e24e-4fa5-b780-6de4a2dbc814.xml
rename to tests/functionaltests/suites/csw30/expected/get_a2f18643-e24e-4fa5-b780-6de4a2dbc814.xml
diff --git a/tests/expected/suites_csw30_get_abc90c8c-5868-4405-a73e-64c849be3b2a.xml b/tests/functionaltests/suites/csw30/expected/get_abc90c8c-5868-4405-a73e-64c849be3b2a.xml
similarity index 100%
rename from tests/expected/suites_csw30_get_abc90c8c-5868-4405-a73e-64c849be3b2a.xml
rename to tests/functionaltests/suites/csw30/expected/get_abc90c8c-5868-4405-a73e-64c849be3b2a.xml
diff --git a/tests/expected/suites_csw30_get_ad0c0571-09ed-436a-9a4f-a5de744c88fe.xml b/tests/functionaltests/suites/csw30/expected/get_ad0c0571-09ed-436a-9a4f-a5de744c88fe.xml
similarity index 100%
rename from tests/expected/suites_csw30_get_ad0c0571-09ed-436a-9a4f-a5de744c88fe.xml
rename to tests/functionaltests/suites/csw30/expected/get_ad0c0571-09ed-436a-9a4f-a5de744c88fe.xml
diff --git a/tests/expected/suites_csw30_get_af502903-f4ee-47ee-b76e-af878d238bcc.xml b/tests/functionaltests/suites/csw30/expected/get_af502903-f4ee-47ee-b76e-af878d238bcc.xml
similarity index 100%
rename from tests/expected/suites_csw30_get_af502903-f4ee-47ee-b76e-af878d238bcc.xml
rename to tests/functionaltests/suites/csw30/expected/get_af502903-f4ee-47ee-b76e-af878d238bcc.xml
diff --git a/tests/expected/suites_csw30_get_b2aafc3f-4f35-47bc-affd-08590972deae.xml b/tests/functionaltests/suites/csw30/expected/get_b2aafc3f-4f35-47bc-affd-08590972deae.xml
similarity index 100%
rename from tests/expected/suites_csw30_get_b2aafc3f-4f35-47bc-affd-08590972deae.xml
rename to tests/functionaltests/suites/csw30/expected/get_b2aafc3f-4f35-47bc-affd-08590972deae.xml
diff --git a/tests/expected/suites_csw30_get_b6069623-f7d8-4021-8582-98f0aea0f763.xml b/tests/functionaltests/suites/csw30/expected/get_b6069623-f7d8-4021-8582-98f0aea0f763.xml
similarity index 100%
rename from tests/expected/suites_csw30_get_b6069623-f7d8-4021-8582-98f0aea0f763.xml
rename to tests/functionaltests/suites/csw30/expected/get_b6069623-f7d8-4021-8582-98f0aea0f763.xml
diff --git a/tests/expected/suites_csw30_get_b9a07a54-75a8-45bd-b341-2823600211e3.xml b/tests/functionaltests/suites/csw30/expected/get_b9a07a54-75a8-45bd-b341-2823600211e3.xml
similarity index 87%
rename from tests/expected/suites_csw30_get_b9a07a54-75a8-45bd-b341-2823600211e3.xml
rename to tests/functionaltests/suites/csw30/expected/get_b9a07a54-75a8-45bd-b341-2823600211e3.xml
index 93cf54a..03a381a 100644
--- a/tests/expected/suites_csw30_get_b9a07a54-75a8-45bd-b341-2823600211e3.xml
+++ b/tests/functionaltests/suites/csw30/expected/get_b9a07a54-75a8-45bd-b341-2823600211e3.xml
@@ -3,6 +3,6 @@
 <ows20:ExceptionReport xmlns:csw="http://www.opengis.net/cat/csw/2.0.2" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dct="http://purl.org/dc/terms/" xmlns:gmd="http://www.isotc211.org/2005/gmd" xmlns:gml="http://www.opengis.net/gml" xmlns:ows="http://www.opengis.net/ows" xmlns:ows20="http://www.opengis.net/ows/2.0" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.0.0" xml:lang="en-US" xsi:schemaLocation="http://www.opengis. [...]
   <ows20:Exception exceptionCode="InvalidParameterValue" locator="bbox">
     <ows20:ExceptionText>Invalid Filter query: Exception: document not valid.
-Error: Reprojection error: Invalid srsName "urn:ogc:def:crs:EPSG::0000": Invalid source projection.</ows20:ExceptionText>
+Error: Reprojection error: Invalid srsName</ows20:ExceptionText>
   </ows20:Exception>
 </ows20:ExceptionReport>
diff --git a/tests/expected/suites_csw30_get_baa4a7d0-0c01-42b6-adc3-0d03e9949fa3.xml b/tests/functionaltests/suites/csw30/expected/get_baa4a7d0-0c01-42b6-adc3-0d03e9949fa3.xml
similarity index 100%
rename from tests/expected/suites_csw30_get_baa4a7d0-0c01-42b6-adc3-0d03e9949fa3.xml
rename to tests/functionaltests/suites/csw30/expected/get_baa4a7d0-0c01-42b6-adc3-0d03e9949fa3.xml
diff --git a/tests/expected/suites_csw30_get_bfbe6409-f64a-4c89-acb3-50f260a5c743.xml b/tests/functionaltests/suites/csw30/expected/get_bfbe6409-f64a-4c89-acb3-50f260a5c743.xml
similarity index 100%
rename from tests/expected/suites_csw30_get_bfbe6409-f64a-4c89-acb3-50f260a5c743.xml
rename to tests/functionaltests/suites/csw30/expected/get_bfbe6409-f64a-4c89-acb3-50f260a5c743.xml
diff --git a/tests/expected/suites_csw30_get_bfe20134-d1da-42ef-9c0f-8e1307bbf92b.xml b/tests/functionaltests/suites/csw30/expected/get_bfe20134-d1da-42ef-9c0f-8e1307bbf92b.xml
similarity index 100%
rename from tests/expected/suites_csw30_get_bfe20134-d1da-42ef-9c0f-8e1307bbf92b.xml
rename to tests/functionaltests/suites/csw30/expected/get_bfe20134-d1da-42ef-9c0f-8e1307bbf92b.xml
diff --git a/tests/expected/suites_csw30_get_22f44168-2ccf-4801-ad96-204212566d56.xml b/tests/functionaltests/suites/csw30/expected/get_c03d173a-3f42-4956-89c8-1fe02c3a0873.xml
similarity index 99%
copy from tests/expected/suites_csw30_get_22f44168-2ccf-4801-ad96-204212566d56.xml
copy to tests/functionaltests/suites/csw30/expected/get_c03d173a-3f42-4956-89c8-1fe02c3a0873.xml
index c5cb70e..a68d7f2 100644
--- a/tests/expected/suites_csw30_get_22f44168-2ccf-4801-ad96-204212566d56.xml
+++ b/tests/functionaltests/suites/csw30/expected/get_c03d173a-3f42-4956-89c8-1fe02c3a0873.xml
@@ -132,6 +132,7 @@
       </ows20:Parameter>
       <ows20:Parameter name="typeNames">
         <ows20:AllowedValues>
+          <ows20:Value>csw30:Record</ows20:Value>
           <ows20:Value>csw:Record</ows20:Value>
         </ows20:AllowedValues>
       </ows20:Parameter>
diff --git a/tests/expected/suites_csw30_get_cb43d8c3-e14c-4a9f-9231-4384b7dd21f3.xml b/tests/functionaltests/suites/csw30/expected/get_cb43d8c3-e14c-4a9f-9231-4384b7dd21f3.xml
similarity index 100%
rename from tests/expected/suites_csw30_get_cb43d8c3-e14c-4a9f-9231-4384b7dd21f3.xml
rename to tests/functionaltests/suites/csw30/expected/get_cb43d8c3-e14c-4a9f-9231-4384b7dd21f3.xml
diff --git a/tests/expected/suites_csw30_get_d03c6fd3-e821-4a26-b62f-d20a474e25af.xml b/tests/functionaltests/suites/csw30/expected/get_d03c6fd3-e821-4a26-b62f-d20a474e25af.xml
similarity index 100%
rename from tests/expected/suites_csw30_get_d03c6fd3-e821-4a26-b62f-d20a474e25af.xml
rename to tests/functionaltests/suites/csw30/expected/get_d03c6fd3-e821-4a26-b62f-d20a474e25af.xml
diff --git a/tests/expected/suites_csw30_get_d4ccbf96-a529-480e-a53d-5b88dc1dea7f.xml b/tests/functionaltests/suites/csw30/expected/get_d4ccbf96-a529-480e-a53d-5b88dc1dea7f.xml
similarity index 100%
rename from tests/expected/suites_csw30_get_d4ccbf96-a529-480e-a53d-5b88dc1dea7f.xml
rename to tests/functionaltests/suites/csw30/expected/get_d4ccbf96-a529-480e-a53d-5b88dc1dea7f.xml
diff --git a/tests/expected/suites_csw30_get_d94c801a-1207-4897-b84a-53f3a192515b.xml b/tests/functionaltests/suites/csw30/expected/get_d94c801a-1207-4897-b84a-53f3a192515b.xml
similarity index 100%
rename from tests/expected/suites_csw30_get_d94c801a-1207-4897-b84a-53f3a192515b.xml
rename to tests/functionaltests/suites/csw30/expected/get_d94c801a-1207-4897-b84a-53f3a192515b.xml
diff --git a/tests/expected/suites_csw30_get_da859e34-91fc-495a-8c09-285a40c0900b.xml b/tests/functionaltests/suites/csw30/expected/get_da859e34-91fc-495a-8c09-285a40c0900b.xml
similarity index 100%
rename from tests/expected/suites_csw30_get_da859e34-91fc-495a-8c09-285a40c0900b.xml
rename to tests/functionaltests/suites/csw30/expected/get_da859e34-91fc-495a-8c09-285a40c0900b.xml
diff --git a/tests/expected/suites_csw30_get_dc246fb8-5af5-4fda-82bb-c18b3ecd439c.xml b/tests/functionaltests/suites/csw30/expected/get_dc246fb8-5af5-4fda-82bb-c18b3ecd439c.xml
similarity index 100%
rename from tests/expected/suites_csw30_get_dc246fb8-5af5-4fda-82bb-c18b3ecd439c.xml
rename to tests/functionaltests/suites/csw30/expected/get_dc246fb8-5af5-4fda-82bb-c18b3ecd439c.xml
diff --git a/tests/expected/suites_csw30_get_de016645-6d5c-4855-943c-2db07ae9f49a.xml b/tests/functionaltests/suites/csw30/expected/get_de016645-6d5c-4855-943c-2db07ae9f49a.xml
similarity index 100%
rename from tests/expected/suites_csw30_get_de016645-6d5c-4855-943c-2db07ae9f49a.xml
rename to tests/functionaltests/suites/csw30/expected/get_de016645-6d5c-4855-943c-2db07ae9f49a.xml
diff --git a/tests/expected/suites_csw30_get_dff3ec6b-bb2d-4887-bd17-8fcf15def042.xml b/tests/functionaltests/suites/csw30/expected/get_dff3ec6b-bb2d-4887-bd17-8fcf15def042.xml
similarity index 100%
rename from tests/expected/suites_csw30_get_dff3ec6b-bb2d-4887-bd17-8fcf15def042.xml
rename to tests/functionaltests/suites/csw30/expected/get_dff3ec6b-bb2d-4887-bd17-8fcf15def042.xml
diff --git a/tests/expected/suites_csw30_get_e38e6bfb-8ac4-4ae4-8b87-0aafbc8d3c6b.xml b/tests/functionaltests/suites/csw30/expected/get_e38e6bfb-8ac4-4ae4-8b87-0aafbc8d3c6b.xml
similarity index 100%
rename from tests/expected/suites_csw30_get_e38e6bfb-8ac4-4ae4-8b87-0aafbc8d3c6b.xml
rename to tests/functionaltests/suites/csw30/expected/get_e38e6bfb-8ac4-4ae4-8b87-0aafbc8d3c6b.xml
diff --git a/tests/expected/suites_csw30_get_22f44168-2ccf-4801-ad96-204212566d56.xml b/tests/functionaltests/suites/csw30/expected/get_e67ca935-d65d-4d8c-8302-1405333dded0.xml
similarity index 99%
copy from tests/expected/suites_csw30_get_22f44168-2ccf-4801-ad96-204212566d56.xml
copy to tests/functionaltests/suites/csw30/expected/get_e67ca935-d65d-4d8c-8302-1405333dded0.xml
index c5cb70e..a68d7f2 100644
--- a/tests/expected/suites_csw30_get_22f44168-2ccf-4801-ad96-204212566d56.xml
+++ b/tests/functionaltests/suites/csw30/expected/get_e67ca935-d65d-4d8c-8302-1405333dded0.xml
@@ -132,6 +132,7 @@
       </ows20:Parameter>
       <ows20:Parameter name="typeNames">
         <ows20:AllowedValues>
+          <ows20:Value>csw30:Record</ows20:Value>
           <ows20:Value>csw:Record</ows20:Value>
         </ows20:AllowedValues>
       </ows20:Parameter>
diff --git a/tests/expected/suites_csw30_get_e7704509-3441-458f-8ef0-e333c6b6043f.xml b/tests/functionaltests/suites/csw30/expected/get_e7704509-3441-458f-8ef0-e333c6b6043f.xml
similarity index 100%
rename from tests/expected/suites_csw30_get_e7704509-3441-458f-8ef0-e333c6b6043f.xml
rename to tests/functionaltests/suites/csw30/expected/get_e7704509-3441-458f-8ef0-e333c6b6043f.xml
diff --git a/tests/expected/suites_csw30_get_f1223a49-6d08-44ff-97fe-4c32cbbfad82.xml b/tests/functionaltests/suites/csw30/expected/get_f1223a49-6d08-44ff-97fe-4c32cbbfad82.xml
similarity index 100%
rename from tests/expected/suites_csw30_get_f1223a49-6d08-44ff-97fe-4c32cbbfad82.xml
rename to tests/functionaltests/suites/csw30/expected/get_f1223a49-6d08-44ff-97fe-4c32cbbfad82.xml
diff --git a/tests/expected/suites_csw30_get_f89dd4e1-3a81-4433-afd2-a3fa1bdb1e18.xml b/tests/functionaltests/suites/csw30/expected/get_f89dd4e1-3a81-4433-afd2-a3fa1bdb1e18.xml
similarity index 100%
rename from tests/expected/suites_csw30_get_f89dd4e1-3a81-4433-afd2-a3fa1bdb1e18.xml
rename to tests/functionaltests/suites/csw30/expected/get_f89dd4e1-3a81-4433-afd2-a3fa1bdb1e18.xml
diff --git a/tests/expected/suites_csw30_post_Exception-GetDomain-parametername-bad.xml b/tests/functionaltests/suites/csw30/expected/post_Exception-GetDomain-parametername-bad.xml
similarity index 100%
rename from tests/expected/suites_csw30_post_Exception-GetDomain-parametername-bad.xml
rename to tests/functionaltests/suites/csw30/expected/post_Exception-GetDomain-parametername-bad.xml
diff --git a/tests/expected/suites_csw30_post_Exception-GetDomain-valuereference-bad.xml b/tests/functionaltests/suites/csw30/expected/post_Exception-GetDomain-valuereference-bad.xml
similarity index 100%
rename from tests/expected/suites_csw30_post_Exception-GetDomain-valuereference-bad.xml
rename to tests/functionaltests/suites/csw30/expected/post_Exception-GetDomain-valuereference-bad.xml
diff --git a/tests/expected/suites_csw30_post_Exception-GetRecordById-404.xml b/tests/functionaltests/suites/csw30/expected/post_Exception-GetRecordById-404.xml
similarity index 100%
rename from tests/expected/suites_csw30_post_Exception-GetRecordById-404.xml
rename to tests/functionaltests/suites/csw30/expected/post_Exception-GetRecordById-404.xml
diff --git a/tests/expected/suites_csw30_post_Exception-GetRecordById-bad-esn.xml b/tests/functionaltests/suites/csw30/expected/post_Exception-GetRecordById-bad-esn.xml
similarity index 100%
rename from tests/expected/suites_csw30_post_Exception-GetRecordById-bad-esn.xml
rename to tests/functionaltests/suites/csw30/expected/post_Exception-GetRecordById-bad-esn.xml
diff --git a/tests/expected/suites_csw30_post_Exception-bad-xml.xml b/tests/functionaltests/suites/csw30/expected/post_Exception-bad-xml.xml
similarity index 100%
rename from tests/expected/suites_csw30_post_Exception-bad-xml.xml
rename to tests/functionaltests/suites/csw30/expected/post_Exception-bad-xml.xml
diff --git a/tests/expected/suites_csw30_post_Exception-not-xml.xml b/tests/functionaltests/suites/csw30/expected/post_Exception-not-xml.xml
similarity index 100%
rename from tests/expected/suites_csw30_post_Exception-not-xml.xml
rename to tests/functionaltests/suites/csw30/expected/post_Exception-not-xml.xml
diff --git a/tests/expected/suites_csw30_get_22f44168-2ccf-4801-ad96-204212566d56.xml b/tests/functionaltests/suites/csw30/expected/post_GetCapabilities.xml
similarity index 99%
rename from tests/expected/suites_csw30_get_22f44168-2ccf-4801-ad96-204212566d56.xml
rename to tests/functionaltests/suites/csw30/expected/post_GetCapabilities.xml
index c5cb70e..a68d7f2 100644
--- a/tests/expected/suites_csw30_get_22f44168-2ccf-4801-ad96-204212566d56.xml
+++ b/tests/functionaltests/suites/csw30/expected/post_GetCapabilities.xml
@@ -132,6 +132,7 @@
       </ows20:Parameter>
       <ows20:Parameter name="typeNames">
         <ows20:AllowedValues>
+          <ows20:Value>csw30:Record</ows20:Value>
           <ows20:Value>csw:Record</ows20:Value>
         </ows20:AllowedValues>
       </ows20:Parameter>
diff --git a/tests/expected/suites_csw30_post_GetDomain-parametername.xml b/tests/functionaltests/suites/csw30/expected/post_GetDomain-parametername.xml
similarity index 100%
rename from tests/expected/suites_csw30_post_GetDomain-parametername.xml
rename to tests/functionaltests/suites/csw30/expected/post_GetDomain-parametername.xml
diff --git a/tests/expected/suites_csw30_post_GetDomain-valuereference.xml b/tests/functionaltests/suites/csw30/expected/post_GetDomain-valuereference.xml
similarity index 100%
rename from tests/expected/suites_csw30_post_GetDomain-valuereference.xml
rename to tests/functionaltests/suites/csw30/expected/post_GetDomain-valuereference.xml
diff --git a/tests/expected/suites_csw30_post_GetRecordById-dc-full.xml b/tests/functionaltests/suites/csw30/expected/post_GetRecordById-dc-full.xml
similarity index 100%
rename from tests/expected/suites_csw30_post_GetRecordById-dc-full.xml
rename to tests/functionaltests/suites/csw30/expected/post_GetRecordById-dc-full.xml
diff --git a/tests/expected/suites_csw30_post_GetRecordById-dc.xml b/tests/functionaltests/suites/csw30/expected/post_GetRecordById-dc.xml
similarity index 100%
rename from tests/expected/suites_csw30_post_GetRecordById-dc.xml
rename to tests/functionaltests/suites/csw30/expected/post_GetRecordById-dc.xml
diff --git a/tests/functionaltests/suites/csw30/get/requests.txt b/tests/functionaltests/suites/csw30/get/requests.txt
new file mode 100644
index 0000000..a45be31
--- /dev/null
+++ b/tests/functionaltests/suites/csw30/get/requests.txt
@@ -0,0 +1,82 @@
+GetCapabilities-base-url,PYCSW_SERVER?config=tests/suites/csw30/default.cfg
+GetCapabilities-no-version,service=CSW&request=GetCapabilities
+GetCapabilities,service=CSW&version=3.0.0&request=GetCapabilities
+Exception-invalid-request,service=CSW&version=3.0.0&request=GetCapabilities-foo
+Exception-GetDomain,service=CSW&version=3.0.0&request=GetDomain
+GetDomain-parameter,service=CSW&version=3.0.0&request=GetDomain&parametername=GetRecords.ElementSetName
+GetDomain-value-reference,service=CSW&version=3.0.0&request=GetDomain&valuereference=dc:title
+Exception-GetDomain-value-reference,service=CSW&version=3.0.0&request=GetDomain&valuereference=dc:title2
+Exception-GetRecordById-dc.xml,service=CSW&version=3.0.0&request=GetRecordById&id=urn:uuid:829babb0-b2f1-49e1-8cd5-7b489fe71a1e
+Exception-GetRecordById-404,service=CSW&version=3.0.0&request=GetRecordById&id=does_not_exist2
+OpenSearch-description,mode=opensearch&service=CSW&version=3.0.0&request=GetCapabilities
+GetRepositoryItem,service=CSW&version=3.0.0&request=GetRepositoryItem&id=urn:uuid:19887a8a-f6b0-4a63-ae56-7fba0e17801f
+Exception-GetRepositoryItem-notfound,service=CSW&version=3.0.0&request=GetRepositoryItem&id=NOTFOUND
+002258f0-627f-457f-b2ad-025777c77ac8,mode=opensearch&service=CSW&version=3.0.0&request=GetCapabilities
+045c600d-973d-41eb-9f60-eba1b717b720,mode=opensearch&service=CSW&version=3.0.0&request=GetRecords&elementsetname=full&typenames=csw:Record&resulttype=results&q=Fusc%C3%A9%20Land&bbox=&time=/&outputformat=application/atom%2Bxml&startposition=1&maxrecords=&recordids=
+0bbcf862-5211-4351-9988-63f8bec49c98,elementSetName=summary&outputFormat=application/atom%2Bxml&request=GetRecords&service=CSW&typeNames=Record&version=3.0.0
+0bdf8457-971e-4ed1-be4a-5feca4dcd8fa,PYCSW_SERVER?config=tests/suites/csw30/default.cfg
+0d8bbdec-0846-42ca-8dc8-b7f4cba41d67,elementName=tns:title&request=GetRecords&service=CSW&typeNames=Record&namespace=xmlns(tns%3Dhttp://purl.org/dc/elements/1.1/)&version=3.0.0
+0e1dca37-477a-4060-99fe-7799b52d656c,mode=opensearch&service=CSW&version=3.0.0&request=GetRecords&elementsetname=full&typenames=csw:Record&resulttype=results&q=lpppclq&bbox=&time=/&outputformat=application/atom%2Bxml&startposition=1&maxrecords=&recordids=
+13c87956-51a4-4780-a8e9-6e0b5c0bb473,elementSetName=full&maxRecords=20&request=GetRecords&service=CSW&typeNames=Record&version=3.0.0
+151d982f-ebd3-4cb2-b507-a667713a1e92,acceptFormats=model/x3d%2Bxml&acceptVersions=3.0.0&request=GetCapabilities&service=CSW
+1869e495-1a61-4713-8285-76d1336ee1a6,acceptVersions=3.0.0&request=GetCapabilities
+1bcb42a9-538c-4f0a-9d4c-d6f10b720aa6,request=GetRecordById&service=CSW&version=3.0.0
+22f44168-2ccf-4801-ad96-204212566d56,PYCSW_SERVER?config=tests/suites/csw30/default.cfg
+2499a9c9-8d33-449c-bc92-d494adfcc84d,acceptVersions=3.0.0&sections=All&request=GetCapabilities&service=CSW
+27f4f39c-d92a-4e3c-b961-c6aa8c24e513,acceptFormats=application/xml&acceptVersions=3.0.0&request=GetCapabilities&service=CSW
+28e569df-8596-4128-8d9a-29ad03138915,id=urn:uuid:a06af396-3105-442d-8b40-22b57a90d2f2&request=GetRecordById&service=CSW&version=3.0.0
+2b06a5c8-0df2-4af1-8d2e-a425de11c845,PYCSW_SERVER?config=tests/suites/csw30/default.cfg
+2ba1418a-444d-4cce-9cfe-4c94efcf8b55,maxRecords=2&elementSetName=summary&outputFormat=application/atom%2Bxml&request=GetRecords&service=CSW&typeNames=csw3:Record&startPosition=3&namespace=xmlns(csw3%3Dhttp://www.opengis.net/cat/csw/3.0)&version=3.0.0
+397fe17a-d5b4-4f96-8cc4-4ce467ed4d0a,service=CSW&version=3.0.0&request=GetRecords&elementsetname=full&typenames=csw:Record&resulttype=results&q=ipsum&bbox=&time=/&outputformat=application/xml&outputschema=http://www.opengis.net/cat/csw/3.0&startposition=1&maxrecords=&recordids=
+3dcd1b15-73d2-4b7d-a3e3-ff15bf14aae4,elementSetName=brief&request=GetRecords&service=CSW&typeNames=tns:Record&namespace=xmlns(tns%3Dhttp://www.opengis.net/cat/csw/3.0)&version=3.0.0
+405e1ff1-5c75-4846-a28b-cfaff2a6921a,elementSetName=summary&recordIds=urn:uuid:19887a8a-f6b0-4a63-ae56-7fba0e17801f,urn:uuid:e9330592-0932-474b-be34-c3a3bb67c7db&request=GetRecords&service=CSW&typeNames=Record&version=3.0.0
+43cd6471-6ac7-45bd-8ff9-148cb2de9a52,PYCSW_SERVER?config=tests/suites/csw30/default.cfg
+4566d2ec-1283-4a02-baed-a74fc5b47e37,acceptVersions=3.0.0&sections=ServiceIdentification&request=GetCapabilities&service=CSW
+461bd4c5-6623-490d-9036-d91a2201e87b,acceptVersions=3.0.0&sections=Filter_Capabilities&request=GetCapabilities&service=CSW
+5496894a-3877-4f62-a20b-5d7126f94925,service=CSW&version=3.0.0&request=GetRecords&elementsetname=full&typenames=csw:Record&resulttype=results&q=&bbox=514432,5429689,529130,5451619&time=/&outputformat=application/xml&outputschema=http://www.opengis.net/cat/csw/3.0&startposition=1&maxrecords=&recordids=
+5a015f6a-bf14-4977-b1e3-6577eb0223c8,service=CSW&version=3.0.0&request=GetRecords&elementsetname=full&typenames=csw:Record&resulttype=results&q=&bbox=-6.17,44.79,17.92,68.41&time=/&outputformat=application/xml&outputschema=http://www.opengis.net/cat/csw/3.0&startposition=1&maxrecords=&recordids=
+5c3a2390-1fb9-43f0-b96c-f48c7a69c990,id=urn:uuid:88247b56-4cbc-4df9-9860-db3f8042e357&outputFormat=model/vnd.collada%2Bxml&request=GetRecordById&service=CSW&version=3.0.0
+5e9e67dc-18d6-4645-8111-c6263c88a61f,acceptVersions=3.0.0&sections=OperationsMetadata&request=GetCapabilities&service=CSW
+604d9379-741c-42e5-b4cf-92e56c87fa64,elementSetName=full&q=amet&request=GetRecords&service=CSW&typeNames=Record&version=3.0.0
+60e6af95-d5fc-465a-82e2-fd2e6d85e4af,request=GetRecords&service=CSW&typeNames=UnknownType&version=3.0.0
+62ad94c2-b558-4265-a427-23d6677975d6,mode=opensearch&service=CSW&version=3.0.0&request=GetRecords&elementsetname=full&typenames=csw:Record&resulttype=results&q=&bbox=&time=/&outputformat=application/atom%2Bxml&startposition=1&maxrecords=&recordids=uid-bc5017e6-5cc8-4b03-aee7-d88f88caba0a
+6a5e247b-0961-4b8a-a0d6-35a491d9cfe7,elementSetName=undefined-view&request=GetRecords&service=CSW&typeNames=Record&version=3.0.0
+6a9d0558-9d87-495b-b999-b49a3ef1cf99,PYCSW_SERVER?config=tests/suites/csw30/default.cfg
+6bd790c9-6019-4652-9c91-330a894d6700,service=CSW&version=3.0.0&request=GetRecords&elementsetname=full&typenames=csw:Record&resulttype=results&q=Fusc%C3%A9%20Land&bbox=&time=/&outputformat=application/xml&outputschema=http://www.opengis.net/cat/csw/3.0&startposition=1&maxrecords=&recordids=
+6e9cba43-5e27-415d-adbd-a92851c2c173,acceptVersions=3.0.0&request=GetCapabilities&service=CSW
+7630d230-e142-4a09-accf-f091000b90cd,id=urn:uuid:66ae76b7-54ba-489b-a582-0f0633d96493&request=GetRecordById&service=CSW&version=3.0.0
+7e82446a-b5dc-43fe-9a73-4cc1f2f2f0bf,acceptFormats=text/xml&acceptVersions=3.0.0&request=GetCapabilities&service=CSW
+8025978e-1a35-4d70-80c2-e8329e0c7864,PYCSW_SERVER?config=tests/suites/csw30/default.cfg
+8184ae4f-536d-4978-8b28-ad703be96967,elementSetName=brief&bbox=44.79,-6.17,68.41,17.92,urn:ogc:def:crs:EPSG::4326&request=GetRecords&service=CSW&typeNames=Record&version=3.0.0
+88f63a89-664f-4315-b4f8-04a0b33803a7,maxRecords=15&elementSetName=summary&q=Mauris&bbox=-6.17,44.79,17.92,68.41&request=GetRecords&service=CSW&typeNames=Record&version=3.0.0
+8987f8f0-4d93-4481-968c-a2ccbd6b8be2,id=urn:example:1461546298217&request=GetRecordById&service=CSW&version=3.0.0
+8e5fa0f6-3f29-4d1f-abe2-d9866f3def98,mode=opensearch&service=CSW&version=3.0.0&request=GetRecords&elementsetname=full&typenames=csw:Record&resulttype=results&q=&bbox=-180,-90,180,90&time=/&outputformat=application/atom%2Bxml&startposition=1&maxrecords=&recordids=
+9000ec29-5649-474e-b2d6-55c00f8a52c0,acceptVersions=9999.12.31&request=GetCapabilities&service=CSW
+91914d35-7bbf-45e6-9b37-5ef484869a4e,elementSetName=summary&bbox=-6.17,44.79,17.92,68.41&request=GetRecords&service=CSW&typeNames=Record&version=3.0.0
+92d4844d-57d5-4cf3-8f47-ba50e369dc04,elementSetName=full&q=atkovxqmf&request=GetRecords&service=CSW&typeNames=Record&version=3.0.0
+9c0e2a4b-b4e6-41c0-b630-c8c99fc89ff3,elementSetName=brief&outputSchema=urn:uuid:6a29d2a8-9651-47a6-9b14-f05d2b5644f0&request=GetRecords&service=CSW&typeNames=Record&version=3.0.0
+9d7ffac8-9798-428d-8e27-3cd12497ee6b,id=urn:uuid:1ef30a8b-876d-4828-9246-c37ab4510bbd&outputSchema=http://www.example.org/ns/alpha&request=GetRecordById&service=CSW&version=3.0.0
+a2f18643-e24e-4fa5-b780-6de4a2dbc814,id=urn:uuid:829babb0-b2f1-49e1-8cd5-7b489fe71a1e&outputFormat=application/atom%2Bxml&request=GetRecordById&service=CSW&version=3.0.0
+abc90c8c-5868-4405-a73e-64c849be3b2a,mode=opensearch&service=CSW&version=3.0.0&request=GetRecords&elementsetname=full&typenames=csw:Record&resulttype=results&q=&bbox=514432,5429689,529130,5451619&time=/&outputformat=application/atom%2Bxml&startposition=1&maxrecords=&recordids=
+ad0c0571-09ed-436a-9a4f-a5de744c88fe,maxRecords=2&elementSetName=summary&request=GetRecords&service=CSW&typeNames=csw3:Record&startPosition=3&namespace=xmlns(csw3%3Dhttp://www.opengis.net/cat/csw/3.0)&version=3.0.0
+af502903-f4ee-47ee-b76e-af878d238bcc,service=CSW&version=3.0.0&request=GetRecords&elementsetname=full&typenames=csw:Record&resulttype=results&q=&bbox=-180,-90,180,90&time=/&outputformat=application/xml&outputschema=http://www.opengis.net/cat/csw/3.0&startposition=1&maxrecords=&recordids=
+b2aafc3f-4f35-47bc-affd-08590972deae,mode=opensearch&service=CSW&version=3.0.0&request=GetRecords&elementsetname=full&typenames=csw:Record&resulttype=results&q=&bbox=-6.17,44.79,17.92,68.41&time=/&outputformat=application/atom%2Bxml&startposition=1&maxrecords=&recordids=
+b6069623-f7d8-4021-8582-98f0aea0f763,mode=opensearch&service=CSW&version=3.0.0&request=GetRecords&elementsetname=full&typenames=csw:Record&resulttype=results&q=&bbox=&time=/&outputformat=application/atom%2Bxml&startposition=3&maxrecords=4&recordids=
+b9a07a54-75a8-45bd-b341-2823600211e3,elementSetName=brief&bbox=472944,5363287,492722,5455253,urn:ogc:def:crs:EPSG::0000&request=GetRecords&service=CSW&typeNames=Record&version=3.0.0
+baa4a7d0-0c01-42b6-adc3-0d03e9949fa3,acceptVersions=3.0.0&request=getCapabilities&service=CSW
+bfbe6409-f64a-4c89-acb3-50f260a5c743,elementSetName=summary&q=Fusc%C3%A9%20Land&request=GetRecords&service=CSW&typeNames=Record&version=3.0.0
+bfe20134-d1da-42ef-9c0f-8e1307bbf92b,service=CSW&version=3.0.0&request=GetRecords&elementsetname=full&typenames=csw:Record&resulttype=results&q=&bbox=&time=/&outputformat=application/xml&outputschema=http://www.opengis.net/cat/csw/3.0&startposition=3&maxrecords=4&recordids=
+c03d173a-3f42-4956-89c8-1fe02c3a0873,SERVICE=CSW&Request=GetCapabilities&acceptversions=3.0.0
+cb43d8c3-e14c-4a9f-9231-4384b7dd21f3,elementName=undefined&request=GetRecords&service=CSW&typeNames=Record&version=3.0.0
+d03c6fd3-e821-4a26-b62f-d20a474e25af,acceptVersions=3.0.0&sections=ServiceProvider&request=GetCapabilities&service=CSW
+d4ccbf96-a529-480e-a53d-5b88dc1dea7f,service=CSW&version=3.0.0&request=GetRecords&elementsetname=full&typenames=csw:Record&resulttype=results&q=&bbox=&time=/&outputformat=application/xml&outputschema=http://www.opengis.net/cat/csw/3.0&startposition=1&maxrecords=&recordids=uid-bc5017e6-5cc8-4b03-aee7-d88f88caba0a
+d94c801a-1207-4897-b84a-53f3a192515b,service=CSW&version=3.0.0&request=GetRecords&elementsetname=full&typenames=csw:Record&resulttype=results&q=lpppclq&bbox=&time=/&outputformat=application/xml&outputschema=http://www.opengis.net/cat/csw/3.0&startposition=1&maxrecords=&recordids=
+da859e34-91fc-495a-8c09-285a40c0900b,id=urn:uuid:94bc9c83-97f6-4b40-9eb8-a8e8787a5c63&elementSetName=full&request=GetRecordById&service=CSW&version=3.0.0
+dc246fb8-5af5-4fda-82bb-c18b3ecd439c,mode=opensearch&service=CSW&version=3.0.0&request=GetRecords&elementsetname=full&typenames=csw:Record&resulttype=results&q=ipsum&bbox=&time=/&outputformat=application/atom%2Bxml&startposition=1&maxrecords=&recordids=
+de016645-6d5c-4855-943c-2db07ae9f49a,mode=opensearch&service=CSW&version=3.0.0&request=GetRecords&elementsetname=full&typenames=csw:Record&resulttype=results&q=&bbox=&time=/&outputformat=application/atom%2Bxml&startposition=1&maxrecords=&recordids=urn%3Auuid%3A94bc9c83-97f6-4b40-9eb8-a8e8787a5c63
+dff3ec6b-bb2d-4887-bd17-8fcf15def042,elementSetName=summary&request=GetRecords&service=CSW&typeNames=Record&version=3.0.0
+e38e6bfb-8ac4-4ae4-8b87-0aafbc8d3c6b,id=urn:uuid:1ef30a8b-876d-4828-9246-c37ab4510bbd&elementSetName=brief&request=GetRecordById&service=CSW&version=3.0.0
+e67ca935-d65d-4d8c-8302-1405333dded0,PYCSW_SERVER?config=tests/suites/csw30/default.cfg
+e7704509-3441-458f-8ef0-e333c6b6043f,elementName=ns1:subject&elementSetName=brief&request=GetRecords&service=CSW&typeNames=Record&namespace=xmlns(ns1%3Dhttp://purl.org/dc/elements/1.1/)&version=3.0.0
+f1223a49-6d08-44ff-97fe-4c32cbbfad82,elementSetName=summary&maxRecords=0&q=titles&request=GetRecords&service=CSW&typeNames=Record&version=3.0.0
+f89dd4e1-3a81-4433-afd2-a3fa1bdb1e18,elementSetName=full&outputFormat=text/example&request=GetRecords&service=CSW&typeNames=Record&version=3.0.0
diff --git a/tests/suites/csw30/post/Exception-GetDomain-parametername-bad.xml b/tests/functionaltests/suites/csw30/post/Exception-GetDomain-parametername-bad.xml
similarity index 100%
rename from tests/suites/csw30/post/Exception-GetDomain-parametername-bad.xml
rename to tests/functionaltests/suites/csw30/post/Exception-GetDomain-parametername-bad.xml
diff --git a/tests/suites/csw30/post/Exception-GetDomain-valuereference-bad.xml b/tests/functionaltests/suites/csw30/post/Exception-GetDomain-valuereference-bad.xml
similarity index 100%
rename from tests/suites/csw30/post/Exception-GetDomain-valuereference-bad.xml
rename to tests/functionaltests/suites/csw30/post/Exception-GetDomain-valuereference-bad.xml
diff --git a/tests/suites/csw30/post/Exception-GetRecordById-404.xml b/tests/functionaltests/suites/csw30/post/Exception-GetRecordById-404.xml
similarity index 100%
rename from tests/suites/csw30/post/Exception-GetRecordById-404.xml
rename to tests/functionaltests/suites/csw30/post/Exception-GetRecordById-404.xml
diff --git a/tests/suites/csw30/post/Exception-GetRecordById-bad-esn.xml b/tests/functionaltests/suites/csw30/post/Exception-GetRecordById-bad-esn.xml
similarity index 100%
rename from tests/suites/csw30/post/Exception-GetRecordById-bad-esn.xml
rename to tests/functionaltests/suites/csw30/post/Exception-GetRecordById-bad-esn.xml
diff --git a/tests/suites/csw30/post/Exception-bad-xml.xml b/tests/functionaltests/suites/csw30/post/Exception-bad-xml.xml
similarity index 100%
rename from tests/suites/csw30/post/Exception-bad-xml.xml
rename to tests/functionaltests/suites/csw30/post/Exception-bad-xml.xml
diff --git a/tests/suites/csw30/post/Exception-not-xml.xml b/tests/functionaltests/suites/csw30/post/Exception-not-xml.xml
similarity index 100%
rename from tests/suites/csw30/post/Exception-not-xml.xml
rename to tests/functionaltests/suites/csw30/post/Exception-not-xml.xml
diff --git a/tests/suites/csw30/post/GetCapabilities.xml b/tests/functionaltests/suites/csw30/post/GetCapabilities.xml
similarity index 100%
rename from tests/suites/csw30/post/GetCapabilities.xml
rename to tests/functionaltests/suites/csw30/post/GetCapabilities.xml
diff --git a/tests/suites/csw30/post/GetDomain-parametername.xml b/tests/functionaltests/suites/csw30/post/GetDomain-parametername.xml
similarity index 100%
rename from tests/suites/csw30/post/GetDomain-parametername.xml
rename to tests/functionaltests/suites/csw30/post/GetDomain-parametername.xml
diff --git a/tests/suites/csw30/post/GetDomain-valuereference.xml b/tests/functionaltests/suites/csw30/post/GetDomain-valuereference.xml
similarity index 100%
rename from tests/suites/csw30/post/GetDomain-valuereference.xml
rename to tests/functionaltests/suites/csw30/post/GetDomain-valuereference.xml
diff --git a/tests/suites/csw30/post/GetRecordById-dc-full.xml b/tests/functionaltests/suites/csw30/post/GetRecordById-dc-full.xml
similarity index 100%
rename from tests/suites/csw30/post/GetRecordById-dc-full.xml
rename to tests/functionaltests/suites/csw30/post/GetRecordById-dc-full.xml
diff --git a/tests/suites/csw30/post/GetRecordById-dc.xml b/tests/functionaltests/suites/csw30/post/GetRecordById-dc.xml
similarity index 100%
rename from tests/suites/csw30/post/GetRecordById-dc.xml
rename to tests/functionaltests/suites/csw30/post/GetRecordById-dc.xml
diff --git a/tests/suites/default/default.cfg b/tests/functionaltests/suites/default/default.cfg
similarity index 100%
rename from tests/suites/default/default.cfg
rename to tests/functionaltests/suites/default/default.cfg
diff --git a/tests/expected/suites_default_get_Exception-GetRepositoryItem-notfound.xml b/tests/functionaltests/suites/default/expected/get_Exception-GetRepositoryItem-notfound.xml
similarity index 100%
rename from tests/expected/suites_default_get_Exception-GetRepositoryItem-notfound.xml
rename to tests/functionaltests/suites/default/expected/get_Exception-GetRepositoryItem-notfound.xml
diff --git a/tests/expected/suites_default_get_Exception-GetRepositoryItem-service-invalid1.xml b/tests/functionaltests/suites/default/expected/get_Exception-GetRepositoryItem-service-invalid1.xml
similarity index 100%
rename from tests/expected/suites_default_get_Exception-GetRepositoryItem-service-invalid1.xml
rename to tests/functionaltests/suites/default/expected/get_Exception-GetRepositoryItem-service-invalid1.xml
diff --git a/tests/expected/suites_default_get_Exception-GetRepositoryItem-service-invalid2.xml b/tests/functionaltests/suites/default/expected/get_Exception-GetRepositoryItem-service-invalid2.xml
similarity index 100%
rename from tests/expected/suites_default_get_Exception-GetRepositoryItem-service-invalid2.xml
rename to tests/functionaltests/suites/default/expected/get_Exception-GetRepositoryItem-service-invalid2.xml
diff --git a/tests/expected/suites_default_get_Exception-GetRepositoryItem-version-invalid.xml b/tests/functionaltests/suites/default/expected/get_Exception-GetRepositoryItem-version-invalid.xml
similarity index 100%
rename from tests/expected/suites_default_get_Exception-GetRepositoryItem-version-invalid.xml
rename to tests/functionaltests/suites/default/expected/get_Exception-GetRepositoryItem-version-invalid.xml
diff --git a/tests/expected/suites_default_get_GetCapabilities-invalid-request.xml b/tests/functionaltests/suites/default/expected/get_GetCapabilities-invalid-request.xml
similarity index 100%
rename from tests/expected/suites_default_get_GetCapabilities-invalid-request.xml
rename to tests/functionaltests/suites/default/expected/get_GetCapabilities-invalid-request.xml
diff --git a/tests/expected/suites_default_get_GetCapabilities.xml b/tests/functionaltests/suites/default/expected/get_GetCapabilities.xml
similarity index 100%
rename from tests/expected/suites_default_get_GetCapabilities.xml
rename to tests/functionaltests/suites/default/expected/get_GetCapabilities.xml
diff --git a/tests/expected/suites_default_get_GetRecords-all.xml b/tests/functionaltests/suites/default/expected/get_GetRecords-all.xml
similarity index 100%
rename from tests/expected/suites_default_get_GetRecords-all.xml
rename to tests/functionaltests/suites/default/expected/get_GetRecords-all.xml
diff --git a/tests/expected/suites_default_get_GetRecords-empty-maxrecords.xml b/tests/functionaltests/suites/default/expected/get_GetRecords-empty-maxrecords.xml
similarity index 100%
rename from tests/expected/suites_default_get_GetRecords-empty-maxrecords.xml
rename to tests/functionaltests/suites/default/expected/get_GetRecords-empty-maxrecords.xml
diff --git a/tests/expected/suites_default_get_GetRecords-filter-cql-title-or-abstract-with-spaces.xml b/tests/functionaltests/suites/default/expected/get_GetRecords-filter-cql-title-or-abstract-with-spaces.xml
similarity index 100%
rename from tests/expected/suites_default_get_GetRecords-filter-cql-title-or-abstract-with-spaces.xml
rename to tests/functionaltests/suites/default/expected/get_GetRecords-filter-cql-title-or-abstract-with-spaces.xml
diff --git a/tests/expected/suites_default_get_GetRecords-filter-cql-title-or-abstract.xml b/tests/functionaltests/suites/default/expected/get_GetRecords-filter-cql-title-or-abstract.xml
similarity index 100%
rename from tests/expected/suites_default_get_GetRecords-filter-cql-title-or-abstract.xml
rename to tests/functionaltests/suites/default/expected/get_GetRecords-filter-cql-title-or-abstract.xml
diff --git a/tests/expected/suites_default_get_GetRecords-filter-cql-title-with-spaces-or-abstract-with-spaces.xml b/tests/functionaltests/suites/default/expected/get_GetRecords-filter-cql-title-with-spaces-or-abstract-with-spaces.xml
similarity index 100%
rename from tests/expected/suites_default_get_GetRecords-filter-cql-title-with-spaces-or-abstract-with-spaces.xml
rename to tests/functionaltests/suites/default/expected/get_GetRecords-filter-cql-title-with-spaces-or-abstract-with-spaces.xml
diff --git a/tests/expected/suites_default_get_GetRecords-filter-cql-title-with-spaces-or-abstract.xml b/tests/functionaltests/suites/default/expected/get_GetRecords-filter-cql-title-with-spaces-or-abstract.xml
similarity index 100%
rename from tests/expected/suites_default_get_GetRecords-filter-cql-title-with-spaces-or-abstract.xml
rename to tests/functionaltests/suites/default/expected/get_GetRecords-filter-cql-title-with-spaces-or-abstract.xml
diff --git a/tests/expected/suites_default_get_GetRecords-filter-cql-title-with-spaces.xml b/tests/functionaltests/suites/default/expected/get_GetRecords-filter-cql-title-with-spaces.xml
similarity index 100%
rename from tests/expected/suites_default_get_GetRecords-filter-cql-title-with-spaces.xml
rename to tests/functionaltests/suites/default/expected/get_GetRecords-filter-cql-title-with-spaces.xml
diff --git a/tests/expected/suites_default_get_GetRecords-filter-cql-title.xml b/tests/functionaltests/suites/default/expected/get_GetRecords-filter-cql-title.xml
similarity index 100%
rename from tests/expected/suites_default_get_GetRecords-filter-cql-title.xml
rename to tests/functionaltests/suites/default/expected/get_GetRecords-filter-cql-title.xml
diff --git a/tests/expected/suites_default_get_GetRecords-filter.xml b/tests/functionaltests/suites/default/expected/get_GetRecords-filter.xml
similarity index 100%
rename from tests/expected/suites_default_get_GetRecords-filter.xml
rename to tests/functionaltests/suites/default/expected/get_GetRecords-filter.xml
diff --git a/tests/expected/suites_default_get_GetRecords-sortby-asc.xml b/tests/functionaltests/suites/default/expected/get_GetRecords-sortby-asc.xml
similarity index 100%
rename from tests/expected/suites_default_get_GetRecords-sortby-asc.xml
rename to tests/functionaltests/suites/default/expected/get_GetRecords-sortby-asc.xml
diff --git a/tests/expected/suites_default_get_GetRecords-sortby-desc.xml b/tests/functionaltests/suites/default/expected/get_GetRecords-sortby-desc.xml
similarity index 100%
rename from tests/expected/suites_default_get_GetRecords-sortby-desc.xml
rename to tests/functionaltests/suites/default/expected/get_GetRecords-sortby-desc.xml
diff --git a/tests/expected/suites_default_get_GetRecords-sortby-invalid-order.xml b/tests/functionaltests/suites/default/expected/get_GetRecords-sortby-invalid-order.xml
similarity index 100%
rename from tests/expected/suites_default_get_GetRecords-sortby-invalid-order.xml
rename to tests/functionaltests/suites/default/expected/get_GetRecords-sortby-invalid-order.xml
diff --git a/tests/expected/suites_default_get_GetRecords-sortby-invalid-propertyname.xml b/tests/functionaltests/suites/default/expected/get_GetRecords-sortby-invalid-propertyname.xml
similarity index 100%
rename from tests/expected/suites_default_get_GetRecords-sortby-invalid-propertyname.xml
rename to tests/functionaltests/suites/default/expected/get_GetRecords-sortby-invalid-propertyname.xml
diff --git a/tests/expected/suites_default_get_GetRepositoryItem.xml b/tests/functionaltests/suites/default/expected/get_GetRepositoryItem.xml
similarity index 100%
rename from tests/expected/suites_default_get_GetRepositoryItem.xml
rename to tests/functionaltests/suites/default/expected/get_GetRepositoryItem.xml
diff --git a/tests/expected/suites_default_post_DescribeRecord-json.xml b/tests/functionaltests/suites/default/expected/post_DescribeRecord-json.xml
similarity index 98%
rename from tests/expected/suites_default_post_DescribeRecord-json.xml
rename to tests/functionaltests/suites/default/expected/post_DescribeRecord-json.xml
index f83952e..19f117b 100644
--- a/tests/expected/suites_default_post_DescribeRecord-json.xml
+++ b/tests/functionaltests/suites/default/expected/post_DescribeRecord-json.xml
@@ -1,6 +1,6 @@
 {
     "csw:DescribeRecordResponse": {
-        "@http://www.w3.org/2001/XMLSchema-instance:schemaLocation": "http://www.opengis.net/cat/csw/2.0.2 http://schemas.opengis.net/csw/2.0.2/CSW-discovery.xsd",
+        "@xsi:schemaLocation": "http://www.opengis.net/cat/csw/2.0.2 http://schemas.opengis.net/csw/2.0.2/CSW-discovery.xsd",
         "csw:SchemaComponent": {
             "@schemaLanguage": "XMLSCHEMA",
             "@targetNamespace": "http://www.opengis.net/cat/csw/2.0.2",
diff --git a/tests/expected/suites_default_post_DescribeRecord.xml b/tests/functionaltests/suites/default/expected/post_DescribeRecord.xml
similarity index 100%
rename from tests/expected/suites_default_post_DescribeRecord.xml
rename to tests/functionaltests/suites/default/expected/post_DescribeRecord.xml
diff --git a/tests/expected/suites_default_post_GetRecords-filter-function-bad.xml b/tests/functionaltests/suites/default/expected/post_Exception-GetRecords-badsrsname.xml
similarity index 92%
copy from tests/expected/suites_default_post_GetRecords-filter-function-bad.xml
copy to tests/functionaltests/suites/default/expected/post_Exception-GetRecords-badsrsname.xml
index bc63e84..513628e 100644
--- a/tests/expected/suites_default_post_GetRecords-filter-function-bad.xml
+++ b/tests/functionaltests/suites/default/expected/post_Exception-GetRecords-badsrsname.xml
@@ -2,6 +2,6 @@
 <!-- PYCSW_VERSION -->
 <ows:ExceptionReport xmlns:csw="http://www.opengis.net/cat/csw/2.0.2" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dct="http://purl.org/dc/terms/" xmlns:gmd="http://www.isotc211.org/2005/gmd" xmlns:gml="http://www.opengis.net/gml" xmlns:ows="http://www.opengis.net/ows" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" language="en-US" version="1.2.0" xsi:schemaLocation="http://www.opengis.net/ows http://schemas.opengis.net/ows/1.0.0/ow [...]
   <ows:Exception exceptionCode="InvalidParameterValue" locator="service">
-    <ows:ExceptionText>Invalid Constraint: Invalid Filter request: Invalid ogc:Function: foo</ows:ExceptionText>
+    <ows:ExceptionText>Invalid Constraint: Invalid Filter request: Reprojection error: Invalid srsName</ows:ExceptionText>
   </ows:Exception>
 </ows:ExceptionReport>
diff --git a/tests/expected/suites_default_post_Exception-GetRecords-elementname.xml b/tests/functionaltests/suites/default/expected/post_Exception-GetRecords-elementname.xml
similarity index 100%
rename from tests/expected/suites_default_post_Exception-GetRecords-elementname.xml
rename to tests/functionaltests/suites/default/expected/post_Exception-GetRecords-elementname.xml
diff --git a/tests/expected/suites_default_post_Exception-GetRecords-invalid-xml.xml b/tests/functionaltests/suites/default/expected/post_Exception-GetRecords-invalid-xml.xml
similarity index 100%
rename from tests/expected/suites_default_post_Exception-GetRecords-invalid-xml.xml
rename to tests/functionaltests/suites/default/expected/post_Exception-GetRecords-invalid-xml.xml
diff --git a/tests/expected/suites_default_post_GetCapabilities-SOAP.xml b/tests/functionaltests/suites/default/expected/post_GetCapabilities-SOAP.xml
similarity index 100%
rename from tests/expected/suites_default_post_GetCapabilities-SOAP.xml
rename to tests/functionaltests/suites/default/expected/post_GetCapabilities-SOAP.xml
diff --git a/tests/expected/suites_default_post_GetCapabilities-sections.xml b/tests/functionaltests/suites/default/expected/post_GetCapabilities-sections.xml
similarity index 100%
rename from tests/expected/suites_default_post_GetCapabilities-sections.xml
rename to tests/functionaltests/suites/default/expected/post_GetCapabilities-sections.xml
diff --git a/tests/expected/suites_default_post_GetCapabilities-updatesequence.xml b/tests/functionaltests/suites/default/expected/post_GetCapabilities-updatesequence.xml
similarity index 100%
rename from tests/expected/suites_default_post_GetCapabilities-updatesequence.xml
rename to tests/functionaltests/suites/default/expected/post_GetCapabilities-updatesequence.xml
diff --git a/tests/expected/suites_default_post_GetCapabilities.xml b/tests/functionaltests/suites/default/expected/post_GetCapabilities.xml
similarity index 100%
rename from tests/expected/suites_default_post_GetCapabilities.xml
rename to tests/functionaltests/suites/default/expected/post_GetCapabilities.xml
diff --git a/tests/expected/suites_default_post_GetDomain-parameter.xml b/tests/functionaltests/suites/default/expected/post_GetDomain-parameter.xml
similarity index 100%
rename from tests/expected/suites_default_post_GetDomain-parameter.xml
rename to tests/functionaltests/suites/default/expected/post_GetDomain-parameter.xml
diff --git a/tests/expected/suites_default_post_GetDomain-property.xml b/tests/functionaltests/suites/default/expected/post_GetDomain-property.xml
similarity index 100%
rename from tests/expected/suites_default_post_GetDomain-property.xml
rename to tests/functionaltests/suites/default/expected/post_GetDomain-property.xml
diff --git a/tests/expected/suites_default_post_GetRecordById-json.xml b/tests/functionaltests/suites/default/expected/post_GetRecordById-json.xml
similarity index 80%
rename from tests/expected/suites_default_post_GetRecordById-json.xml
rename to tests/functionaltests/suites/default/expected/post_GetRecordById-json.xml
index a13b4e9..e8d687f 100644
--- a/tests/expected/suites_default_post_GetRecordById-json.xml
+++ b/tests/functionaltests/suites/default/expected/post_GetRecordById-json.xml
@@ -1,6 +1,6 @@
 {
     "csw:GetRecordByIdResponse": {
-        "@http://www.w3.org/2001/XMLSchema-instance:schemaLocation": "http://www.opengis.net/cat/csw/2.0.2 http://schemas.opengis.net/csw/2.0.2/CSW-discovery.xsd",
+        "@xsi:schemaLocation": "http://www.opengis.net/cat/csw/2.0.2 http://schemas.opengis.net/csw/2.0.2/CSW-discovery.xsd",
         "csw:SummaryRecord": {
             "dc:identifier": "urn:uuid:94bc9c83-97f6-4b40-9eb8-a8e8787a5c63",
             "dc:title": "Mauris sed neque",
diff --git a/tests/expected/suites_default_post_GetRecordById.xml b/tests/functionaltests/suites/default/expected/post_GetRecordById.xml
similarity index 100%
rename from tests/expected/suites_default_post_GetRecordById.xml
rename to tests/functionaltests/suites/default/expected/post_GetRecordById.xml
diff --git a/tests/expected/suites_default_post_GetRecords-all-json.xml b/tests/functionaltests/suites/default/expected/post_GetRecords-all-json.xml
similarity index 94%
rename from tests/expected/suites_default_post_GetRecords-all-json.xml
rename to tests/functionaltests/suites/default/expected/post_GetRecords-all-json.xml
index ba33ab6..20fbf37 100644
--- a/tests/expected/suites_default_post_GetRecords-all-json.xml
+++ b/tests/functionaltests/suites/default/expected/post_GetRecords-all-json.xml
@@ -1,7 +1,7 @@
 {
     "csw:GetRecordsResponse": {
         "@version": "2.0.2",
-        "@http://www.w3.org/2001/XMLSchema-instance:schemaLocation": "http://www.opengis.net/cat/csw/2.0.2 http://schemas.opengis.net/csw/2.0.2/CSW-discovery.xsd",
+        "@xsi:schemaLocation": "http://www.opengis.net/cat/csw/2.0.2 http://schemas.opengis.net/csw/2.0.2/CSW-discovery.xsd",
         "csw:SearchStatus": {
             "@timestamp": "PYCSW_TIMESTAMP"
         },
diff --git a/tests/expected/suites_default_post_GetRecords-all-resulttype-hits.xml b/tests/functionaltests/suites/default/expected/post_GetRecords-all-resulttype-hits.xml
similarity index 100%
rename from tests/expected/suites_default_post_GetRecords-all-resulttype-hits.xml
rename to tests/functionaltests/suites/default/expected/post_GetRecords-all-resulttype-hits.xml
diff --git a/tests/expected/suites_default_post_GetRecords-all-resulttype-validate.xml b/tests/functionaltests/suites/default/expected/post_GetRecords-all-resulttype-validate.xml
similarity index 100%
rename from tests/expected/suites_default_post_GetRecords-all-resulttype-validate.xml
rename to tests/functionaltests/suites/default/expected/post_GetRecords-all-resulttype-validate.xml
diff --git a/tests/expected/suites_default_post_GetRecords-all-sortby-bbox.xml b/tests/functionaltests/suites/default/expected/post_GetRecords-all-sortby-bbox.xml
similarity index 100%
rename from tests/expected/suites_default_post_GetRecords-all-sortby-bbox.xml
rename to tests/functionaltests/suites/default/expected/post_GetRecords-all-sortby-bbox.xml
diff --git a/tests/expected/suites_default_post_GetRecords-all.xml b/tests/functionaltests/suites/default/expected/post_GetRecords-all.xml
similarity index 100%
rename from tests/expected/suites_default_post_GetRecords-all.xml
rename to tests/functionaltests/suites/default/expected/post_GetRecords-all.xml
diff --git a/tests/expected/suites_default_post_GetRecords-bbox-filter-crs84.xml b/tests/functionaltests/suites/default/expected/post_GetRecords-bbox-filter-crs84.xml
similarity index 100%
rename from tests/expected/suites_default_post_GetRecords-bbox-filter-crs84.xml
rename to tests/functionaltests/suites/default/expected/post_GetRecords-bbox-filter-crs84.xml
diff --git a/tests/expected/suites_default_post_GetRecords-cql-title-and-abstract.xml b/tests/functionaltests/suites/default/expected/post_GetRecords-cql-title-and-abstract.xml
similarity index 100%
rename from tests/expected/suites_default_post_GetRecords-cql-title-and-abstract.xml
rename to tests/functionaltests/suites/default/expected/post_GetRecords-cql-title-and-abstract.xml
diff --git a/tests/expected/suites_default_post_GetRecords-cql-title.xml b/tests/functionaltests/suites/default/expected/post_GetRecords-cql-title.xml
similarity index 100%
rename from tests/expected/suites_default_post_GetRecords-cql-title.xml
rename to tests/functionaltests/suites/default/expected/post_GetRecords-cql-title.xml
diff --git a/tests/expected/suites_default_post_GetRecords-distributedsearch.xml b/tests/functionaltests/suites/default/expected/post_GetRecords-distributedsearch.xml
similarity index 100%
rename from tests/expected/suites_default_post_GetRecords-distributedsearch.xml
rename to tests/functionaltests/suites/default/expected/post_GetRecords-distributedsearch.xml
diff --git a/tests/expected/suites_default_post_GetRecords-elementname.xml b/tests/functionaltests/suites/default/expected/post_GetRecords-elementname.xml
similarity index 100%
rename from tests/expected/suites_default_post_GetRecords-elementname.xml
rename to tests/functionaltests/suites/default/expected/post_GetRecords-elementname.xml
diff --git a/tests/expected/suites_default_post_GetRecords-end.xml b/tests/functionaltests/suites/default/expected/post_GetRecords-end.xml
similarity index 100%
rename from tests/expected/suites_default_post_GetRecords-end.xml
rename to tests/functionaltests/suites/default/expected/post_GetRecords-end.xml
diff --git a/tests/expected/suites_default_post_GetRecords-filter-and-bbox-freetext.xml b/tests/functionaltests/suites/default/expected/post_GetRecords-filter-and-bbox-freetext.xml
similarity index 100%
rename from tests/expected/suites_default_post_GetRecords-filter-and-bbox-freetext.xml
rename to tests/functionaltests/suites/default/expected/post_GetRecords-filter-and-bbox-freetext.xml
diff --git a/tests/expected/suites_default_post_GetRecords-filter-and-nested-or.xml b/tests/functionaltests/suites/default/expected/post_GetRecords-filter-and-nested-or.xml
similarity index 100%
rename from tests/expected/suites_default_post_GetRecords-filter-and-nested-or.xml
rename to tests/functionaltests/suites/default/expected/post_GetRecords-filter-and-nested-or.xml
diff --git a/tests/expected/suites_default_post_GetRecords-filter-and-nested-or2.xml b/tests/functionaltests/suites/default/expected/post_GetRecords-filter-and-nested-or2.xml
similarity index 100%
rename from tests/expected/suites_default_post_GetRecords-filter-and-nested-or2.xml
rename to tests/functionaltests/suites/default/expected/post_GetRecords-filter-and-nested-or2.xml
diff --git a/tests/expected/suites_default_post_GetRecords-filter-anytext-and-not.xml b/tests/functionaltests/suites/default/expected/post_GetRecords-filter-anytext-and-not.xml
similarity index 100%
rename from tests/expected/suites_default_post_GetRecords-filter-anytext-and-not.xml
rename to tests/functionaltests/suites/default/expected/post_GetRecords-filter-anytext-and-not.xml
diff --git a/tests/expected/suites_default_post_GetRecords-filter-anytext-equal.xml b/tests/functionaltests/suites/default/expected/post_GetRecords-filter-anytext-equal.xml
similarity index 100%
rename from tests/expected/suites_default_post_GetRecords-filter-anytext-equal.xml
rename to tests/functionaltests/suites/default/expected/post_GetRecords-filter-anytext-equal.xml
diff --git a/tests/expected/suites_default_post_GetRecords-filter-anytext.xml b/tests/functionaltests/suites/default/expected/post_GetRecords-filter-anytext.xml
similarity index 100%
rename from tests/expected/suites_default_post_GetRecords-filter-anytext.xml
rename to tests/functionaltests/suites/default/expected/post_GetRecords-filter-anytext.xml
diff --git a/tests/expected/suites_default_post_GetRecords-filter-bbox-reproject.xml b/tests/functionaltests/suites/default/expected/post_GetRecords-filter-bbox-reproject.xml
similarity index 100%
rename from tests/expected/suites_default_post_GetRecords-filter-bbox-reproject.xml
rename to tests/functionaltests/suites/default/expected/post_GetRecords-filter-bbox-reproject.xml
diff --git a/tests/expected/suites_default_post_GetRecords-filter-bbox-sortby.xml b/tests/functionaltests/suites/default/expected/post_GetRecords-filter-bbox-sortby.xml
similarity index 100%
rename from tests/expected/suites_default_post_GetRecords-filter-bbox-sortby.xml
rename to tests/functionaltests/suites/default/expected/post_GetRecords-filter-bbox-sortby.xml
diff --git a/tests/expected/suites_default_post_GetRecords-filter-bbox.xml b/tests/functionaltests/suites/default/expected/post_GetRecords-filter-bbox.xml
similarity index 100%
rename from tests/expected/suites_default_post_GetRecords-filter-bbox.xml
rename to tests/functionaltests/suites/default/expected/post_GetRecords-filter-bbox.xml
diff --git a/tests/expected/suites_default_post_GetRecords-filter-between.xml b/tests/functionaltests/suites/default/expected/post_GetRecords-filter-between.xml
similarity index 100%
rename from tests/expected/suites_default_post_GetRecords-filter-between.xml
rename to tests/functionaltests/suites/default/expected/post_GetRecords-filter-between.xml
diff --git a/tests/expected/suites_default_post_GetRecords-filter-function-bad.xml b/tests/functionaltests/suites/default/expected/post_GetRecords-filter-function-bad.xml
similarity index 100%
rename from tests/expected/suites_default_post_GetRecords-filter-function-bad.xml
rename to tests/functionaltests/suites/default/expected/post_GetRecords-filter-function-bad.xml
diff --git a/tests/expected/suites_default_post_GetRecords-filter-function.xml b/tests/functionaltests/suites/default/expected/post_GetRecords-filter-function.xml
similarity index 100%
rename from tests/expected/suites_default_post_GetRecords-filter-function.xml
rename to tests/functionaltests/suites/default/expected/post_GetRecords-filter-function.xml
diff --git a/tests/expected/suites_default_post_GetRecords-filter-not-bbox.xml b/tests/functionaltests/suites/default/expected/post_GetRecords-filter-not-bbox.xml
similarity index 100%
rename from tests/expected/suites_default_post_GetRecords-filter-not-bbox.xml
rename to tests/functionaltests/suites/default/expected/post_GetRecords-filter-not-bbox.xml
diff --git a/tests/expected/suites_default_post_GetRecords-filter-or-bbox-freetext.xml b/tests/functionaltests/suites/default/expected/post_GetRecords-filter-or-bbox-freetext.xml
similarity index 100%
rename from tests/expected/suites_default_post_GetRecords-filter-or-bbox-freetext.xml
rename to tests/functionaltests/suites/default/expected/post_GetRecords-filter-or-bbox-freetext.xml
diff --git a/tests/expected/suites_default_post_GetRecords-filter-or-nested-and.xml b/tests/functionaltests/suites/default/expected/post_GetRecords-filter-or-nested-and.xml
similarity index 100%
rename from tests/expected/suites_default_post_GetRecords-filter-or-nested-and.xml
rename to tests/functionaltests/suites/default/expected/post_GetRecords-filter-or-nested-and.xml
diff --git a/tests/expected/suites_default_post_GetRecords-filter-or-title-abstract.xml b/tests/functionaltests/suites/default/expected/post_GetRecords-filter-or-title-abstract.xml
similarity index 100%
rename from tests/expected/suites_default_post_GetRecords-filter-or-title-abstract.xml
rename to tests/functionaltests/suites/default/expected/post_GetRecords-filter-or-title-abstract.xml
diff --git a/tests/expected/suites_default_post_GetRecords-maxrecords.xml b/tests/functionaltests/suites/default/expected/post_GetRecords-maxrecords.xml
similarity index 100%
rename from tests/expected/suites_default_post_GetRecords-maxrecords.xml
rename to tests/functionaltests/suites/default/expected/post_GetRecords-maxrecords.xml
diff --git a/tests/expected/suites_default_post_GetRecords-requestid.xml b/tests/functionaltests/suites/default/expected/post_GetRecords-requestid.xml
similarity index 100%
rename from tests/expected/suites_default_post_GetRecords-requestid.xml
rename to tests/functionaltests/suites/default/expected/post_GetRecords-requestid.xml
diff --git a/tests/expected/suites_default_post_Harvest-default.xml b/tests/functionaltests/suites/default/expected/post_Harvest-default.xml
similarity index 100%
rename from tests/expected/suites_default_post_Harvest-default.xml
rename to tests/functionaltests/suites/default/expected/post_Harvest-default.xml
diff --git a/tests/expected/suites_default_post_Harvest-response-handler.xml b/tests/functionaltests/suites/default/expected/post_Harvest-response-handler.xml
similarity index 100%
rename from tests/expected/suites_default_post_Harvest-response-handler.xml
rename to tests/functionaltests/suites/default/expected/post_Harvest-response-handler.xml
diff --git a/tests/expected/suites_default_post_Transaction-delete.xml b/tests/functionaltests/suites/default/expected/post_Transaction-delete.xml
similarity index 100%
rename from tests/expected/suites_default_post_Transaction-delete.xml
rename to tests/functionaltests/suites/default/expected/post_Transaction-delete.xml
diff --git a/tests/expected/suites_default_post_Transaction-insert.xml b/tests/functionaltests/suites/default/expected/post_Transaction-insert.xml
similarity index 100%
rename from tests/expected/suites_default_post_Transaction-insert.xml
rename to tests/functionaltests/suites/default/expected/post_Transaction-insert.xml
diff --git a/tests/expected/suites_default_post_Transaction-update-full.xml b/tests/functionaltests/suites/default/expected/post_Transaction-update-full.xml
similarity index 100%
rename from tests/expected/suites_default_post_Transaction-update-full.xml
rename to tests/functionaltests/suites/default/expected/post_Transaction-update-full.xml
diff --git a/tests/expected/suites_default_post_Transaction-update-recordproperty.xml b/tests/functionaltests/suites/default/expected/post_Transaction-update-recordproperty.xml
similarity index 100%
rename from tests/expected/suites_default_post_Transaction-update-recordproperty.xml
rename to tests/functionaltests/suites/default/expected/post_Transaction-update-recordproperty.xml
diff --git a/tests/functionaltests/suites/default/get/requests.txt b/tests/functionaltests/suites/default/get/requests.txt
new file mode 100644
index 0000000..299790a
--- /dev/null
+++ b/tests/functionaltests/suites/default/get/requests.txt
@@ -0,0 +1,20 @@
+GetCapabilities,service=CSW&version=2.0.2&request=GetCapabilities
+GetCapabilities-invalid-request,service=CSW&version=2.0.2&request=GetCapabilitiese
+GetRecords-all,service=CSW&version=2.0.2&request=GetRecords&typenames=csw:Record&elementsetname=full
+GetRecords-sortby-asc,service=CSW&version=2.0.2&request=GetRecords&typenames=csw:Record&elementsetname=full&resulttype=results&sortby=dc:title:A
+GetRecords-sortby-desc,service=CSW&version=2.0.2&request=GetRecords&typenames=csw:Record&elementsetname=full&resulttype=results&sortby=dc:title:D
+GetRecords-sortby-invalid-propertyname,service=CSW&version=2.0.2&request=GetRecords&typenames=csw:Record&elementsetname=full&resulttype=results&sortby=dc:titlei:A
+GetRecords-sortby-invalid-order,service=CSW&version=2.0.2&request=GetRecords&typenames=csw:Record&elementsetname=full&resulttype=results&sortby=dc:title:FOO
+GetRecords-filter,service=CSW&version=2.0.2&request=GetRecords&typenames=csw:Record&elementsetname=full&resulttype=results&constraintlanguage=FILTER&constraint=%3Cogc%3AFilter%20xmlns%3Aogc%3D%22http%3A%2F%2Fwww.opengis.net%2Fogc%22%3E%3Cogc%3APropertyIsEqualTo%3E%3Cogc%3APropertyName%3Edc%3Atitle%3C%2Fogc%3APropertyName%3E%3Cogc%3ALiteral%3ELorem%20ipsum%3C%2Fogc%3ALiteral%3E%3C%2Fogc%3APropertyIsEqualTo%3E%3C%2Fogc%3AFilter%3E
+GetRecords-filter-cql-title,service=CSW&version=2.0.2&request=GetRecords&typenames=csw:Record&elementsetname=full&resulttype=results&constraintlanguage=CQL_TEXT&constraint=dc%3Atitle%20like%20%27%25lor%25%27
+GetRecords-filter-cql-title-with-spaces,service=CSW&version=2.0.2&request=GetRecords&typenames=csw:Record&elementsetname=full&resulttype=results&constraintlanguage=CQL_TEXT&constraint=dc%3Atitle%20like%20%27%25Lorem%20ipsum%25%27
+GetRecords-filter-cql-title-or-abstract,service=CSW&version=2.0.2&request=GetRecords&typenames=csw:Record&elementsetname=full&resulttype=results&constraintlanguage=CQL_TEXT&constraint=dc%3Atitle%20like%20%27%25lor%25%27%20or%20dct%3Aabstract%20like%20%27%25pharetra%25%27
+GetRecords-filter-cql-title-with-spaces-or-abstract,service=CSW&version=2.0.2&request=GetRecords&typenames=csw:Record&elementsetname=full&resulttype=results&constraintlanguage=CQL_TEXT&constraint=dc%3Atitle%20like%20%27%25dolor%20sit%25%27%20or%20dct%3Aabstract%20like%20%27%25pharetra%25%27
+GetRecords-filter-cql-title-or-abstract-with-spaces,service=CSW&version=2.0.2&request=GetRecords&typenames=csw:Record&elementsetname=full&resulttype=results&constraintlanguage=CQL_TEXT&constraint=dc%3Atitle%20like%20%27%25lor%25%27%20or%20dct%3Aabstract%20like%20%27%25pharetra%20in%25%27
+GetRecords-filter-cql-title-with-spaces-or-abstract-with-spaces,service=CSW&version=2.0.2&request=GetRecords&typenames=csw:Record&elementsetname=full&resulttype=results&constraintlanguage=CQL_TEXT&constraint=dc%3Atitle%20like%20%27%25dolor%20sit%25%27%20or%20dct%3Aabstract%20like%20%27%25pharetra%20in%25%27
+GetRecords-empty-maxrecords,service=CSW&version=2.0.2&request=GetRecords&typenames=csw:Record&elementsetname=full&maxrecords=
+GetRepositoryItem,service=CSW&version=2.0.2&request=GetRepositoryItem&id=urn:uuid:94bc9c83-97f6-4b40-9eb8-a8e8787a5c63
+Exception-GetRepositoryItem-notfound,service=CSW&version=2.0.2&request=GetRepositoryItem&id=NOTFOUND
+Exception-GetRepositoryItem-service-invalid1,service=CSW%00&version=2.0.2&request=GetRepositoryItem&id=123
+Exception-GetRepositoryItem-service-invalid2,service=CSW%00'&version=2.0.2&request=GetRepositoryItem&id=123
+Exception-GetRepositoryItem-version-invalid,service=CSW&version=2.0.2'&request=GetRepositoryItem&id=123
diff --git a/tests/suites/default/post/DescribeRecord-json.xml b/tests/functionaltests/suites/default/post/DescribeRecord-json.xml
similarity index 100%
rename from tests/suites/default/post/DescribeRecord-json.xml
rename to tests/functionaltests/suites/default/post/DescribeRecord-json.xml
diff --git a/tests/suites/default/post/DescribeRecord.xml b/tests/functionaltests/suites/default/post/DescribeRecord.xml
similarity index 100%
rename from tests/suites/default/post/DescribeRecord.xml
rename to tests/functionaltests/suites/default/post/DescribeRecord.xml
diff --git a/tests/suites/default/post/Exception-GetRecords-badsrsname.xml b/tests/functionaltests/suites/default/post/Exception-GetRecords-badsrsname.xml
similarity index 100%
rename from tests/suites/default/post/Exception-GetRecords-badsrsname.xml
rename to tests/functionaltests/suites/default/post/Exception-GetRecords-badsrsname.xml
diff --git a/tests/suites/default/post/Exception-GetRecords-elementname.xml b/tests/functionaltests/suites/default/post/Exception-GetRecords-elementname.xml
similarity index 100%
rename from tests/suites/default/post/Exception-GetRecords-elementname.xml
rename to tests/functionaltests/suites/default/post/Exception-GetRecords-elementname.xml
diff --git a/tests/suites/default/post/Exception-GetRecords-invalid-xml.xml b/tests/functionaltests/suites/default/post/Exception-GetRecords-invalid-xml.xml
similarity index 100%
rename from tests/suites/default/post/Exception-GetRecords-invalid-xml.xml
rename to tests/functionaltests/suites/default/post/Exception-GetRecords-invalid-xml.xml
diff --git a/tests/suites/default/post/GetCapabilities-SOAP.xml b/tests/functionaltests/suites/default/post/GetCapabilities-SOAP.xml
similarity index 100%
rename from tests/suites/default/post/GetCapabilities-SOAP.xml
rename to tests/functionaltests/suites/default/post/GetCapabilities-SOAP.xml
diff --git a/tests/suites/default/post/GetCapabilities-sections.xml b/tests/functionaltests/suites/default/post/GetCapabilities-sections.xml
similarity index 100%
rename from tests/suites/default/post/GetCapabilities-sections.xml
rename to tests/functionaltests/suites/default/post/GetCapabilities-sections.xml
diff --git a/tests/suites/default/post/GetCapabilities-updatesequence.xml b/tests/functionaltests/suites/default/post/GetCapabilities-updatesequence.xml
similarity index 100%
rename from tests/suites/default/post/GetCapabilities-updatesequence.xml
rename to tests/functionaltests/suites/default/post/GetCapabilities-updatesequence.xml
diff --git a/tests/suites/default/post/GetCapabilities.xml b/tests/functionaltests/suites/default/post/GetCapabilities.xml
similarity index 100%
rename from tests/suites/default/post/GetCapabilities.xml
rename to tests/functionaltests/suites/default/post/GetCapabilities.xml
diff --git a/tests/suites/default/post/GetDomain-parameter.xml b/tests/functionaltests/suites/default/post/GetDomain-parameter.xml
similarity index 100%
rename from tests/suites/default/post/GetDomain-parameter.xml
rename to tests/functionaltests/suites/default/post/GetDomain-parameter.xml
diff --git a/tests/suites/default/post/GetDomain-property.xml b/tests/functionaltests/suites/default/post/GetDomain-property.xml
similarity index 100%
rename from tests/suites/default/post/GetDomain-property.xml
rename to tests/functionaltests/suites/default/post/GetDomain-property.xml
diff --git a/tests/suites/default/post/GetRecordById-json.xml b/tests/functionaltests/suites/default/post/GetRecordById-json.xml
similarity index 100%
rename from tests/suites/default/post/GetRecordById-json.xml
rename to tests/functionaltests/suites/default/post/GetRecordById-json.xml
diff --git a/tests/suites/default/post/GetRecordById.xml b/tests/functionaltests/suites/default/post/GetRecordById.xml
similarity index 100%
rename from tests/suites/default/post/GetRecordById.xml
rename to tests/functionaltests/suites/default/post/GetRecordById.xml
diff --git a/tests/suites/default/post/GetRecords-all-json.xml b/tests/functionaltests/suites/default/post/GetRecords-all-json.xml
similarity index 100%
rename from tests/suites/default/post/GetRecords-all-json.xml
rename to tests/functionaltests/suites/default/post/GetRecords-all-json.xml
diff --git a/tests/suites/default/post/GetRecords-all-resulttype-hits.xml b/tests/functionaltests/suites/default/post/GetRecords-all-resulttype-hits.xml
similarity index 100%
rename from tests/suites/default/post/GetRecords-all-resulttype-hits.xml
rename to tests/functionaltests/suites/default/post/GetRecords-all-resulttype-hits.xml
diff --git a/tests/suites/default/post/GetRecords-all-resulttype-validate.xml b/tests/functionaltests/suites/default/post/GetRecords-all-resulttype-validate.xml
similarity index 100%
rename from tests/suites/default/post/GetRecords-all-resulttype-validate.xml
rename to tests/functionaltests/suites/default/post/GetRecords-all-resulttype-validate.xml
diff --git a/tests/suites/default/post/GetRecords-all-sortby-bbox.xml b/tests/functionaltests/suites/default/post/GetRecords-all-sortby-bbox.xml
similarity index 100%
copy from tests/suites/default/post/GetRecords-all-sortby-bbox.xml
copy to tests/functionaltests/suites/default/post/GetRecords-all-sortby-bbox.xml
diff --git a/tests/suites/default/post/GetRecords-all.xml b/tests/functionaltests/suites/default/post/GetRecords-all.xml
similarity index 100%
rename from tests/suites/default/post/GetRecords-all.xml
rename to tests/functionaltests/suites/default/post/GetRecords-all.xml
diff --git a/tests/suites/default/post/GetRecords-bbox-filter-crs84.xml b/tests/functionaltests/suites/default/post/GetRecords-bbox-filter-crs84.xml
similarity index 100%
rename from tests/suites/default/post/GetRecords-bbox-filter-crs84.xml
rename to tests/functionaltests/suites/default/post/GetRecords-bbox-filter-crs84.xml
diff --git a/tests/suites/default/post/GetRecords-cql-title-and-abstract.xml b/tests/functionaltests/suites/default/post/GetRecords-cql-title-and-abstract.xml
similarity index 100%
rename from tests/suites/default/post/GetRecords-cql-title-and-abstract.xml
rename to tests/functionaltests/suites/default/post/GetRecords-cql-title-and-abstract.xml
diff --git a/tests/suites/default/post/GetRecords-cql-title.xml b/tests/functionaltests/suites/default/post/GetRecords-cql-title.xml
similarity index 100%
rename from tests/suites/default/post/GetRecords-cql-title.xml
rename to tests/functionaltests/suites/default/post/GetRecords-cql-title.xml
diff --git a/tests/suites/default/post/GetRecords-distributedsearch.xml b/tests/functionaltests/suites/default/post/GetRecords-distributedsearch.xml
similarity index 100%
rename from tests/suites/default/post/GetRecords-distributedsearch.xml
rename to tests/functionaltests/suites/default/post/GetRecords-distributedsearch.xml
diff --git a/tests/suites/default/post/GetRecords-elementname.xml b/tests/functionaltests/suites/default/post/GetRecords-elementname.xml
similarity index 100%
rename from tests/suites/default/post/GetRecords-elementname.xml
rename to tests/functionaltests/suites/default/post/GetRecords-elementname.xml
diff --git a/tests/suites/default/post/GetRecords-end.xml b/tests/functionaltests/suites/default/post/GetRecords-end.xml
similarity index 100%
rename from tests/suites/default/post/GetRecords-end.xml
rename to tests/functionaltests/suites/default/post/GetRecords-end.xml
diff --git a/tests/suites/default/post/GetRecords-filter-and-bbox-freetext.xml b/tests/functionaltests/suites/default/post/GetRecords-filter-and-bbox-freetext.xml
similarity index 100%
rename from tests/suites/default/post/GetRecords-filter-and-bbox-freetext.xml
rename to tests/functionaltests/suites/default/post/GetRecords-filter-and-bbox-freetext.xml
diff --git a/tests/suites/default/post/GetRecords-filter-and-nested-or.xml b/tests/functionaltests/suites/default/post/GetRecords-filter-and-nested-or.xml
similarity index 100%
rename from tests/suites/default/post/GetRecords-filter-and-nested-or.xml
rename to tests/functionaltests/suites/default/post/GetRecords-filter-and-nested-or.xml
diff --git a/tests/suites/default/post/GetRecords-filter-and-nested-or2.xml b/tests/functionaltests/suites/default/post/GetRecords-filter-and-nested-or2.xml
similarity index 100%
rename from tests/suites/default/post/GetRecords-filter-and-nested-or2.xml
rename to tests/functionaltests/suites/default/post/GetRecords-filter-and-nested-or2.xml
diff --git a/tests/suites/default/post/GetRecords-filter-anytext-and-not.xml b/tests/functionaltests/suites/default/post/GetRecords-filter-anytext-and-not.xml
similarity index 100%
rename from tests/suites/default/post/GetRecords-filter-anytext-and-not.xml
rename to tests/functionaltests/suites/default/post/GetRecords-filter-anytext-and-not.xml
diff --git a/tests/suites/default/post/GetRecords-filter-anytext-equal.xml b/tests/functionaltests/suites/default/post/GetRecords-filter-anytext-equal.xml
similarity index 100%
rename from tests/suites/default/post/GetRecords-filter-anytext-equal.xml
rename to tests/functionaltests/suites/default/post/GetRecords-filter-anytext-equal.xml
diff --git a/tests/suites/default/post/GetRecords-filter-anytext.xml b/tests/functionaltests/suites/default/post/GetRecords-filter-anytext.xml
similarity index 100%
rename from tests/suites/default/post/GetRecords-filter-anytext.xml
rename to tests/functionaltests/suites/default/post/GetRecords-filter-anytext.xml
diff --git a/tests/suites/default/post/GetRecords-filter-bbox-reproject.xml b/tests/functionaltests/suites/default/post/GetRecords-filter-bbox-reproject.xml
similarity index 100%
rename from tests/suites/default/post/GetRecords-filter-bbox-reproject.xml
rename to tests/functionaltests/suites/default/post/GetRecords-filter-bbox-reproject.xml
diff --git a/tests/suites/default/post/GetRecords-filter-bbox-sortby.xml b/tests/functionaltests/suites/default/post/GetRecords-filter-bbox-sortby.xml
similarity index 100%
rename from tests/suites/default/post/GetRecords-filter-bbox-sortby.xml
rename to tests/functionaltests/suites/default/post/GetRecords-filter-bbox-sortby.xml
diff --git a/tests/suites/default/post/GetRecords-filter-bbox.xml b/tests/functionaltests/suites/default/post/GetRecords-filter-bbox.xml
similarity index 100%
rename from tests/suites/default/post/GetRecords-filter-bbox.xml
rename to tests/functionaltests/suites/default/post/GetRecords-filter-bbox.xml
diff --git a/tests/suites/default/post/GetRecords-filter-between.xml b/tests/functionaltests/suites/default/post/GetRecords-filter-between.xml
similarity index 100%
rename from tests/suites/default/post/GetRecords-filter-between.xml
rename to tests/functionaltests/suites/default/post/GetRecords-filter-between.xml
diff --git a/tests/suites/default/post/GetRecords-filter-function-bad.xml b/tests/functionaltests/suites/default/post/GetRecords-filter-function-bad.xml
similarity index 100%
rename from tests/suites/default/post/GetRecords-filter-function-bad.xml
rename to tests/functionaltests/suites/default/post/GetRecords-filter-function-bad.xml
diff --git a/tests/suites/default/post/GetRecords-filter-function.xml b/tests/functionaltests/suites/default/post/GetRecords-filter-function.xml
similarity index 100%
rename from tests/suites/default/post/GetRecords-filter-function.xml
rename to tests/functionaltests/suites/default/post/GetRecords-filter-function.xml
diff --git a/tests/suites/default/post/GetRecords-filter-not-bbox.xml b/tests/functionaltests/suites/default/post/GetRecords-filter-not-bbox.xml
similarity index 100%
rename from tests/suites/default/post/GetRecords-filter-not-bbox.xml
rename to tests/functionaltests/suites/default/post/GetRecords-filter-not-bbox.xml
diff --git a/tests/suites/default/post/GetRecords-filter-or-bbox-freetext.xml b/tests/functionaltests/suites/default/post/GetRecords-filter-or-bbox-freetext.xml
similarity index 100%
rename from tests/suites/default/post/GetRecords-filter-or-bbox-freetext.xml
rename to tests/functionaltests/suites/default/post/GetRecords-filter-or-bbox-freetext.xml
diff --git a/tests/suites/default/post/GetRecords-filter-or-nested-and.xml b/tests/functionaltests/suites/default/post/GetRecords-filter-or-nested-and.xml
similarity index 100%
rename from tests/suites/default/post/GetRecords-filter-or-nested-and.xml
rename to tests/functionaltests/suites/default/post/GetRecords-filter-or-nested-and.xml
diff --git a/tests/suites/default/post/GetRecords-filter-or-title-abstract.xml b/tests/functionaltests/suites/default/post/GetRecords-filter-or-title-abstract.xml
similarity index 100%
rename from tests/suites/default/post/GetRecords-filter-or-title-abstract.xml
rename to tests/functionaltests/suites/default/post/GetRecords-filter-or-title-abstract.xml
diff --git a/tests/suites/default/post/GetRecords-maxrecords.xml b/tests/functionaltests/suites/default/post/GetRecords-maxrecords.xml
similarity index 100%
rename from tests/suites/default/post/GetRecords-maxrecords.xml
rename to tests/functionaltests/suites/default/post/GetRecords-maxrecords.xml
diff --git a/tests/suites/default/post/GetRecords-requestid.xml b/tests/functionaltests/suites/default/post/GetRecords-requestid.xml
similarity index 100%
rename from tests/suites/default/post/GetRecords-requestid.xml
rename to tests/functionaltests/suites/default/post/GetRecords-requestid.xml
diff --git a/tests/suites/default/post/Harvest-default.xml b/tests/functionaltests/suites/default/post/Harvest-default.xml
similarity index 100%
rename from tests/suites/default/post/Harvest-default.xml
rename to tests/functionaltests/suites/default/post/Harvest-default.xml
diff --git a/tests/suites/default/post/Harvest-response-handler.xml b/tests/functionaltests/suites/default/post/Harvest-response-handler.xml
similarity index 100%
rename from tests/suites/default/post/Harvest-response-handler.xml
rename to tests/functionaltests/suites/default/post/Harvest-response-handler.xml
diff --git a/tests/suites/default/post/Transaction-delete.xml b/tests/functionaltests/suites/default/post/Transaction-delete.xml
similarity index 100%
rename from tests/suites/default/post/Transaction-delete.xml
rename to tests/functionaltests/suites/default/post/Transaction-delete.xml
diff --git a/tests/suites/default/post/Transaction-insert.xml b/tests/functionaltests/suites/default/post/Transaction-insert.xml
similarity index 100%
rename from tests/suites/default/post/Transaction-insert.xml
rename to tests/functionaltests/suites/default/post/Transaction-insert.xml
diff --git a/tests/suites/default/post/Transaction-update-full.xml b/tests/functionaltests/suites/default/post/Transaction-update-full.xml
similarity index 100%
rename from tests/suites/default/post/Transaction-update-full.xml
rename to tests/functionaltests/suites/default/post/Transaction-update-full.xml
diff --git a/tests/suites/default/post/Transaction-update-recordproperty.xml b/tests/functionaltests/suites/default/post/Transaction-update-recordproperty.xml
similarity index 100%
rename from tests/suites/default/post/Transaction-update-recordproperty.xml
rename to tests/functionaltests/suites/default/post/Transaction-update-recordproperty.xml
diff --git a/tests/suites/dif/default.cfg b/tests/functionaltests/suites/dif/default.cfg
similarity index 100%
rename from tests/suites/dif/default.cfg
rename to tests/functionaltests/suites/dif/default.cfg
diff --git a/tests/expected/suites_dif_post_DescribeRecord.xml b/tests/functionaltests/suites/dif/expected/post_DescribeRecord.xml
similarity index 100%
rename from tests/expected/suites_dif_post_DescribeRecord.xml
rename to tests/functionaltests/suites/dif/expected/post_DescribeRecord.xml
diff --git a/tests/expected/suites_dif_post_GetCapabilities.xml b/tests/functionaltests/suites/dif/expected/post_GetCapabilities.xml
similarity index 100%
rename from tests/expected/suites_dif_post_GetCapabilities.xml
rename to tests/functionaltests/suites/dif/expected/post_GetCapabilities.xml
diff --git a/tests/expected/suites_dif_post_GetRecords-filter-bbox.xml b/tests/functionaltests/suites/dif/expected/post_GetRecords-filter-bbox.xml
similarity index 100%
rename from tests/expected/suites_dif_post_GetRecords-filter-bbox.xml
rename to tests/functionaltests/suites/dif/expected/post_GetRecords-filter-bbox.xml
diff --git a/tests/suites/dif/post/DescribeRecord.xml b/tests/functionaltests/suites/dif/post/DescribeRecord.xml
similarity index 100%
rename from tests/suites/dif/post/DescribeRecord.xml
rename to tests/functionaltests/suites/dif/post/DescribeRecord.xml
diff --git a/tests/suites/dif/post/GetCapabilities.xml b/tests/functionaltests/suites/dif/post/GetCapabilities.xml
similarity index 100%
rename from tests/suites/dif/post/GetCapabilities.xml
rename to tests/functionaltests/suites/dif/post/GetCapabilities.xml
diff --git a/tests/suites/dif/post/GetRecords-filter-bbox.xml b/tests/functionaltests/suites/dif/post/GetRecords-filter-bbox.xml
similarity index 100%
rename from tests/suites/dif/post/GetRecords-filter-bbox.xml
rename to tests/functionaltests/suites/dif/post/GetRecords-filter-bbox.xml
diff --git a/tests/suites/ebrim/default.cfg b/tests/functionaltests/suites/ebrim/default.cfg
similarity index 100%
rename from tests/suites/ebrim/default.cfg
rename to tests/functionaltests/suites/ebrim/default.cfg
diff --git a/tests/expected/suites_ebrim_post_DescribeRecord.xml b/tests/functionaltests/suites/ebrim/expected/post_DescribeRecord.xml
similarity index 100%
rename from tests/expected/suites_ebrim_post_DescribeRecord.xml
rename to tests/functionaltests/suites/ebrim/expected/post_DescribeRecord.xml
diff --git a/tests/expected/suites_ebrim_post_GetCapabilities.xml b/tests/functionaltests/suites/ebrim/expected/post_GetCapabilities.xml
similarity index 100%
rename from tests/expected/suites_ebrim_post_GetCapabilities.xml
rename to tests/functionaltests/suites/ebrim/expected/post_GetCapabilities.xml
diff --git a/tests/expected/suites_ebrim_post_GetRecords-filter-bbox-full.xml b/tests/functionaltests/suites/ebrim/expected/post_GetRecords-filter-bbox-full.xml
similarity index 100%
rename from tests/expected/suites_ebrim_post_GetRecords-filter-bbox-full.xml
rename to tests/functionaltests/suites/ebrim/expected/post_GetRecords-filter-bbox-full.xml
diff --git a/tests/expected/suites_ebrim_post_GetRecords-filter-bbox.xml b/tests/functionaltests/suites/ebrim/expected/post_GetRecords-filter-bbox.xml
similarity index 100%
rename from tests/expected/suites_ebrim_post_GetRecords-filter-bbox.xml
rename to tests/functionaltests/suites/ebrim/expected/post_GetRecords-filter-bbox.xml
diff --git a/tests/suites/ebrim/post/DescribeRecord.xml b/tests/functionaltests/suites/ebrim/post/DescribeRecord.xml
similarity index 100%
rename from tests/suites/ebrim/post/DescribeRecord.xml
rename to tests/functionaltests/suites/ebrim/post/DescribeRecord.xml
diff --git a/tests/suites/ebrim/post/GetCapabilities.xml b/tests/functionaltests/suites/ebrim/post/GetCapabilities.xml
similarity index 100%
rename from tests/suites/ebrim/post/GetCapabilities.xml
rename to tests/functionaltests/suites/ebrim/post/GetCapabilities.xml
diff --git a/tests/suites/ebrim/post/GetRecords-filter-bbox-full.xml b/tests/functionaltests/suites/ebrim/post/GetRecords-filter-bbox-full.xml
similarity index 100%
rename from tests/suites/ebrim/post/GetRecords-filter-bbox-full.xml
rename to tests/functionaltests/suites/ebrim/post/GetRecords-filter-bbox-full.xml
diff --git a/tests/suites/ebrim/post/GetRecords-filter-bbox.xml b/tests/functionaltests/suites/ebrim/post/GetRecords-filter-bbox.xml
similarity index 100%
rename from tests/suites/ebrim/post/GetRecords-filter-bbox.xml
rename to tests/functionaltests/suites/ebrim/post/GetRecords-filter-bbox.xml
diff --git a/tests/suites/fgdc/default.cfg b/tests/functionaltests/suites/fgdc/default.cfg
similarity index 100%
rename from tests/suites/fgdc/default.cfg
rename to tests/functionaltests/suites/fgdc/default.cfg
diff --git a/tests/expected/suites_fgdc_post_DescribeRecord.xml b/tests/functionaltests/suites/fgdc/expected/post_DescribeRecord.xml
similarity index 100%
rename from tests/expected/suites_fgdc_post_DescribeRecord.xml
rename to tests/functionaltests/suites/fgdc/expected/post_DescribeRecord.xml
diff --git a/tests/expected/suites_fgdc_post_GetCapabilities.xml b/tests/functionaltests/suites/fgdc/expected/post_GetCapabilities.xml
similarity index 100%
rename from tests/expected/suites_fgdc_post_GetCapabilities.xml
rename to tests/functionaltests/suites/fgdc/expected/post_GetCapabilities.xml
diff --git a/tests/expected/suites_fgdc_post_GetRecords-filter-bbox.xml b/tests/functionaltests/suites/fgdc/expected/post_GetRecords-filter-bbox.xml
similarity index 100%
rename from tests/expected/suites_fgdc_post_GetRecords-filter-bbox.xml
rename to tests/functionaltests/suites/fgdc/expected/post_GetRecords-filter-bbox.xml
diff --git a/tests/suites/fgdc/post/DescribeRecord.xml b/tests/functionaltests/suites/fgdc/post/DescribeRecord.xml
similarity index 100%
rename from tests/suites/fgdc/post/DescribeRecord.xml
rename to tests/functionaltests/suites/fgdc/post/DescribeRecord.xml
diff --git a/tests/suites/fgdc/post/GetCapabilities.xml b/tests/functionaltests/suites/fgdc/post/GetCapabilities.xml
similarity index 100%
rename from tests/suites/fgdc/post/GetCapabilities.xml
rename to tests/functionaltests/suites/fgdc/post/GetCapabilities.xml
diff --git a/tests/suites/fgdc/post/GetRecords-filter-bbox.xml b/tests/functionaltests/suites/fgdc/post/GetRecords-filter-bbox.xml
similarity index 100%
rename from tests/suites/fgdc/post/GetRecords-filter-bbox.xml
rename to tests/functionaltests/suites/fgdc/post/GetRecords-filter-bbox.xml
diff --git a/tests/suites/gm03/default.cfg b/tests/functionaltests/suites/gm03/default.cfg
similarity index 100%
rename from tests/suites/gm03/default.cfg
rename to tests/functionaltests/suites/gm03/default.cfg
diff --git a/tests/expected/suites_gm03_post_GetCapabilities.xml b/tests/functionaltests/suites/gm03/expected/post_GetCapabilities.xml
similarity index 100%
rename from tests/expected/suites_gm03_post_GetCapabilities.xml
rename to tests/functionaltests/suites/gm03/expected/post_GetCapabilities.xml
diff --git a/tests/expected/suites_gm03_post_GetRecords-filter-bbox.xml b/tests/functionaltests/suites/gm03/expected/post_GetRecords-filter-bbox.xml
similarity index 100%
rename from tests/expected/suites_gm03_post_GetRecords-filter-bbox.xml
rename to tests/functionaltests/suites/gm03/expected/post_GetRecords-filter-bbox.xml
diff --git a/tests/suites/gm03/post/GetCapabilities.xml b/tests/functionaltests/suites/gm03/post/GetCapabilities.xml
similarity index 100%
rename from tests/suites/gm03/post/GetCapabilities.xml
rename to tests/functionaltests/suites/gm03/post/GetCapabilities.xml
diff --git a/tests/suites/gm03/post/GetRecords-filter-bbox.xml b/tests/functionaltests/suites/gm03/post/GetRecords-filter-bbox.xml
similarity index 100%
rename from tests/suites/gm03/post/GetRecords-filter-bbox.xml
rename to tests/functionaltests/suites/gm03/post/GetRecords-filter-bbox.xml
diff --git a/tests/suites/harvesting/default.cfg b/tests/functionaltests/suites/harvesting/default.cfg
similarity index 100%
rename from tests/suites/harvesting/default.cfg
rename to tests/functionaltests/suites/harvesting/default.cfg
diff --git a/tests/expected/suites_harvesting_get_Exception-Harvest-invalid-resourcetype.xml b/tests/functionaltests/suites/harvesting/expected/get_Exception-Harvest-invalid-resourcetype.xml
similarity index 67%
rename from tests/expected/suites_harvesting_get_Exception-Harvest-invalid-resourcetype.xml
rename to tests/functionaltests/suites/harvesting/expected/get_Exception-Harvest-invalid-resourcetype.xml
index 911ecc1..4e1e40c 100644
--- a/tests/expected/suites_harvesting_get_Exception-Harvest-invalid-resourcetype.xml
+++ b/tests/functionaltests/suites/harvesting/expected/get_Exception-Harvest-invalid-resourcetype.xml
@@ -2,6 +2,6 @@
 <!-- PYCSW_VERSION -->
 <ows:ExceptionReport xmlns:csw="http://www.opengis.net/cat/csw/2.0.2" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dct="http://purl.org/dc/terms/" xmlns:gmd="http://www.isotc211.org/2005/gmd" xmlns:gml="http://www.opengis.net/gml" xmlns:ows="http://www.opengis.net/ows" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" language="en-US" version="1.2.0" xsi:schemaLocation="http://www.opengis.net/ows http://schemas.opengis.net/ows/1.0.0/ow [...]
   <ows:Exception exceptionCode="InvalidParameterValue" locator="resourcetype">
-    <ows:ExceptionText>Invalid resource type parameter: http://www.opengis.net/wms1234.            Allowable resourcetype values: http://www.opengis.net/cat/csw/2.0.2,http://www.opengis.net/cat/csw/3.0,http://www.opengis.net/wms,http://www.opengis.net/wmts/1.0,http://www.opengis.net/wfs,http://www.opengis.net/wcs,http://www.opengis.net/wps/1.0.0,http://www.opengis.net/sos/1.0,http://www.opengis.net/sos/2.0,http://www.isotc211.org/2005/gmi,urn:geoss:waf,http://www.interlis.ch/INTERLIS2.3, [...]
+    <ows:ExceptionText>Invalid resource type parameter: http://www.opengis.net/wms1234.            Allowable resourcetype values: http://www.opengis.net/cat/csw/2.0.2,http://www.opengis.net/cat/csw/3.0,http://www.opengis.net/wms,http://www.opengis.net/wmts/1.0,http://www.opengis.net/wfs,http://www.opengis.net/wfs/2.0,http://www.opengis.net/wcs,http://www.opengis.net/wps/1.0.0,http://www.opengis.net/sos/1.0,http://www.opengis.net/sos/2.0,http://www.isotc211.org/2005/gmi,urn:geoss:waf,http [...]
   </ows:Exception>
 </ows:ExceptionReport>
diff --git a/tests/expected/suites_harvesting_get_Exception-Harvest-missing-resourcetype.xml b/tests/functionaltests/suites/harvesting/expected/get_Exception-Harvest-missing-resourcetype.xml
similarity index 100%
rename from tests/expected/suites_harvesting_get_Exception-Harvest-missing-resourcetype.xml
rename to tests/functionaltests/suites/harvesting/expected/get_Exception-Harvest-missing-resourcetype.xml
diff --git a/tests/expected/suites_harvesting_get_Exception-Harvest-missing-source.xml b/tests/functionaltests/suites/harvesting/expected/get_Exception-Harvest-missing-source.xml
similarity index 100%
rename from tests/expected/suites_harvesting_get_Exception-Harvest-missing-source.xml
rename to tests/functionaltests/suites/harvesting/expected/get_Exception-Harvest-missing-source.xml
diff --git a/tests/expected/suites_harvesting_get_Exception-Harvest-waf-bad-value.xml b/tests/functionaltests/suites/harvesting/expected/get_Exception-Harvest-waf-bad-value.xml
similarity index 100%
rename from tests/expected/suites_harvesting_get_Exception-Harvest-waf-bad-value.xml
rename to tests/functionaltests/suites/harvesting/expected/get_Exception-Harvest-waf-bad-value.xml
diff --git a/tests/expected/suites_harvesting_get_Exception-Harvest-waf-no-records-found.xml b/tests/functionaltests/suites/harvesting/expected/get_Exception-Harvest-waf-no-records-found.xml
similarity index 100%
rename from tests/expected/suites_harvesting_get_Exception-Harvest-waf-no-records-found.xml
rename to tests/functionaltests/suites/harvesting/expected/get_Exception-Harvest-waf-no-records-found.xml
diff --git a/tests/expected/suites_harvesting_post_Clear-000-delete-all.xml b/tests/functionaltests/suites/harvesting/expected/post_Clear-000-delete-all.xml
similarity index 100%
rename from tests/expected/suites_harvesting_post_Clear-000-delete-all.xml
rename to tests/functionaltests/suites/harvesting/expected/post_Clear-000-delete-all.xml
diff --git a/tests/expected/suites_harvesting_post_Exception-Havest-csw-404.xml b/tests/functionaltests/suites/harvesting/expected/post_Exception-Havest-csw-404.xml
similarity index 100%
rename from tests/expected/suites_harvesting_post_Exception-Havest-csw-404.xml
rename to tests/functionaltests/suites/harvesting/expected/post_Exception-Havest-csw-404.xml
diff --git a/tests/expected/suites_harvesting_post_GetCapabilities.xml b/tests/functionaltests/suites/harvesting/expected/post_GetCapabilities.xml
similarity index 99%
rename from tests/expected/suites_harvesting_post_GetCapabilities.xml
rename to tests/functionaltests/suites/harvesting/expected/post_GetCapabilities.xml
index 3d8fef7..c7b5eea 100644
--- a/tests/expected/suites_harvesting_post_GetCapabilities.xml
+++ b/tests/functionaltests/suites/harvesting/expected/post_GetCapabilities.xml
@@ -259,6 +259,7 @@
         <ows:Value>http://www.opengis.net/sos/2.0</ows:Value>
         <ows:Value>http://www.opengis.net/wcs</ows:Value>
         <ows:Value>http://www.opengis.net/wfs</ows:Value>
+        <ows:Value>http://www.opengis.net/wfs/2.0</ows:Value>
         <ows:Value>http://www.opengis.net/wms</ows:Value>
         <ows:Value>http://www.opengis.net/wmts/1.0</ows:Value>
         <ows:Value>http://www.opengis.net/wps/1.0.0</ows:Value>
@@ -284,6 +285,7 @@
         <ows:Value>http://www.opengis.net/sos/2.0</ows:Value>
         <ows:Value>http://www.opengis.net/wcs</ows:Value>
         <ows:Value>http://www.opengis.net/wfs</ows:Value>
+        <ows:Value>http://www.opengis.net/wfs/2.0</ows:Value>
         <ows:Value>http://www.opengis.net/wms</ows:Value>
         <ows:Value>http://www.opengis.net/wmts/1.0</ows:Value>
         <ows:Value>http://www.opengis.net/wps/1.0.0</ows:Value>
diff --git a/tests/expected/suites_manager_post_GetDomain-parameter.xml b/tests/functionaltests/suites/harvesting/expected/post_GetDomain-parameter.xml
similarity index 96%
rename from tests/expected/suites_manager_post_GetDomain-parameter.xml
rename to tests/functionaltests/suites/harvesting/expected/post_GetDomain-parameter.xml
index a681d2a..b47402c 100644
--- a/tests/expected/suites_manager_post_GetDomain-parameter.xml
+++ b/tests/functionaltests/suites/harvesting/expected/post_GetDomain-parameter.xml
@@ -16,6 +16,7 @@
       <csw:Value>http://www.opengis.net/sos/2.0</csw:Value>
       <csw:Value>http://www.opengis.net/wcs</csw:Value>
       <csw:Value>http://www.opengis.net/wfs</csw:Value>
+      <csw:Value>http://www.opengis.net/wfs/2.0</csw:Value>
       <csw:Value>http://www.opengis.net/wms</csw:Value>
       <csw:Value>http://www.opengis.net/wmts/1.0</csw:Value>
       <csw:Value>http://www.opengis.net/wps/1.0.0</csw:Value>
diff --git a/tests/expected/suites_harvesting_post_Harvest-csw-iso.xml b/tests/functionaltests/suites/harvesting/expected/post_Harvest-csw-iso.xml
similarity index 100%
rename from tests/expected/suites_harvesting_post_Harvest-csw-iso.xml
rename to tests/functionaltests/suites/harvesting/expected/post_Harvest-csw-iso.xml
diff --git a/tests/expected/suites_harvesting_post_Harvest-csw-run1.xml b/tests/functionaltests/suites/harvesting/expected/post_Harvest-csw-run1.xml
similarity index 100%
rename from tests/expected/suites_harvesting_post_Harvest-csw-run1.xml
rename to tests/functionaltests/suites/harvesting/expected/post_Harvest-csw-run1.xml
diff --git a/tests/expected/suites_harvesting_post_Harvest-csw-run2.xml b/tests/functionaltests/suites/harvesting/expected/post_Harvest-csw-run2.xml
similarity index 100%
rename from tests/expected/suites_harvesting_post_Harvest-csw-run2.xml
rename to tests/functionaltests/suites/harvesting/expected/post_Harvest-csw-run2.xml
diff --git a/tests/expected/suites_harvesting_post_Harvest-dc.xml b/tests/functionaltests/suites/harvesting/expected/post_Harvest-dc.xml
similarity index 100%
rename from tests/expected/suites_harvesting_post_Harvest-dc.xml
rename to tests/functionaltests/suites/harvesting/expected/post_Harvest-dc.xml
diff --git a/tests/expected/suites_harvesting_post_Harvest-fgdc.xml b/tests/functionaltests/suites/harvesting/expected/post_Harvest-fgdc.xml
similarity index 100%
rename from tests/expected/suites_harvesting_post_Harvest-fgdc.xml
rename to tests/functionaltests/suites/harvesting/expected/post_Harvest-fgdc.xml
diff --git a/tests/expected/suites_harvesting_post_Harvest-iso.xml b/tests/functionaltests/suites/harvesting/expected/post_Harvest-iso.xml
similarity index 100%
rename from tests/expected/suites_harvesting_post_Harvest-iso.xml
rename to tests/functionaltests/suites/harvesting/expected/post_Harvest-iso.xml
diff --git a/tests/expected/suites_harvesting_post_Harvest-rdf.xml b/tests/functionaltests/suites/harvesting/expected/post_Harvest-rdf.xml
similarity index 100%
rename from tests/expected/suites_harvesting_post_Harvest-rdf.xml
rename to tests/functionaltests/suites/harvesting/expected/post_Harvest-rdf.xml
diff --git a/tests/expected/suites_harvesting_post_Harvest-sos100.xml b/tests/functionaltests/suites/harvesting/expected/post_Harvest-sos100.xml
similarity index 100%
rename from tests/expected/suites_harvesting_post_Harvest-sos100.xml
rename to tests/functionaltests/suites/harvesting/expected/post_Harvest-sos100.xml
diff --git a/tests/expected/suites_harvesting_post_Harvest-sos200.xml b/tests/functionaltests/suites/harvesting/expected/post_Harvest-sos200.xml
similarity index 100%
rename from tests/expected/suites_harvesting_post_Harvest-sos200.xml
rename to tests/functionaltests/suites/harvesting/expected/post_Harvest-sos200.xml
diff --git a/tests/expected/suites_harvesting_post_Harvest-waf.xml b/tests/functionaltests/suites/harvesting/expected/post_Harvest-waf.xml
similarity index 100%
rename from tests/expected/suites_harvesting_post_Harvest-waf.xml
rename to tests/functionaltests/suites/harvesting/expected/post_Harvest-waf.xml
diff --git a/tests/expected/suites_harvesting_post_Harvest-wcs.xml b/tests/functionaltests/suites/harvesting/expected/post_Harvest-wcs.xml
similarity index 100%
rename from tests/expected/suites_harvesting_post_Harvest-wcs.xml
rename to tests/functionaltests/suites/harvesting/expected/post_Harvest-wcs.xml
diff --git a/tests/expected/suites_harvesting_post_Harvest-wfs.xml b/tests/functionaltests/suites/harvesting/expected/post_Harvest-wfs110.xml
similarity index 100%
copy from tests/expected/suites_harvesting_post_Harvest-wfs.xml
copy to tests/functionaltests/suites/harvesting/expected/post_Harvest-wfs110.xml
diff --git a/tests/functionaltests/suites/harvesting/expected/post_Harvest-wfs200.xml b/tests/functionaltests/suites/harvesting/expected/post_Harvest-wfs200.xml
new file mode 100644
index 0000000..d73153e
--- /dev/null
+++ b/tests/functionaltests/suites/harvesting/expected/post_Harvest-wfs200.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- PYCSW_VERSION -->
+<csw:HarvestResponse xmlns:csw="http://www.opengis.net/cat/csw/2.0.2" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dct="http://purl.org/dc/terms/" xmlns:gmd="http://www.isotc211.org/2005/gmd" xmlns:gml="http://www.opengis.net/gml" xmlns:ows="http://www.opengis.net/ows" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/cat/csw/2.0.2 http://schemas.opengis.net/csw/2.0.2/CSW-publication.xsd">
+  <csw:TransactionResponse version="2.0.2">
+    <csw:TransactionSummary>
+      <csw:totalInserted>11</csw:totalInserted>
+      <csw:totalUpdated>0</csw:totalUpdated>
+      <csw:totalDeleted>0</csw:totalDeleted>
+    </csw:TransactionSummary>
+    <csw:InsertResult>
+      <csw:BriefRecord>
+        <dc:identifier>PYCSW_IDENTIFIER</dc:identifier>
+        <dc:title>CERA_CERA_TechClasses_WGS84</dc:title>
+      </csw:BriefRecord>
+      <csw:BriefRecord>
+        <dc:identifier>PYCSW_IDENTIFIER-CERA_CERA_TechClasses_WGS84:MBIE_Technical_Classes_WGS84_2012-08-16</dc:identifier>
+        <dc:title>MBIE_Technical_Classes_WGS84_2012-08-16</dc:title>
+      </csw:BriefRecord>
+      <csw:BriefRecord>
+        <dc:identifier>PYCSW_IDENTIFIER-CERA_CERA_TechClasses_WGS84:MBIE_Technical_Classes_WGS84_2012-05-18</dc:identifier>
+        <dc:title>MBIE_Technical_Classes_WGS84_2012-05-18</dc:title>
+      </csw:BriefRecord>
+      <csw:BriefRecord>
+        <dc:identifier>PYCSW_IDENTIFIER-CERA_CERA_TechClasses_WGS84:MBIE_Technical_Classes_WGS84_2013-12-04</dc:identifier>
+        <dc:title>MBIE_Technical_Classes_WGS84_2013-12-04</dc:title>
+      </csw:BriefRecord>
+      <csw:BriefRecord>
+        <dc:identifier>PYCSW_IDENTIFIER-CERA_CERA_TechClasses_WGS84:MBIE_Technical_Classes_WGS84_2011-10-28</dc:identifier>
+        <dc:title>MBIE_Technical_Classes_WGS84_2011-10-28</dc:title>
+      </csw:BriefRecord>
+      <csw:BriefRecord>
+        <dc:identifier>PYCSW_IDENTIFIER-CERA_CERA_TechClasses_WGS84:MBIE_Technical_Classes_WGS84_2012-02-10</dc:identifier>
+        <dc:title>MBIE_Technical_Classes_WGS84_2012-02-10</dc:title>
+      </csw:BriefRecord>
+      <csw:BriefRecord>
+        <dc:identifier>PYCSW_IDENTIFIER-CERA_CERA_TechClasses_WGS84:MBIE_Technical_Classes_WGS84_2012-09-14</dc:identifier>
+        <dc:title>MBIE_Technical_Classes_WGS84_2012-09-14</dc:title>
+      </csw:BriefRecord>
+      <csw:BriefRecord>
+        <dc:identifier>PYCSW_IDENTIFIER-CERA_CERA_TechClasses_WGS84:MBIE_Technical_Classes_WGS84_2012-03-23</dc:identifier>
+        <dc:title>MBIE_Technical_Classes_WGS84_2012-03-23</dc:title>
+      </csw:BriefRecord>
+      <csw:BriefRecord>
+        <dc:identifier>PYCSW_IDENTIFIER-CERA_CERA_TechClasses_WGS84:MBIE_Technical_Classes_WGS84_2011-11-17</dc:identifier>
+        <dc:title>MBIE_Technical_Classes_WGS84_2011-11-17</dc:title>
+      </csw:BriefRecord>
+      <csw:BriefRecord>
+        <dc:identifier>PYCSW_IDENTIFIER-CERA_CERA_TechClasses_WGS84:MBIE_Technical_Classes_WGS84_2012-08-24</dc:identifier>
+        <dc:title>MBIE_Technical_Classes_WGS84_2012-08-24</dc:title>
+      </csw:BriefRecord>
+      <csw:BriefRecord>
+        <dc:identifier>PYCSW_IDENTIFIER-CERA_CERA_TechClasses_WGS84:MBIE_Technical_Classes_WGS84_2012-10-31</dc:identifier>
+        <dc:title>MBIE_Technical_Classes_WGS84_2012-10-31</dc:title>
+      </csw:BriefRecord>
+    </csw:InsertResult>
+  </csw:TransactionResponse>
+</csw:HarvestResponse>
diff --git a/tests/expected/suites_harvesting_post_Harvest-wms-run1.xml b/tests/functionaltests/suites/harvesting/expected/post_Harvest-wms-run1.xml
similarity index 100%
rename from tests/expected/suites_harvesting_post_Harvest-wms-run1.xml
rename to tests/functionaltests/suites/harvesting/expected/post_Harvest-wms-run1.xml
diff --git a/tests/expected/suites_harvesting_post_Harvest-wms-run2.xml b/tests/functionaltests/suites/harvesting/expected/post_Harvest-wms-run2.xml
similarity index 100%
rename from tests/expected/suites_harvesting_post_Harvest-wms-run2.xml
rename to tests/functionaltests/suites/harvesting/expected/post_Harvest-wms-run2.xml
diff --git a/tests/expected/suites_harvesting_post_Harvest-wfs.xml b/tests/functionaltests/suites/harvesting/expected/post_Harvest-wmts.xml
similarity index 55%
rename from tests/expected/suites_harvesting_post_Harvest-wfs.xml
rename to tests/functionaltests/suites/harvesting/expected/post_Harvest-wmts.xml
index 96ec6fe..372bad7 100644
--- a/tests/expected/suites_harvesting_post_Harvest-wfs.xml
+++ b/tests/functionaltests/suites/harvesting/expected/post_Harvest-wmts.xml
@@ -3,34 +3,42 @@
 <csw:HarvestResponse xmlns:csw="http://www.opengis.net/cat/csw/2.0.2" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dct="http://purl.org/dc/terms/" xmlns:gmd="http://www.isotc211.org/2005/gmd" xmlns:gml="http://www.opengis.net/gml" xmlns:ows="http://www.opengis.net/ows" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/cat/csw/2.0.2 http://schemas.opengis.net/csw/2.0.2/CSW-publication.xsd">
   <csw:TransactionResponse version="2.0.2">
     <csw:TransactionSummary>
-      <csw:totalInserted>6</csw:totalInserted>
+      <csw:totalInserted>8</csw:totalInserted>
       <csw:totalUpdated>0</csw:totalUpdated>
       <csw:totalDeleted>0</csw:totalDeleted>
     </csw:TransactionSummary>
     <csw:InsertResult>
       <csw:BriefRecord>
         <dc:identifier>PYCSW_IDENTIFIER</dc:identifier>
-        <dc:title>GeoServer Web Feature Service</dc:title>
+        <dc:title>Web Map Tile Service</dc:title>
       </csw:BriefRecord>
       <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-geoss_water_sba:Reservoir</dc:identifier>
-        <dc:title>Reservoir</dc:title>
+        <dc:identifier>PYCSW_IDENTIFIER-flwbplmzk</dc:identifier>
+        <dc:title>Flächenwidmungs- und Bebauungsplan</dc:title>
       </csw:BriefRecord>
       <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-geoss_water_sba:glwd_1</dc:identifier>
-        <dc:title>glwd_1</dc:title>
+        <dc:identifier>PYCSW_IDENTIFIER-lb</dc:identifier>
+        <dc:title>Luftbild</dc:title>
       </csw:BriefRecord>
       <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-geoss_water_sba:Dams</dc:identifier>
-        <dc:title>Dams</dc:title>
+        <dc:identifier>PYCSW_IDENTIFIER-lb2014</dc:identifier>
+        <dc:title>Luftbild 2014</dc:title>
       </csw:BriefRecord>
       <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-geoss_water_sba:glwd_2</dc:identifier>
-        <dc:title>glwd_2</dc:title>
+        <dc:identifier>PYCSW_IDENTIFIER-beschriftung</dc:identifier>
+        <dc:title>Beschriftung</dc:title>
       </csw:BriefRecord>
       <csw:BriefRecord>
-        <dc:identifier>PYCSW_IDENTIFIER-geoss_water_sba:Lakes</dc:identifier>
-        <dc:title>Lakes</dc:title>
+        <dc:identifier>PYCSW_IDENTIFIER-lb1938</dc:identifier>
+        <dc:title>Luftbild 1938</dc:title>
+      </csw:BriefRecord>
+      <csw:BriefRecord>
+        <dc:identifier>PYCSW_IDENTIFIER-fmzk</dc:identifier>
+        <dc:title>MZK Flächen</dc:title>
+      </csw:BriefRecord>
+      <csw:BriefRecord>
+        <dc:identifier>PYCSW_IDENTIFIER-lb1956</dc:identifier>
+        <dc:title>Luftbild 1956</dc:title>
       </csw:BriefRecord>
     </csw:InsertResult>
   </csw:TransactionResponse>
diff --git a/tests/functionaltests/suites/harvesting/expected/post_Harvest-wps.xml b/tests/functionaltests/suites/harvesting/expected/post_Harvest-wps.xml
new file mode 100644
index 0000000..12381ec
--- /dev/null
+++ b/tests/functionaltests/suites/harvesting/expected/post_Harvest-wps.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- PYCSW_VERSION -->
+<csw:HarvestResponse xmlns:csw="http://www.opengis.net/cat/csw/2.0.2" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dct="http://purl.org/dc/terms/" xmlns:gmd="http://www.isotc211.org/2005/gmd" xmlns:gml="http://www.opengis.net/gml" xmlns:ows="http://www.opengis.net/ows" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/cat/csw/2.0.2 http://schemas.opengis.net/csw/2.0.2/CSW-publication.xsd">
+  <csw:TransactionResponse version="2.0.2">
+    <csw:TransactionSummary>
+      <csw:totalInserted>11</csw:totalInserted>
+      <csw:totalUpdated>0</csw:totalUpdated>
+      <csw:totalDeleted>0</csw:totalDeleted>
+    </csw:TransactionSummary>
+    <csw:InsertResult>
+      <csw:BriefRecord>
+        <dc:identifier>PYCSW_IDENTIFIER</dc:identifier>
+        <dc:title>Geo Data Portal WPS Implementation</dc:title>
+      </csw:BriefRecord>
+      <csw:BriefRecord>
+        <dc:identifier>PYCSW_IDENTIFIER-gov.usgs.cida.gdp.wps.algorithm.filemanagement.CreateNewShapefileDataStore</dc:identifier>
+        <dc:title>gov.usgs.cida.gdp.wps.algorithm.filemanagement.CreateNewShapefileDataStore</dc:title>
+      </csw:BriefRecord>
+      <csw:BriefRecord>
+        <dc:identifier>PYCSW_IDENTIFIER-gov.usgs.cida.gdp.wps.algorithm.discovery.GetGridTimeRange</dc:identifier>
+        <dc:title>Get Grid Time Range</dc:title>
+      </csw:BriefRecord>
+      <csw:BriefRecord>
+        <dc:identifier>PYCSW_IDENTIFIER-gov.usgs.cida.gdp.wps.algorithm.filemanagement.ReceiveFiles</dc:identifier>
+        <dc:title>gov.usgs.cida.gdp.wps.algorithm.filemanagement.ReceiveFiles</dc:title>
+      </csw:BriefRecord>
+      <csw:BriefRecord>
+        <dc:identifier>PYCSW_IDENTIFIER-gov.usgs.cida.gdp.wps.algorithm.discovery.GetWcsCoverages</dc:identifier>
+        <dc:title>gov.usgs.cida.gdp.wps.algorithm.discovery.GetWcsCoverages</dc:title>
+      </csw:BriefRecord>
+      <csw:BriefRecord>
+        <dc:identifier>PYCSW_IDENTIFIER-gov.usgs.cida.gdp.wps.algorithm.filemanagement.GetWatersGeom</dc:identifier>
+        <dc:title>gov.usgs.cida.gdp.wps.algorithm.filemanagement.GetWatersGeom</dc:title>
+      </csw:BriefRecord>
+      <csw:BriefRecord>
+        <dc:identifier>PYCSW_IDENTIFIER-gov.usgs.cida.gdp.wps.algorithm.communication.GeoserverManagementAlgorithm</dc:identifier>
+        <dc:title>gov.usgs.cida.gdp.wps.algorithm.communication.GeoserverManagementAlgorithm</dc:title>
+      </csw:BriefRecord>
+      <csw:BriefRecord>
+        <dc:identifier>PYCSW_IDENTIFIER-gov.usgs.cida.gdp.wps.algorithm.communication.EmailWhenFinishedAlgorithm</dc:identifier>
+        <dc:title>gov.usgs.cida.gdp.wps.algorithm.communication.EmailWhenFinishedAlgorithm</dc:title>
+      </csw:BriefRecord>
+      <csw:BriefRecord>
+        <dc:identifier>PYCSW_IDENTIFIER-gov.usgs.cida.gdp.wps.algorithm.discovery.InterrogateDataset</dc:identifier>
+        <dc:title>Interogate Dataset URI</dc:title>
+      </csw:BriefRecord>
+      <csw:BriefRecord>
+        <dc:identifier>PYCSW_IDENTIFIER-gov.usgs.cida.gdp.wps.algorithm.discovery.ListOpendapGrids</dc:identifier>
+        <dc:title>List OpendDAP Grids</dc:title>
+      </csw:BriefRecord>
+      <csw:BriefRecord>
+        <dc:identifier>PYCSW_IDENTIFIER-gov.usgs.cida.gdp.wps.algorithm.discovery.CalculateWCSCoverageInfo</dc:identifier>
+        <dc:title>gov.usgs.cida.gdp.wps.algorithm.discovery.CalculateWCSCoverageInfo</dc:title>
+      </csw:BriefRecord>
+    </csw:InsertResult>
+  </csw:TransactionResponse>
+</csw:HarvestResponse>
diff --git a/tests/expected/suites_harvesting_post_Harvest-zzz-post-GetRecords-filter-ows-dc.xml b/tests/functionaltests/suites/harvesting/expected/post_Harvest-zzz-post-GetRecords-filter-ows-dc.xml
similarity index 99%
rename from tests/expected/suites_harvesting_post_Harvest-zzz-post-GetRecords-filter-ows-dc.xml
rename to tests/functionaltests/suites/harvesting/expected/post_Harvest-zzz-post-GetRecords-filter-ows-dc.xml
index 350b511..5957395 100644
--- a/tests/expected/suites_harvesting_post_Harvest-zzz-post-GetRecords-filter-ows-dc.xml
+++ b/tests/functionaltests/suites/harvesting/expected/post_Harvest-zzz-post-GetRecords-filter-ows-dc.xml
@@ -2,7 +2,7 @@
 <!-- PYCSW_VERSION -->
 <csw:GetRecordsResponse xmlns:csw="http://www.opengis.net/cat/csw/2.0.2" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dct="http://purl.org/dc/terms/" xmlns:gmd="http://www.isotc211.org/2005/gmd" xmlns:gml="http://www.opengis.net/gml" xmlns:ows="http://www.opengis.net/ows" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0.2" xsi:schemaLocation="http://www.opengis.net/cat/csw/2.0.2 http://schemas.opengis.net/csw/2.0.2/CSW-di [...]
   <csw:SearchStatus timestamp="PYCSW_TIMESTAMP"/>
-  <csw:SearchResults nextRecord="6" numberOfRecordsMatched="11" numberOfRecordsReturned="5" recordSchema="http://www.opengis.net/cat/csw/2.0.2" elementSet="full">
+  <csw:SearchResults nextRecord="6" numberOfRecordsMatched="12" numberOfRecordsReturned="5" recordSchema="http://www.opengis.net/cat/csw/2.0.2" elementSet="full">
     <csw:Record>
       <dc:identifier>PYCSW_IDENTIFIER</dc:identifier>
       <dc:title>pycsw Geospatial Catalogue OGC services demo</dc:title>
diff --git a/tests/expected/suites_harvesting_post_Harvest-zzz-post-GetRecords-filter-sos-abstract-dc.xml b/tests/functionaltests/suites/harvesting/expected/post_Harvest-zzz-post-GetRecords-filter-sos-abstract-dc.xml
similarity index 100%
rename from tests/expected/suites_harvesting_post_Harvest-zzz-post-GetRecords-filter-sos-abstract-dc.xml
rename to tests/functionaltests/suites/harvesting/expected/post_Harvest-zzz-post-GetRecords-filter-sos-abstract-dc.xml
diff --git a/tests/expected/suites_harvesting_post_Harvest-zzz-post-GetRecords-filter-sos-dc.xml b/tests/functionaltests/suites/harvesting/expected/post_Harvest-zzz-post-GetRecords-filter-sos-dc.xml
similarity index 100%
rename from tests/expected/suites_harvesting_post_Harvest-zzz-post-GetRecords-filter-sos-dc.xml
rename to tests/functionaltests/suites/harvesting/expected/post_Harvest-zzz-post-GetRecords-filter-sos-dc.xml
diff --git a/tests/expected/suites_harvesting_post_Harvest-zzz-post-GetRecords-filter-sos-iso.xml b/tests/functionaltests/suites/harvesting/expected/post_Harvest-zzz-post-GetRecords-filter-sos-iso.xml
similarity index 100%
rename from tests/expected/suites_harvesting_post_Harvest-zzz-post-GetRecords-filter-sos-iso.xml
rename to tests/functionaltests/suites/harvesting/expected/post_Harvest-zzz-post-GetRecords-filter-sos-iso.xml
diff --git a/tests/functionaltests/suites/harvesting/expected/post_Harvest-zzz-post-GetRecords-filter-wfs-iso.xml b/tests/functionaltests/suites/harvesting/expected/post_Harvest-zzz-post-GetRecords-filter-wfs-iso.xml
new file mode 100644
index 0000000..c264459
--- /dev/null
+++ b/tests/functionaltests/suites/harvesting/expected/post_Harvest-zzz-post-GetRecords-filter-wfs-iso.xml
@@ -0,0 +1,1041 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- PYCSW_VERSION -->
+<csw:GetRecordsResponse xmlns:csw="http://www.opengis.net/cat/csw/2.0.2" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dct="http://purl.org/dc/terms/" xmlns:gco="http://www.isotc211.org/2005/gco" xmlns:gmd="http://www.isotc211.org/2005/gmd" xmlns:gml="http://www.opengis.net/gml" xmlns:ows="http://www.opengis.net/ows" xmlns:srv="http://www.isotc211.org/2005/srv" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XML [...]
+  <csw:SearchStatus timestamp="PYCSW_TIMESTAMP"/>
+  <csw:SearchResults nextRecord="0" numberOfRecordsMatched="2" numberOfRecordsReturned="2" recordSchema="http://www.isotc211.org/2005/gmd" elementSet="full">
+    <gmd:MD_Metadata xsi:schemaLocation="http://www.isotc211.org/2005/gmd http://schemas.opengis.net/csw/2.0.2/profiles/apiso/1.0.0/apiso.xsd">
+      <gmd:fileIdentifier>
+        <gco:CharacterString>PYCSW_IDENTIFIER</gco:CharacterString>
+      </gmd:fileIdentifier>
+      <gmd:language>
+        <gco:CharacterString/>
+      </gmd:language>
+      <gmd:hierarchyLevel>
+        <gmd:MD_ScopeCode codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#MD_ScopeCode" codeListValue="service" codeSpace="ISOTC211/19115">service</gmd:MD_ScopeCode>
+      </gmd:hierarchyLevel>
+      <gmd:contact>
+        <gmd:CI_ResponsibleParty>
+          <gmd:individualName>
+            <gco:CharacterString>Matt Austin</gco:CharacterString>
+          </gmd:individualName>
+          <gmd:organisationName>
+            <gco:CharacterString>National Oceanic and Atmospheric Administration</gco:CharacterString>
+          </gmd:organisationName>
+          <gmd:positionName>
+            <gco:CharacterString/>
+          </gmd:positionName>
+          <gmd:contactInfo>
+            <gmd:CI_Contact>
+              <gmd:phone>
+                <gmd:CI_Telephone>
+                  <gmd:voice>
+                    <gco:CharacterString/>
+                  </gmd:voice>
+                  <gmd:facsimile>
+                    <gco:CharacterString/>
+                  </gmd:facsimile>
+                </gmd:CI_Telephone>
+              </gmd:phone>
+              <gmd:address>
+                <gmd:CI_Address>
+                  <gmd:deliveryPoint>
+                    <gco:CharacterString/>
+                  </gmd:deliveryPoint>
+                  <gmd:city>
+                    <gco:CharacterString>Silver Spring</gco:CharacterString>
+                  </gmd:city>
+                  <gmd:administrativeArea>
+                    <gco:CharacterString>Maryland</gco:CharacterString>
+                  </gmd:administrativeArea>
+                  <gmd:postalCode>
+                    <gco:CharacterString>20910</gco:CharacterString>
+                  </gmd:postalCode>
+                  <gmd:country>
+                    <gco:CharacterString>USA</gco:CharacterString>
+                  </gmd:country>
+                  <gmd:electronicMailAddress>
+                    <gco:CharacterString/>
+                  </gmd:electronicMailAddress>
+                </gmd:CI_Address>
+              </gmd:address>
+            </gmd:CI_Contact>
+          </gmd:contactInfo>
+          <gmd:role>
+            <gmd:CI_RoleCode codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#CI_RoleCode" codeListValue="pointOfContact">pointOfContact</gmd:CI_RoleCode>
+          </gmd:role>
+        </gmd:CI_ResponsibleParty>
+      </gmd:contact>
+      <gmd:dateStamp>
+        <gco:Date/>
+      </gmd:dateStamp>
+      <gmd:metadataStandardName>
+        <gco:CharacterString>ISO19119</gco:CharacterString>
+      </gmd:metadataStandardName>
+      <gmd:metadataStandardVersion>
+        <gco:CharacterString>2005/PDAM 1</gco:CharacterString>
+      </gmd:metadataStandardVersion>
+      <gmd:identificationInfo>
+        <srv:SV_ServiceIdentification id="PYCSW_IDENTIFIER">
+          <gmd:citation>
+            <gmd:CI_Citation>
+              <gmd:title>
+                <gco:CharacterString>GeoServer Web Feature Service</gco:CharacterString>
+              </gmd:title>
+            </gmd:CI_Citation>
+          </gmd:citation>
+          <gmd:abstract>
+            <gco:CharacterString>This is the reference implementation of WFS 1.0.0 and WFS 1.1.0, supports all WFS operations including Transaction.</gco:CharacterString>
+          </gmd:abstract>
+          <gmd:descriptiveKeywords>
+            <gmd:MD_Keywords>
+              <gmd:keyword>
+                <gco:CharacterString>WFS</gco:CharacterString>
+              </gmd:keyword>
+              <gmd:keyword>
+                <gco:CharacterString>WMS</gco:CharacterString>
+              </gmd:keyword>
+              <gmd:keyword>
+                <gco:CharacterString>GEOSERVER</gco:CharacterString>
+              </gmd:keyword>
+            </gmd:MD_Keywords>
+          </gmd:descriptiveKeywords>
+          <gmd:language>
+            <gco:CharacterString/>
+          </gmd:language>
+          <srv:serviceType>
+            <gco:LocalName>OGC:WFS</gco:LocalName>
+          </srv:serviceType>
+          <srv:serviceTypeVersion>
+            <gco:CharacterString>1.1.0</gco:CharacterString>
+          </srv:serviceTypeVersion>
+          <srv:keywords>
+            <gmd:MD_Keywords>
+              <gmd:keyword>
+                <gco:CharacterString>WFS</gco:CharacterString>
+              </gmd:keyword>
+              <gmd:keyword>
+                <gco:CharacterString>WMS</gco:CharacterString>
+              </gmd:keyword>
+              <gmd:keyword>
+                <gco:CharacterString>GEOSERVER</gco:CharacterString>
+              </gmd:keyword>
+            </gmd:MD_Keywords>
+          </srv:keywords>
+          <srv:extent>
+            <gmd:EX_Extent>
+              <gmd:geographicElement>
+                <gmd:EX_GeographicBoundingBox>
+                  <gmd:westBoundLongitude>
+                    <gco:Decimal>-179.87</gco:Decimal>
+                  </gmd:westBoundLongitude>
+                  <gmd:eastBoundLongitude>
+                    <gco:Decimal>179.99</gco:Decimal>
+                  </gmd:eastBoundLongitude>
+                  <gmd:southBoundLatitude>
+                    <gco:Decimal>-54.61</gco:Decimal>
+                  </gmd:southBoundLatitude>
+                  <gmd:northBoundLatitude>
+                    <gco:Decimal>83.46</gco:Decimal>
+                  </gmd:northBoundLatitude>
+                </gmd:EX_GeographicBoundingBox>
+              </gmd:geographicElement>
+            </gmd:EX_Extent>
+          </srv:extent>
+          <srv:couplingType>
+            <srv:SV_CouplingType codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#SV_CouplingType" codeListValue="tight">tight</srv:SV_CouplingType>
+          </srv:couplingType>
+          <srv:coupledResource>
+            <srv:SV_CoupledResource>
+              <srv:operationName>
+                <gco:CharacterString>GetFeature</gco:CharacterString>
+              </srv:operationName>
+              <srv:identifier>
+                <gco:CharacterString>geoss_water_sba:Reservoir</gco:CharacterString>
+              </srv:identifier>
+            </srv:SV_CoupledResource>
+          </srv:coupledResource>
+          <srv:coupledResource>
+            <srv:SV_CoupledResource>
+              <srv:operationName>
+                <gco:CharacterString>GetFeature</gco:CharacterString>
+              </srv:operationName>
+              <srv:identifier>
+                <gco:CharacterString>geoss_water_sba:glwd_1</gco:CharacterString>
+              </srv:identifier>
+            </srv:SV_CoupledResource>
+          </srv:coupledResource>
+          <srv:coupledResource>
+            <srv:SV_CoupledResource>
+              <srv:operationName>
+                <gco:CharacterString>GetFeature</gco:CharacterString>
+              </srv:operationName>
+              <srv:identifier>
+                <gco:CharacterString>geoss_water_sba:Dams</gco:CharacterString>
+              </srv:identifier>
+            </srv:SV_CoupledResource>
+          </srv:coupledResource>
+          <srv:coupledResource>
+            <srv:SV_CoupledResource>
+              <srv:operationName>
+                <gco:CharacterString>GetFeature</gco:CharacterString>
+              </srv:operationName>
+              <srv:identifier>
+                <gco:CharacterString>geoss_water_sba:glwd_2</gco:CharacterString>
+              </srv:identifier>
+            </srv:SV_CoupledResource>
+          </srv:coupledResource>
+          <srv:coupledResource>
+            <srv:SV_CoupledResource>
+              <srv:operationName>
+                <gco:CharacterString>GetFeature</gco:CharacterString>
+              </srv:operationName>
+              <srv:identifier>
+                <gco:CharacterString>geoss_water_sba:Lakes</gco:CharacterString>
+              </srv:identifier>
+            </srv:SV_CoupledResource>
+          </srv:coupledResource>
+          <srv:containsOperations>
+            <srv:SV_OperationMetadata>
+              <srv:operationName>
+                <gco:CharacterString>GetCapabilities</gco:CharacterString>
+              </srv:operationName>
+              <srv:DCP>
+                <srv:DCPList codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#DCPList" codeListValue="HTTPGet">HTTPGet</srv:DCPList>
+              </srv:DCP>
+              <srv:DCP>
+                <srv:DCPList codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#DCPList" codeListValue="HTTPPost">HTTPPost</srv:DCPList>
+              </srv:DCP>
+              <srv:connectPoint>
+                <gmd:CI_OnlineResource>
+                  <gmd:linkage>
+                    <gmd:URL>http://services.ogc.noaa.gov/geoserver/geoss_water_sba/wfs</gmd:URL>
+                  </gmd:linkage>
+                </gmd:CI_OnlineResource>
+              </srv:connectPoint>
+            </srv:SV_OperationMetadata>
+          </srv:containsOperations>
+          <srv:containsOperations>
+            <srv:SV_OperationMetadata>
+              <srv:operationName>
+                <gco:CharacterString>DescribeFeatureType</gco:CharacterString>
+              </srv:operationName>
+              <srv:DCP>
+                <srv:DCPList codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#DCPList" codeListValue="HTTPGet">HTTPGet</srv:DCPList>
+              </srv:DCP>
+              <srv:DCP>
+                <srv:DCPList codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#DCPList" codeListValue="HTTPPost">HTTPPost</srv:DCPList>
+              </srv:DCP>
+              <srv:connectPoint>
+                <gmd:CI_OnlineResource>
+                  <gmd:linkage>
+                    <gmd:URL>http://services.ogc.noaa.gov/geoserver/geoss_water_sba/wfs</gmd:URL>
+                  </gmd:linkage>
+                </gmd:CI_OnlineResource>
+              </srv:connectPoint>
+            </srv:SV_OperationMetadata>
+          </srv:containsOperations>
+          <srv:containsOperations>
+            <srv:SV_OperationMetadata>
+              <srv:operationName>
+                <gco:CharacterString>GetFeature</gco:CharacterString>
+              </srv:operationName>
+              <srv:DCP>
+                <srv:DCPList codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#DCPList" codeListValue="HTTPGet">HTTPGet</srv:DCPList>
+              </srv:DCP>
+              <srv:DCP>
+                <srv:DCPList codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#DCPList" codeListValue="HTTPPost">HTTPPost</srv:DCPList>
+              </srv:DCP>
+              <srv:connectPoint>
+                <gmd:CI_OnlineResource>
+                  <gmd:linkage>
+                    <gmd:URL>http://services.ogc.noaa.gov/geoserver/geoss_water_sba/wfs</gmd:URL>
+                  </gmd:linkage>
+                </gmd:CI_OnlineResource>
+              </srv:connectPoint>
+            </srv:SV_OperationMetadata>
+          </srv:containsOperations>
+          <srv:containsOperations>
+            <srv:SV_OperationMetadata>
+              <srv:operationName>
+                <gco:CharacterString>GetGmlObject</gco:CharacterString>
+              </srv:operationName>
+              <srv:DCP>
+                <srv:DCPList codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#DCPList" codeListValue="HTTPGet">HTTPGet</srv:DCPList>
+              </srv:DCP>
+              <srv:DCP>
+                <srv:DCPList codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#DCPList" codeListValue="HTTPPost">HTTPPost</srv:DCPList>
+              </srv:DCP>
+              <srv:connectPoint>
+                <gmd:CI_OnlineResource>
+                  <gmd:linkage>
+                    <gmd:URL>http://services.ogc.noaa.gov/geoserver/geoss_water_sba/wfs</gmd:URL>
+                  </gmd:linkage>
+                </gmd:CI_OnlineResource>
+              </srv:connectPoint>
+            </srv:SV_OperationMetadata>
+          </srv:containsOperations>
+          <srv:containsOperations>
+            <srv:SV_OperationMetadata>
+              <srv:operationName>
+                <gco:CharacterString>LockFeature</gco:CharacterString>
+              </srv:operationName>
+              <srv:DCP>
+                <srv:DCPList codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#DCPList" codeListValue="HTTPGet">HTTPGet</srv:DCPList>
+              </srv:DCP>
+              <srv:DCP>
+                <srv:DCPList codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#DCPList" codeListValue="HTTPPost">HTTPPost</srv:DCPList>
+              </srv:DCP>
+              <srv:connectPoint>
+                <gmd:CI_OnlineResource>
+                  <gmd:linkage>
+                    <gmd:URL>http://services.ogc.noaa.gov/geoserver/geoss_water_sba/wfs</gmd:URL>
+                  </gmd:linkage>
+                </gmd:CI_OnlineResource>
+              </srv:connectPoint>
+            </srv:SV_OperationMetadata>
+          </srv:containsOperations>
+          <srv:containsOperations>
+            <srv:SV_OperationMetadata>
+              <srv:operationName>
+                <gco:CharacterString>GetFeatureWithLock</gco:CharacterString>
+              </srv:operationName>
+              <srv:DCP>
+                <srv:DCPList codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#DCPList" codeListValue="HTTPGet">HTTPGet</srv:DCPList>
+              </srv:DCP>
+              <srv:DCP>
+                <srv:DCPList codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#DCPList" codeListValue="HTTPPost">HTTPPost</srv:DCPList>
+              </srv:DCP>
+              <srv:connectPoint>
+                <gmd:CI_OnlineResource>
+                  <gmd:linkage>
+                    <gmd:URL>http://services.ogc.noaa.gov/geoserver/geoss_water_sba/wfs</gmd:URL>
+                  </gmd:linkage>
+                </gmd:CI_OnlineResource>
+              </srv:connectPoint>
+            </srv:SV_OperationMetadata>
+          </srv:containsOperations>
+          <srv:containsOperations>
+            <srv:SV_OperationMetadata>
+              <srv:operationName>
+                <gco:CharacterString>Transaction</gco:CharacterString>
+              </srv:operationName>
+              <srv:DCP>
+                <srv:DCPList codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#DCPList" codeListValue="HTTPGet">HTTPGet</srv:DCPList>
+              </srv:DCP>
+              <srv:DCP>
+                <srv:DCPList codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#DCPList" codeListValue="HTTPPost">HTTPPost</srv:DCPList>
+              </srv:DCP>
+              <srv:connectPoint>
+                <gmd:CI_OnlineResource>
+                  <gmd:linkage>
+                    <gmd:URL>http://services.ogc.noaa.gov/geoserver/geoss_water_sba/wfs</gmd:URL>
+                  </gmd:linkage>
+                </gmd:CI_OnlineResource>
+              </srv:connectPoint>
+            </srv:SV_OperationMetadata>
+          </srv:containsOperations>
+          <srv:operatesOn uuidref="geoss_water_sba:Reservoir" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/harvesting/default.cfg&service=CSW&version=2.0.2&request=GetRecordById&outputschema=http://www.isotc211.org/2005/gmd&id=PYCSW_IDENTIFIER-geoss_water_sba:Reservoir"/>
+          <srv:operatesOn uuidref="geoss_water_sba:glwd_1" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/harvesting/default.cfg&service=CSW&version=2.0.2&request=GetRecordById&outputschema=http://www.isotc211.org/2005/gmd&id=PYCSW_IDENTIFIER-geoss_water_sba:glwd_1"/>
+          <srv:operatesOn uuidref="geoss_water_sba:Dams" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/harvesting/default.cfg&service=CSW&version=2.0.2&request=GetRecordById&outputschema=http://www.isotc211.org/2005/gmd&id=PYCSW_IDENTIFIER-geoss_water_sba:Dams"/>
+          <srv:operatesOn uuidref="geoss_water_sba:glwd_2" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/harvesting/default.cfg&service=CSW&version=2.0.2&request=GetRecordById&outputschema=http://www.isotc211.org/2005/gmd&id=PYCSW_IDENTIFIER-geoss_water_sba:glwd_2"/>
+          <srv:operatesOn uuidref="geoss_water_sba:Lakes" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/harvesting/default.cfg&service=CSW&version=2.0.2&request=GetRecordById&outputschema=http://www.isotc211.org/2005/gmd&id=PYCSW_IDENTIFIER-geoss_water_sba:Lakes"/>
+        </srv:SV_ServiceIdentification>
+      </gmd:identificationInfo>
+      <gmd:distributionInfo>
+        <gmd:MD_Distribution>
+          <gmd:transferOptions>
+            <gmd:MD_DigitalTransferOptions>
+              <gmd:onLine>
+                <gmd:CI_OnlineResource>
+                  <gmd:linkage>
+                    <gmd:URL>http://services.ogc.noaa.gov/geoserver/geoss_water_sba/wfs</gmd:URL>
+                  </gmd:linkage>
+                  <gmd:protocol>
+                    <gco:CharacterString>OGC:WFS</gco:CharacterString>
+                  </gmd:protocol>
+                  <gmd:name>
+                    <gco:CharacterString>PYCSW_IDENTIFIER</gco:CharacterString>
+                  </gmd:name>
+                  <gmd:description>
+                    <gco:CharacterString>OGC-WFS Web Feature Service</gco:CharacterString>
+                  </gmd:description>
+                </gmd:CI_OnlineResource>
+              </gmd:onLine>
+            </gmd:MD_DigitalTransferOptions>
+          </gmd:transferOptions>
+        </gmd:MD_Distribution>
+      </gmd:distributionInfo>
+    </gmd:MD_Metadata>
+    <gmd:MD_Metadata xsi:schemaLocation="http://www.isotc211.org/2005/gmd http://schemas.opengis.net/csw/2.0.2/profiles/apiso/1.0.0/apiso.xsd">
+      <gmd:fileIdentifier>
+        <gco:CharacterString>PYCSW_IDENTIFIER</gco:CharacterString>
+      </gmd:fileIdentifier>
+      <gmd:language>
+        <gco:CharacterString/>
+      </gmd:language>
+      <gmd:hierarchyLevel>
+        <gmd:MD_ScopeCode codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#MD_ScopeCode" codeListValue="service" codeSpace="ISOTC211/19115">service</gmd:MD_ScopeCode>
+      </gmd:hierarchyLevel>
+      <gmd:contact>
+        <gmd:CI_ResponsibleParty>
+          <gmd:individualName>
+            <gco:CharacterString/>
+          </gmd:individualName>
+          <gmd:organisationName>
+            <gco:CharacterString/>
+          </gmd:organisationName>
+          <gmd:positionName>
+            <gco:CharacterString/>
+          </gmd:positionName>
+          <gmd:contactInfo>
+            <gmd:CI_Contact>
+              <gmd:phone>
+                <gmd:CI_Telephone>
+                  <gmd:voice>
+                    <gco:CharacterString/>
+                  </gmd:voice>
+                  <gmd:facsimile>
+                    <gco:CharacterString/>
+                  </gmd:facsimile>
+                </gmd:CI_Telephone>
+              </gmd:phone>
+              <gmd:address>
+                <gmd:CI_Address>
+                  <gmd:deliveryPoint>
+                    <gco:CharacterString/>
+                  </gmd:deliveryPoint>
+                  <gmd:city>
+                    <gco:CharacterString/>
+                  </gmd:city>
+                  <gmd:administrativeArea>
+                    <gco:CharacterString/>
+                  </gmd:administrativeArea>
+                  <gmd:postalCode>
+                    <gco:CharacterString/>
+                  </gmd:postalCode>
+                  <gmd:country>
+                    <gco:CharacterString/>
+                  </gmd:country>
+                  <gmd:electronicMailAddress>
+                    <gco:CharacterString/>
+                  </gmd:electronicMailAddress>
+                </gmd:CI_Address>
+              </gmd:address>
+              <gmd:onlineResource>
+                <gmd:linkage>
+                  <gmd:URL>http://maps.cera.govt.nz/arcgis/services/CERA/CERA_TechClasses_WGS84/MapServer/WFSServer</gmd:URL>
+                </gmd:linkage>
+              </gmd:onlineResource>
+            </gmd:CI_Contact>
+          </gmd:contactInfo>
+          <gmd:role>
+            <gmd:CI_RoleCode codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#CI_RoleCode" codeListValue="pointOfContact">pointOfContact</gmd:CI_RoleCode>
+          </gmd:role>
+        </gmd:CI_ResponsibleParty>
+      </gmd:contact>
+      <gmd:dateStamp>
+        <gco:Date/>
+      </gmd:dateStamp>
+      <gmd:metadataStandardName>
+        <gco:CharacterString>ISO19119</gco:CharacterString>
+      </gmd:metadataStandardName>
+      <gmd:metadataStandardVersion>
+        <gco:CharacterString>2005/PDAM 1</gco:CharacterString>
+      </gmd:metadataStandardVersion>
+      <gmd:identificationInfo>
+        <srv:SV_ServiceIdentification id="PYCSW_IDENTIFIER">
+          <gmd:citation>
+            <gmd:CI_Citation>
+              <gmd:title>
+                <gco:CharacterString>CERA_CERA_TechClasses_WGS84</gco:CharacterString>
+              </gmd:title>
+            </gmd:CI_Citation>
+          </gmd:citation>
+          <gmd:abstract>
+            <gco:CharacterString/>
+          </gmd:abstract>
+          <gmd:descriptiveKeywords>
+            <gmd:MD_Keywords>
+              <gmd:keyword>
+                <gco:CharacterString/>
+              </gmd:keyword>
+            </gmd:MD_Keywords>
+          </gmd:descriptiveKeywords>
+          <gmd:language>
+            <gco:CharacterString/>
+          </gmd:language>
+          <srv:serviceType>
+            <gco:LocalName>OGC:WFS</gco:LocalName>
+          </srv:serviceType>
+          <srv:serviceTypeVersion>
+            <gco:CharacterString>2.0.0</gco:CharacterString>
+          </srv:serviceTypeVersion>
+          <srv:keywords>
+            <gmd:MD_Keywords>
+              <gmd:keyword>
+                <gco:CharacterString/>
+              </gmd:keyword>
+            </gmd:MD_Keywords>
+          </srv:keywords>
+          <srv:extent>
+            <gmd:EX_Extent>
+              <gmd:geographicElement>
+                <gmd:EX_GeographicBoundingBox>
+                  <gmd:westBoundLongitude>
+                    <gco:Decimal>171.11</gco:Decimal>
+                  </gmd:westBoundLongitude>
+                  <gmd:eastBoundLongitude>
+                    <gco:Decimal>173.13</gco:Decimal>
+                  </gmd:eastBoundLongitude>
+                  <gmd:southBoundLatitude>
+                    <gco:Decimal>-43.9</gco:Decimal>
+                  </gmd:southBoundLatitude>
+                  <gmd:northBoundLatitude>
+                    <gco:Decimal>-42.74</gco:Decimal>
+                  </gmd:northBoundLatitude>
+                </gmd:EX_GeographicBoundingBox>
+              </gmd:geographicElement>
+            </gmd:EX_Extent>
+          </srv:extent>
+          <srv:couplingType>
+            <srv:SV_CouplingType codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#SV_CouplingType" codeListValue="tight">tight</srv:SV_CouplingType>
+          </srv:couplingType>
+          <srv:coupledResource>
+            <srv:SV_CoupledResource>
+              <srv:operationName>
+                <gco:CharacterString>GetFeature</gco:CharacterString>
+              </srv:operationName>
+              <srv:identifier>
+                <gco:CharacterString>CERA_CERA_TechClasses_WGS84:MBIE_Technical_Classes_WGS84_2012-08-16</gco:CharacterString>
+              </srv:identifier>
+            </srv:SV_CoupledResource>
+          </srv:coupledResource>
+          <srv:coupledResource>
+            <srv:SV_CoupledResource>
+              <srv:operationName>
+                <gco:CharacterString>GetFeature</gco:CharacterString>
+              </srv:operationName>
+              <srv:identifier>
+                <gco:CharacterString>CERA_CERA_TechClasses_WGS84:MBIE_Technical_Classes_WGS84_2012-05-18</gco:CharacterString>
+              </srv:identifier>
+            </srv:SV_CoupledResource>
+          </srv:coupledResource>
+          <srv:coupledResource>
+            <srv:SV_CoupledResource>
+              <srv:operationName>
+                <gco:CharacterString>GetFeature</gco:CharacterString>
+              </srv:operationName>
+              <srv:identifier>
+                <gco:CharacterString>CERA_CERA_TechClasses_WGS84:MBIE_Technical_Classes_WGS84_2013-12-04</gco:CharacterString>
+              </srv:identifier>
+            </srv:SV_CoupledResource>
+          </srv:coupledResource>
+          <srv:coupledResource>
+            <srv:SV_CoupledResource>
+              <srv:operationName>
+                <gco:CharacterString>GetFeature</gco:CharacterString>
+              </srv:operationName>
+              <srv:identifier>
+                <gco:CharacterString>CERA_CERA_TechClasses_WGS84:MBIE_Technical_Classes_WGS84_2011-10-28</gco:CharacterString>
+              </srv:identifier>
+            </srv:SV_CoupledResource>
+          </srv:coupledResource>
+          <srv:coupledResource>
+            <srv:SV_CoupledResource>
+              <srv:operationName>
+                <gco:CharacterString>GetFeature</gco:CharacterString>
+              </srv:operationName>
+              <srv:identifier>
+                <gco:CharacterString>CERA_CERA_TechClasses_WGS84:MBIE_Technical_Classes_WGS84_2012-02-10</gco:CharacterString>
+              </srv:identifier>
+            </srv:SV_CoupledResource>
+          </srv:coupledResource>
+          <srv:coupledResource>
+            <srv:SV_CoupledResource>
+              <srv:operationName>
+                <gco:CharacterString>GetFeature</gco:CharacterString>
+              </srv:operationName>
+              <srv:identifier>
+                <gco:CharacterString>CERA_CERA_TechClasses_WGS84:MBIE_Technical_Classes_WGS84_2012-09-14</gco:CharacterString>
+              </srv:identifier>
+            </srv:SV_CoupledResource>
+          </srv:coupledResource>
+          <srv:coupledResource>
+            <srv:SV_CoupledResource>
+              <srv:operationName>
+                <gco:CharacterString>GetFeature</gco:CharacterString>
+              </srv:operationName>
+              <srv:identifier>
+                <gco:CharacterString>CERA_CERA_TechClasses_WGS84:MBIE_Technical_Classes_WGS84_2012-03-23</gco:CharacterString>
+              </srv:identifier>
+            </srv:SV_CoupledResource>
+          </srv:coupledResource>
+          <srv:coupledResource>
+            <srv:SV_CoupledResource>
+              <srv:operationName>
+                <gco:CharacterString>GetFeature</gco:CharacterString>
+              </srv:operationName>
+              <srv:identifier>
+                <gco:CharacterString>CERA_CERA_TechClasses_WGS84:MBIE_Technical_Classes_WGS84_2011-11-17</gco:CharacterString>
+              </srv:identifier>
+            </srv:SV_CoupledResource>
+          </srv:coupledResource>
+          <srv:coupledResource>
+            <srv:SV_CoupledResource>
+              <srv:operationName>
+                <gco:CharacterString>GetFeature</gco:CharacterString>
+              </srv:operationName>
+              <srv:identifier>
+                <gco:CharacterString>CERA_CERA_TechClasses_WGS84:MBIE_Technical_Classes_WGS84_2012-08-24</gco:CharacterString>
+              </srv:identifier>
+            </srv:SV_CoupledResource>
+          </srv:coupledResource>
+          <srv:coupledResource>
+            <srv:SV_CoupledResource>
+              <srv:operationName>
+                <gco:CharacterString>GetFeature</gco:CharacterString>
+              </srv:operationName>
+              <srv:identifier>
+                <gco:CharacterString>CERA_CERA_TechClasses_WGS84:MBIE_Technical_Classes_WGS84_2012-10-31</gco:CharacterString>
+              </srv:identifier>
+            </srv:SV_CoupledResource>
+          </srv:coupledResource>
+          <srv:containsOperations>
+            <srv:SV_OperationMetadata>
+              <srv:operationName>
+                <gco:CharacterString>GetCapabilities</gco:CharacterString>
+              </srv:operationName>
+              <srv:DCP>
+                <srv:DCPList codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#DCPList" codeListValue="HTTPGet">HTTPGet</srv:DCPList>
+              </srv:DCP>
+              <srv:DCP>
+                <srv:DCPList codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#DCPList" codeListValue="HTTPPost">HTTPPost</srv:DCPList>
+              </srv:DCP>
+              <srv:connectPoint>
+                <gmd:CI_OnlineResource>
+                  <gmd:linkage>
+                    <gmd:URL>http://maps.cera.govt.nz/arcgis/services/CERA/CERA_TechClasses_WGS84/MapServer/WFSServer</gmd:URL>
+                  </gmd:linkage>
+                </gmd:CI_OnlineResource>
+              </srv:connectPoint>
+            </srv:SV_OperationMetadata>
+          </srv:containsOperations>
+          <srv:containsOperations>
+            <srv:SV_OperationMetadata>
+              <srv:operationName>
+                <gco:CharacterString>DescribeFeatureType</gco:CharacterString>
+              </srv:operationName>
+              <srv:DCP>
+                <srv:DCPList codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#DCPList" codeListValue="HTTPGet">HTTPGet</srv:DCPList>
+              </srv:DCP>
+              <srv:DCP>
+                <srv:DCPList codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#DCPList" codeListValue="HTTPPost">HTTPPost</srv:DCPList>
+              </srv:DCP>
+              <srv:connectPoint>
+                <gmd:CI_OnlineResource>
+                  <gmd:linkage>
+                    <gmd:URL>http://maps.cera.govt.nz/arcgis/services/CERA/CERA_TechClasses_WGS84/MapServer/WFSServer</gmd:URL>
+                  </gmd:linkage>
+                </gmd:CI_OnlineResource>
+              </srv:connectPoint>
+            </srv:SV_OperationMetadata>
+          </srv:containsOperations>
+          <srv:containsOperations>
+            <srv:SV_OperationMetadata>
+              <srv:operationName>
+                <gco:CharacterString>GetFeature</gco:CharacterString>
+              </srv:operationName>
+              <srv:DCP>
+                <srv:DCPList codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#DCPList" codeListValue="HTTPGet">HTTPGet</srv:DCPList>
+              </srv:DCP>
+              <srv:DCP>
+                <srv:DCPList codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#DCPList" codeListValue="HTTPPost">HTTPPost</srv:DCPList>
+              </srv:DCP>
+              <srv:connectPoint>
+                <gmd:CI_OnlineResource>
+                  <gmd:linkage>
+                    <gmd:URL>http://maps.cera.govt.nz/arcgis/services/CERA/CERA_TechClasses_WGS84/MapServer/WFSServer</gmd:URL>
+                  </gmd:linkage>
+                </gmd:CI_OnlineResource>
+              </srv:connectPoint>
+            </srv:SV_OperationMetadata>
+          </srv:containsOperations>
+          <srv:containsOperations>
+            <srv:SV_OperationMetadata>
+              <srv:operationName>
+                <gco:CharacterString>ListStoredQueries</gco:CharacterString>
+              </srv:operationName>
+              <srv:DCP>
+                <srv:DCPList codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#DCPList" codeListValue="HTTPGet">HTTPGet</srv:DCPList>
+              </srv:DCP>
+              <srv:DCP>
+                <srv:DCPList codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#DCPList" codeListValue="HTTPPost">HTTPPost</srv:DCPList>
+              </srv:DCP>
+              <srv:connectPoint>
+                <gmd:CI_OnlineResource>
+                  <gmd:linkage>
+                    <gmd:URL>http://maps.cera.govt.nz/arcgis/services/CERA/CERA_TechClasses_WGS84/MapServer/WFSServer</gmd:URL>
+                  </gmd:linkage>
+                </gmd:CI_OnlineResource>
+              </srv:connectPoint>
+            </srv:SV_OperationMetadata>
+          </srv:containsOperations>
+          <srv:containsOperations>
+            <srv:SV_OperationMetadata>
+              <srv:operationName>
+                <gco:CharacterString>DescribeStoredQueries</gco:CharacterString>
+              </srv:operationName>
+              <srv:DCP>
+                <srv:DCPList codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#DCPList" codeListValue="HTTPGet">HTTPGet</srv:DCPList>
+              </srv:DCP>
+              <srv:DCP>
+                <srv:DCPList codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#DCPList" codeListValue="HTTPPost">HTTPPost</srv:DCPList>
+              </srv:DCP>
+              <srv:connectPoint>
+                <gmd:CI_OnlineResource>
+                  <gmd:linkage>
+                    <gmd:URL>http://maps.cera.govt.nz/arcgis/services/CERA/CERA_TechClasses_WGS84/MapServer/WFSServer</gmd:URL>
+                  </gmd:linkage>
+                </gmd:CI_OnlineResource>
+              </srv:connectPoint>
+            </srv:SV_OperationMetadata>
+          </srv:containsOperations>
+          <srv:containsOperations>
+            <srv:SV_OperationMetadata>
+              <srv:operationName>
+                <gco:CharacterString>ImplementsSimpleWFS</gco:CharacterString>
+              </srv:operationName>
+              <srv:DCP>
+                <srv:DCPList codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#DCPList" codeListValue="HTTPGet">HTTPGet</srv:DCPList>
+              </srv:DCP>
+              <srv:DCP>
+                <srv:DCPList codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#DCPList" codeListValue="HTTPPost">HTTPPost</srv:DCPList>
+              </srv:DCP>
+              <srv:connectPoint>
+                <gmd:CI_OnlineResource>
+                  <gmd:linkage>
+                    <gmd:URL>http://maps.cera.govt.nz/arcgis/services/CERA/CERA_TechClasses_WGS84/MapServer/WFSServer</gmd:URL>
+                  </gmd:linkage>
+                </gmd:CI_OnlineResource>
+              </srv:connectPoint>
+            </srv:SV_OperationMetadata>
+          </srv:containsOperations>
+          <srv:containsOperations>
+            <srv:SV_OperationMetadata>
+              <srv:operationName>
+                <gco:CharacterString>ImplementsBasicWFS</gco:CharacterString>
+              </srv:operationName>
+              <srv:DCP>
+                <srv:DCPList codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#DCPList" codeListValue="HTTPGet">HTTPGet</srv:DCPList>
+              </srv:DCP>
+              <srv:DCP>
+                <srv:DCPList codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#DCPList" codeListValue="HTTPPost">HTTPPost</srv:DCPList>
+              </srv:DCP>
+              <srv:connectPoint>
+                <gmd:CI_OnlineResource>
+                  <gmd:linkage>
+                    <gmd:URL>http://maps.cera.govt.nz/arcgis/services/CERA/CERA_TechClasses_WGS84/MapServer/WFSServer</gmd:URL>
+                  </gmd:linkage>
+                </gmd:CI_OnlineResource>
+              </srv:connectPoint>
+            </srv:SV_OperationMetadata>
+          </srv:containsOperations>
+          <srv:containsOperations>
+            <srv:SV_OperationMetadata>
+              <srv:operationName>
+                <gco:CharacterString>ImplementsTransactionalWFS</gco:CharacterString>
+              </srv:operationName>
+              <srv:DCP>
+                <srv:DCPList codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#DCPList" codeListValue="HTTPGet">HTTPGet</srv:DCPList>
+              </srv:DCP>
+              <srv:DCP>
+                <srv:DCPList codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#DCPList" codeListValue="HTTPPost">HTTPPost</srv:DCPList>
+              </srv:DCP>
+              <srv:connectPoint>
+                <gmd:CI_OnlineResource>
+                  <gmd:linkage>
+                    <gmd:URL>http://maps.cera.govt.nz/arcgis/services/CERA/CERA_TechClasses_WGS84/MapServer/WFSServer</gmd:URL>
+                  </gmd:linkage>
+                </gmd:CI_OnlineResource>
+              </srv:connectPoint>
+            </srv:SV_OperationMetadata>
+          </srv:containsOperations>
+          <srv:containsOperations>
+            <srv:SV_OperationMetadata>
+              <srv:operationName>
+                <gco:CharacterString>ImplementsLockingWFS</gco:CharacterString>
+              </srv:operationName>
+              <srv:DCP>
+                <srv:DCPList codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#DCPList" codeListValue="HTTPGet">HTTPGet</srv:DCPList>
+              </srv:DCP>
+              <srv:DCP>
+                <srv:DCPList codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#DCPList" codeListValue="HTTPPost">HTTPPost</srv:DCPList>
+              </srv:DCP>
+              <srv:connectPoint>
+                <gmd:CI_OnlineResource>
+                  <gmd:linkage>
+                    <gmd:URL>http://maps.cera.govt.nz/arcgis/services/CERA/CERA_TechClasses_WGS84/MapServer/WFSServer</gmd:URL>
+                  </gmd:linkage>
+                </gmd:CI_OnlineResource>
+              </srv:connectPoint>
+            </srv:SV_OperationMetadata>
+          </srv:containsOperations>
+          <srv:containsOperations>
+            <srv:SV_OperationMetadata>
+              <srv:operationName>
+                <gco:CharacterString>ImplementsInheritance</gco:CharacterString>
+              </srv:operationName>
+              <srv:DCP>
+                <srv:DCPList codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#DCPList" codeListValue="HTTPGet">HTTPGet</srv:DCPList>
+              </srv:DCP>
+              <srv:DCP>
+                <srv:DCPList codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#DCPList" codeListValue="HTTPPost">HTTPPost</srv:DCPList>
+              </srv:DCP>
+              <srv:connectPoint>
+                <gmd:CI_OnlineResource>
+                  <gmd:linkage>
+                    <gmd:URL>http://maps.cera.govt.nz/arcgis/services/CERA/CERA_TechClasses_WGS84/MapServer/WFSServer</gmd:URL>
+                  </gmd:linkage>
+                </gmd:CI_OnlineResource>
+              </srv:connectPoint>
+            </srv:SV_OperationMetadata>
+          </srv:containsOperations>
+          <srv:containsOperations>
+            <srv:SV_OperationMetadata>
+              <srv:operationName>
+                <gco:CharacterString>ImplementsRemoteResolve</gco:CharacterString>
+              </srv:operationName>
+              <srv:DCP>
+                <srv:DCPList codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#DCPList" codeListValue="HTTPGet">HTTPGet</srv:DCPList>
+              </srv:DCP>
+              <srv:DCP>
+                <srv:DCPList codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#DCPList" codeListValue="HTTPPost">HTTPPost</srv:DCPList>
+              </srv:DCP>
+              <srv:connectPoint>
+                <gmd:CI_OnlineResource>
+                  <gmd:linkage>
+                    <gmd:URL>http://maps.cera.govt.nz/arcgis/services/CERA/CERA_TechClasses_WGS84/MapServer/WFSServer</gmd:URL>
+                  </gmd:linkage>
+                </gmd:CI_OnlineResource>
+              </srv:connectPoint>
+            </srv:SV_OperationMetadata>
+          </srv:containsOperations>
+          <srv:containsOperations>
+            <srv:SV_OperationMetadata>
+              <srv:operationName>
+                <gco:CharacterString>ImplementsResultPaging</gco:CharacterString>
+              </srv:operationName>
+              <srv:DCP>
+                <srv:DCPList codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#DCPList" codeListValue="HTTPGet">HTTPGet</srv:DCPList>
+              </srv:DCP>
+              <srv:DCP>
+                <srv:DCPList codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#DCPList" codeListValue="HTTPPost">HTTPPost</srv:DCPList>
+              </srv:DCP>
+              <srv:connectPoint>
+                <gmd:CI_OnlineResource>
+                  <gmd:linkage>
+                    <gmd:URL>http://maps.cera.govt.nz/arcgis/services/CERA/CERA_TechClasses_WGS84/MapServer/WFSServer</gmd:URL>
+                  </gmd:linkage>
+                </gmd:CI_OnlineResource>
+              </srv:connectPoint>
+            </srv:SV_OperationMetadata>
+          </srv:containsOperations>
+          <srv:containsOperations>
+            <srv:SV_OperationMetadata>
+              <srv:operationName>
+                <gco:CharacterString>ImplementsStandardJoins</gco:CharacterString>
+              </srv:operationName>
+              <srv:DCP>
+                <srv:DCPList codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#DCPList" codeListValue="HTTPGet">HTTPGet</srv:DCPList>
+              </srv:DCP>
+              <srv:DCP>
+                <srv:DCPList codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#DCPList" codeListValue="HTTPPost">HTTPPost</srv:DCPList>
+              </srv:DCP>
+              <srv:connectPoint>
+                <gmd:CI_OnlineResource>
+                  <gmd:linkage>
+                    <gmd:URL>http://maps.cera.govt.nz/arcgis/services/CERA/CERA_TechClasses_WGS84/MapServer/WFSServer</gmd:URL>
+                  </gmd:linkage>
+                </gmd:CI_OnlineResource>
+              </srv:connectPoint>
+            </srv:SV_OperationMetadata>
+          </srv:containsOperations>
+          <srv:containsOperations>
+            <srv:SV_OperationMetadata>
+              <srv:operationName>
+                <gco:CharacterString>ImplementsSpatialJoins</gco:CharacterString>
+              </srv:operationName>
+              <srv:DCP>
+                <srv:DCPList codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#DCPList" codeListValue="HTTPGet">HTTPGet</srv:DCPList>
+              </srv:DCP>
+              <srv:DCP>
+                <srv:DCPList codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#DCPList" codeListValue="HTTPPost">HTTPPost</srv:DCPList>
+              </srv:DCP>
+              <srv:connectPoint>
+                <gmd:CI_OnlineResource>
+                  <gmd:linkage>
+                    <gmd:URL>http://maps.cera.govt.nz/arcgis/services/CERA/CERA_TechClasses_WGS84/MapServer/WFSServer</gmd:URL>
+                  </gmd:linkage>
+                </gmd:CI_OnlineResource>
+              </srv:connectPoint>
+            </srv:SV_OperationMetadata>
+          </srv:containsOperations>
+          <srv:containsOperations>
+            <srv:SV_OperationMetadata>
+              <srv:operationName>
+                <gco:CharacterString>ImplementsTemporalJoins</gco:CharacterString>
+              </srv:operationName>
+              <srv:DCP>
+                <srv:DCPList codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#DCPList" codeListValue="HTTPGet">HTTPGet</srv:DCPList>
+              </srv:DCP>
+              <srv:DCP>
+                <srv:DCPList codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#DCPList" codeListValue="HTTPPost">HTTPPost</srv:DCPList>
+              </srv:DCP>
+              <srv:connectPoint>
+                <gmd:CI_OnlineResource>
+                  <gmd:linkage>
+                    <gmd:URL>http://maps.cera.govt.nz/arcgis/services/CERA/CERA_TechClasses_WGS84/MapServer/WFSServer</gmd:URL>
+                  </gmd:linkage>
+                </gmd:CI_OnlineResource>
+              </srv:connectPoint>
+            </srv:SV_OperationMetadata>
+          </srv:containsOperations>
+          <srv:containsOperations>
+            <srv:SV_OperationMetadata>
+              <srv:operationName>
+                <gco:CharacterString>ImplementsFeatureVersioning</gco:CharacterString>
+              </srv:operationName>
+              <srv:DCP>
+                <srv:DCPList codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#DCPList" codeListValue="HTTPGet">HTTPGet</srv:DCPList>
+              </srv:DCP>
+              <srv:DCP>
+                <srv:DCPList codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#DCPList" codeListValue="HTTPPost">HTTPPost</srv:DCPList>
+              </srv:DCP>
+              <srv:connectPoint>
+                <gmd:CI_OnlineResource>
+                  <gmd:linkage>
+                    <gmd:URL>http://maps.cera.govt.nz/arcgis/services/CERA/CERA_TechClasses_WGS84/MapServer/WFSServer</gmd:URL>
+                  </gmd:linkage>
+                </gmd:CI_OnlineResource>
+              </srv:connectPoint>
+            </srv:SV_OperationMetadata>
+          </srv:containsOperations>
+          <srv:containsOperations>
+            <srv:SV_OperationMetadata>
+              <srv:operationName>
+                <gco:CharacterString>ManageStoredQueries</gco:CharacterString>
+              </srv:operationName>
+              <srv:DCP>
+                <srv:DCPList codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#DCPList" codeListValue="HTTPGet">HTTPGet</srv:DCPList>
+              </srv:DCP>
+              <srv:DCP>
+                <srv:DCPList codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#DCPList" codeListValue="HTTPPost">HTTPPost</srv:DCPList>
+              </srv:DCP>
+              <srv:connectPoint>
+                <gmd:CI_OnlineResource>
+                  <gmd:linkage>
+                    <gmd:URL>http://maps.cera.govt.nz/arcgis/services/CERA/CERA_TechClasses_WGS84/MapServer/WFSServer</gmd:URL>
+                  </gmd:linkage>
+                </gmd:CI_OnlineResource>
+              </srv:connectPoint>
+            </srv:SV_OperationMetadata>
+          </srv:containsOperations>
+          <srv:containsOperations>
+            <srv:SV_OperationMetadata>
+              <srv:operationName>
+                <gco:CharacterString>KVPEncoding</gco:CharacterString>
+              </srv:operationName>
+              <srv:DCP>
+                <srv:DCPList codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#DCPList" codeListValue="HTTPGet">HTTPGet</srv:DCPList>
+              </srv:DCP>
+              <srv:DCP>
+                <srv:DCPList codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#DCPList" codeListValue="HTTPPost">HTTPPost</srv:DCPList>
+              </srv:DCP>
+              <srv:connectPoint>
+                <gmd:CI_OnlineResource>
+                  <gmd:linkage>
+                    <gmd:URL>http://maps.cera.govt.nz/arcgis/services/CERA/CERA_TechClasses_WGS84/MapServer/WFSServer</gmd:URL>
+                  </gmd:linkage>
+                </gmd:CI_OnlineResource>
+              </srv:connectPoint>
+            </srv:SV_OperationMetadata>
+          </srv:containsOperations>
+          <srv:containsOperations>
+            <srv:SV_OperationMetadata>
+              <srv:operationName>
+                <gco:CharacterString>XMLEncoding</gco:CharacterString>
+              </srv:operationName>
+              <srv:DCP>
+                <srv:DCPList codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#DCPList" codeListValue="HTTPGet">HTTPGet</srv:DCPList>
+              </srv:DCP>
+              <srv:DCP>
+                <srv:DCPList codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#DCPList" codeListValue="HTTPPost">HTTPPost</srv:DCPList>
+              </srv:DCP>
+              <srv:connectPoint>
+                <gmd:CI_OnlineResource>
+                  <gmd:linkage>
+                    <gmd:URL>http://maps.cera.govt.nz/arcgis/services/CERA/CERA_TechClasses_WGS84/MapServer/WFSServer</gmd:URL>
+                  </gmd:linkage>
+                </gmd:CI_OnlineResource>
+              </srv:connectPoint>
+            </srv:SV_OperationMetadata>
+          </srv:containsOperations>
+          <srv:containsOperations>
+            <srv:SV_OperationMetadata>
+              <srv:operationName>
+                <gco:CharacterString>SOAPEncoding</gco:CharacterString>
+              </srv:operationName>
+              <srv:DCP>
+                <srv:DCPList codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#DCPList" codeListValue="HTTPGet">HTTPGet</srv:DCPList>
+              </srv:DCP>
+              <srv:DCP>
+                <srv:DCPList codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#DCPList" codeListValue="HTTPPost">HTTPPost</srv:DCPList>
+              </srv:DCP>
+              <srv:connectPoint>
+                <gmd:CI_OnlineResource>
+                  <gmd:linkage>
+                    <gmd:URL>http://maps.cera.govt.nz/arcgis/services/CERA/CERA_TechClasses_WGS84/MapServer/WFSServer</gmd:URL>
+                  </gmd:linkage>
+                </gmd:CI_OnlineResource>
+              </srv:connectPoint>
+            </srv:SV_OperationMetadata>
+          </srv:containsOperations>
+          <srv:operatesOn uuidref="CERA_CERA_TechClasses_WGS84:MBIE_Technical_Classes_WGS84_2012-08-16" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/harvesting/default.cfg&service=CSW&version=2.0.2&request=GetRecordById&outputschema=http://www.isotc211.org/2005/gmd&id=PYCSW_IDENTIFIER-CERA_CERA_TechClasses_WGS84:MBIE_Technical_Classes_WGS84_2012-08-16"/>
+          <srv:operatesOn uuidref="CERA_CERA_TechClasses_WGS84:MBIE_Technical_Classes_WGS84_2012-05-18" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/harvesting/default.cfg&service=CSW&version=2.0.2&request=GetRecordById&outputschema=http://www.isotc211.org/2005/gmd&id=PYCSW_IDENTIFIER-CERA_CERA_TechClasses_WGS84:MBIE_Technical_Classes_WGS84_2012-05-18"/>
+          <srv:operatesOn uuidref="CERA_CERA_TechClasses_WGS84:MBIE_Technical_Classes_WGS84_2013-12-04" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/harvesting/default.cfg&service=CSW&version=2.0.2&request=GetRecordById&outputschema=http://www.isotc211.org/2005/gmd&id=PYCSW_IDENTIFIER-CERA_CERA_TechClasses_WGS84:MBIE_Technical_Classes_WGS84_2013-12-04"/>
+          <srv:operatesOn uuidref="CERA_CERA_TechClasses_WGS84:MBIE_Technical_Classes_WGS84_2011-10-28" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/harvesting/default.cfg&service=CSW&version=2.0.2&request=GetRecordById&outputschema=http://www.isotc211.org/2005/gmd&id=PYCSW_IDENTIFIER-CERA_CERA_TechClasses_WGS84:MBIE_Technical_Classes_WGS84_2011-10-28"/>
+          <srv:operatesOn uuidref="CERA_CERA_TechClasses_WGS84:MBIE_Technical_Classes_WGS84_2012-02-10" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/harvesting/default.cfg&service=CSW&version=2.0.2&request=GetRecordById&outputschema=http://www.isotc211.org/2005/gmd&id=PYCSW_IDENTIFIER-CERA_CERA_TechClasses_WGS84:MBIE_Technical_Classes_WGS84_2012-02-10"/>
+          <srv:operatesOn uuidref="CERA_CERA_TechClasses_WGS84:MBIE_Technical_Classes_WGS84_2012-09-14" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/harvesting/default.cfg&service=CSW&version=2.0.2&request=GetRecordById&outputschema=http://www.isotc211.org/2005/gmd&id=PYCSW_IDENTIFIER-CERA_CERA_TechClasses_WGS84:MBIE_Technical_Classes_WGS84_2012-09-14"/>
+          <srv:operatesOn uuidref="CERA_CERA_TechClasses_WGS84:MBIE_Technical_Classes_WGS84_2012-03-23" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/harvesting/default.cfg&service=CSW&version=2.0.2&request=GetRecordById&outputschema=http://www.isotc211.org/2005/gmd&id=PYCSW_IDENTIFIER-CERA_CERA_TechClasses_WGS84:MBIE_Technical_Classes_WGS84_2012-03-23"/>
+          <srv:operatesOn uuidref="CERA_CERA_TechClasses_WGS84:MBIE_Technical_Classes_WGS84_2011-11-17" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/harvesting/default.cfg&service=CSW&version=2.0.2&request=GetRecordById&outputschema=http://www.isotc211.org/2005/gmd&id=PYCSW_IDENTIFIER-CERA_CERA_TechClasses_WGS84:MBIE_Technical_Classes_WGS84_2011-11-17"/>
+          <srv:operatesOn uuidref="CERA_CERA_TechClasses_WGS84:MBIE_Technical_Classes_WGS84_2012-08-24" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/harvesting/default.cfg&service=CSW&version=2.0.2&request=GetRecordById&outputschema=http://www.isotc211.org/2005/gmd&id=PYCSW_IDENTIFIER-CERA_CERA_TechClasses_WGS84:MBIE_Technical_Classes_WGS84_2012-08-24"/>
+          <srv:operatesOn uuidref="CERA_CERA_TechClasses_WGS84:MBIE_Technical_Classes_WGS84_2012-10-31" xlink:href="http://localhost/pycsw/csw.py?config=tests/suites/harvesting/default.cfg&service=CSW&version=2.0.2&request=GetRecordById&outputschema=http://www.isotc211.org/2005/gmd&id=PYCSW_IDENTIFIER-CERA_CERA_TechClasses_WGS84:MBIE_Technical_Classes_WGS84_2012-10-31"/>
+        </srv:SV_ServiceIdentification>
+      </gmd:identificationInfo>
+      <gmd:distributionInfo>
+        <gmd:MD_Distribution>
+          <gmd:transferOptions>
+            <gmd:MD_DigitalTransferOptions>
+              <gmd:onLine>
+                <gmd:CI_OnlineResource>
+                  <gmd:linkage>
+                    <gmd:URL>http://maps.cera.govt.nz/arcgis/services/CERA/CERA_TechClasses_WGS84/MapServer/WFSServer</gmd:URL>
+                  </gmd:linkage>
+                  <gmd:protocol>
+                    <gco:CharacterString>OGC:WFS</gco:CharacterString>
+                  </gmd:protocol>
+                  <gmd:name>
+                    <gco:CharacterString>PYCSW_IDENTIFIER</gco:CharacterString>
+                  </gmd:name>
+                  <gmd:description>
+                    <gco:CharacterString>OGC-WFS Web Feature Service</gco:CharacterString>
+                  </gmd:description>
+                </gmd:CI_OnlineResource>
+              </gmd:onLine>
+            </gmd:MD_DigitalTransferOptions>
+          </gmd:transferOptions>
+        </gmd:MD_Distribution>
+      </gmd:distributionInfo>
+    </gmd:MD_Metadata>
+  </csw:SearchResults>
+</csw:GetRecordsResponse>
diff --git a/tests/expected/suites_harvesting_post_Harvest-zzz-post-GetRecords-filter-wms-dc.xml b/tests/functionaltests/suites/harvesting/expected/post_Harvest-zzz-post-GetRecords-filter-wms-dc.xml
similarity index 99%
rename from tests/expected/suites_harvesting_post_Harvest-zzz-post-GetRecords-filter-wms-dc.xml
rename to tests/functionaltests/suites/harvesting/expected/post_Harvest-zzz-post-GetRecords-filter-wms-dc.xml
index 89b1cfb..c825868 100644
--- a/tests/expected/suites_harvesting_post_Harvest-zzz-post-GetRecords-filter-wms-dc.xml
+++ b/tests/functionaltests/suites/harvesting/expected/post_Harvest-zzz-post-GetRecords-filter-wms-dc.xml
@@ -72,7 +72,7 @@
       <dc:title>IEM WMS Service</dc:title>
       <dc:type>service</dc:type>
       <dc:subject></dc:subject>
-      <dc:format>OGC:WMS</dc:format>
+      <dc:format>WMS</dc:format>
       <dct:references scheme="OGC:WMS">http://mesonet.agron.iastate.edu/cgi-bin/wms/nexrad/n0r-t.cgi</dct:references>
       <dct:abstract>IEM generated CONUS composite of NWS WSR-88D level III base reflectivity.</dct:abstract>
       <dc:creator>Daryl Herzmann</dc:creator>
diff --git a/tests/expected/suites_harvesting_post_Harvest-zzz-post-GetRecords-filter-wms-iso.xml b/tests/functionaltests/suites/harvesting/expected/post_Harvest-zzz-post-GetRecords-filter-wms-iso.xml
similarity index 99%
rename from tests/expected/suites_harvesting_post_Harvest-zzz-post-GetRecords-filter-wms-iso.xml
rename to tests/functionaltests/suites/harvesting/expected/post_Harvest-zzz-post-GetRecords-filter-wms-iso.xml
index bc8c4c8..b17cbca 100644
--- a/tests/expected/suites_harvesting_post_Harvest-zzz-post-GetRecords-filter-wms-iso.xml
+++ b/tests/functionaltests/suites/harvesting/expected/post_Harvest-zzz-post-GetRecords-filter-wms-iso.xml
@@ -1145,7 +1145,7 @@
             <gco:LocalName>OGC:WMS</gco:LocalName>
           </srv:serviceType>
           <srv:serviceTypeVersion>
-            <gco:CharacterString>1.1.1</gco:CharacterString>
+            <gco:CharacterString>1.3.0</gco:CharacterString>
           </srv:serviceTypeVersion>
           <srv:keywords>
             <gmd:MD_Keywords>
diff --git a/tests/expected/suites_harvesting_post_Harvest-zzz-post-GetRecords-filter-wms-layer.xml b/tests/functionaltests/suites/harvesting/expected/post_Harvest-zzz-post-GetRecords-filter-wms-layer.xml
similarity index 100%
rename from tests/expected/suites_harvesting_post_Harvest-zzz-post-GetRecords-filter-wms-layer.xml
rename to tests/functionaltests/suites/harvesting/expected/post_Harvest-zzz-post-GetRecords-filter-wms-layer.xml
diff --git a/tests/functionaltests/suites/harvesting/expected/post_Harvest-zzz-post-GetRecords-filter-wps-process.xml b/tests/functionaltests/suites/harvesting/expected/post_Harvest-zzz-post-GetRecords-filter-wps-process.xml
new file mode 100644
index 0000000..0d07614
--- /dev/null
+++ b/tests/functionaltests/suites/harvesting/expected/post_Harvest-zzz-post-GetRecords-filter-wps-process.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- PYCSW_VERSION -->
+<csw:GetRecordsResponse xmlns:csw="http://www.opengis.net/cat/csw/2.0.2" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dct="http://purl.org/dc/terms/" xmlns:gmd="http://www.isotc211.org/2005/gmd" xmlns:gml="http://www.opengis.net/gml" xmlns:ows="http://www.opengis.net/ows" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0.2" xsi:schemaLocation="http://www.opengis.net/cat/csw/2.0.2 http://schemas.opengis.net/csw/2.0.2/CSW-di [...]
+  <csw:SearchStatus timestamp="PYCSW_TIMESTAMP"/>
+  <csw:SearchResults nextRecord="6" numberOfRecordsMatched="10" numberOfRecordsReturned="5" recordSchema="http://www.opengis.net/cat/csw/2.0.2" elementSet="full">
+    <csw:Record>
+      <dc:identifier>PYCSW_IDENTIFIER</dc:identifier>
+      <dc:title>gov.usgs.cida.gdp.wps.algorithm.filemanagement.CreateNewShapefileDataStore</dc:title>
+      <dc:type>software</dc:type>
+      <dct:references scheme="OGC:WPS">http://cida.usgs.gov/gdp/utility/WebProcessingService</dct:references>
+      <dct:references scheme="OGC:WPS-1.1.0-http-get-capabilities">http://cida.usgs.gov/gdp/utility/WebProcessingService?version=1.0.0&request=GetCapabilities&service=WPS</dct:references>
+      <dct:references scheme="OGC:WPS-1.0.0-http-describe-process">http://cida.usgs.gov/gdp/utility/WebProcessingService?identifier=gov.usgs.cida.gdp.wps.algorithm.filemanagement.CreateNewShapefileDataStore&version=1.0.0&request=DescribeProcess&service=WPS</dct:references>
+      <dc:source>http://cida.usgs.gov/gdp/utility/WebProcessingService</dc:source>
+    </csw:Record>
+    <csw:Record>
+      <dc:identifier>PYCSW_IDENTIFIER</dc:identifier>
+      <dc:title>Get Grid Time Range</dc:title>
+      <dc:type>software</dc:type>
+      <dct:references scheme="OGC:WPS">http://cida.usgs.gov/gdp/utility/WebProcessingService</dct:references>
+      <dct:references scheme="OGC:WPS-1.1.0-http-get-capabilities">http://cida.usgs.gov/gdp/utility/WebProcessingService?version=1.0.0&request=GetCapabilities&service=WPS</dct:references>
+      <dct:references scheme="OGC:WPS-1.0.0-http-describe-process">http://cida.usgs.gov/gdp/utility/WebProcessingService?identifier=gov.usgs.cida.gdp.wps.algorithm.filemanagement.CreateNewShapefileDataStore&version=1.0.0&request=DescribeProcess&service=WPS</dct:references>
+      <dct:references scheme="OGC:WPS-1.0.0-http-describe-process">http://cida.usgs.gov/gdp/utility/WebProcessingService?identifier=gov.usgs.cida.gdp.wps.algorithm.discovery.GetGridTimeRange&version=1.0.0&request=DescribeProcess&service=WPS</dct:references>
+      <dc:source>http://cida.usgs.gov/gdp/utility/WebProcessingService</dc:source>
+    </csw:Record>
+    <csw:Record>
+      <dc:identifier>PYCSW_IDENTIFIER</dc:identifier>
+      <dc:title>gov.usgs.cida.gdp.wps.algorithm.filemanagement.ReceiveFiles</dc:title>
+      <dc:type>software</dc:type>
+      <dct:references scheme="OGC:WPS">http://cida.usgs.gov/gdp/utility/WebProcessingService</dct:references>
+      <dct:references scheme="OGC:WPS-1.1.0-http-get-capabilities">http://cida.usgs.gov/gdp/utility/WebProcessingService?version=1.0.0&request=GetCapabilities&service=WPS</dct:references>
+      <dct:references scheme="OGC:WPS-1.0.0-http-describe-process">http://cida.usgs.gov/gdp/utility/WebProcessingService?identifier=gov.usgs.cida.gdp.wps.algorithm.filemanagement.CreateNewShapefileDataStore&version=1.0.0&request=DescribeProcess&service=WPS</dct:references>
+      <dct:references scheme="OGC:WPS-1.0.0-http-describe-process">http://cida.usgs.gov/gdp/utility/WebProcessingService?identifier=gov.usgs.cida.gdp.wps.algorithm.discovery.GetGridTimeRange&version=1.0.0&request=DescribeProcess&service=WPS</dct:references>
+      <dct:references scheme="OGC:WPS-1.0.0-http-describe-process">http://cida.usgs.gov/gdp/utility/WebProcessingService?identifier=gov.usgs.cida.gdp.wps.algorithm.filemanagement.ReceiveFiles&version=1.0.0&request=DescribeProcess&service=WPS</dct:references>
+      <dc:source>http://cida.usgs.gov/gdp/utility/WebProcessingService</dc:source>
+    </csw:Record>
+    <csw:Record>
+      <dc:identifier>PYCSW_IDENTIFIER</dc:identifier>
+      <dc:title>gov.usgs.cida.gdp.wps.algorithm.discovery.GetWcsCoverages</dc:title>
+      <dc:type>software</dc:type>
+      <dct:references scheme="OGC:WPS">http://cida.usgs.gov/gdp/utility/WebProcessingService</dct:references>
+      <dct:references scheme="OGC:WPS-1.1.0-http-get-capabilities">http://cida.usgs.gov/gdp/utility/WebProcessingService?version=1.0.0&request=GetCapabilities&service=WPS</dct:references>
+      <dct:references scheme="OGC:WPS-1.0.0-http-describe-process">http://cida.usgs.gov/gdp/utility/WebProcessingService?identifier=gov.usgs.cida.gdp.wps.algorithm.filemanagement.CreateNewShapefileDataStore&version=1.0.0&request=DescribeProcess&service=WPS</dct:references>
+      <dct:references scheme="OGC:WPS-1.0.0-http-describe-process">http://cida.usgs.gov/gdp/utility/WebProcessingService?identifier=gov.usgs.cida.gdp.wps.algorithm.discovery.GetGridTimeRange&version=1.0.0&request=DescribeProcess&service=WPS</dct:references>
+      <dct:references scheme="OGC:WPS-1.0.0-http-describe-process">http://cida.usgs.gov/gdp/utility/WebProcessingService?identifier=gov.usgs.cida.gdp.wps.algorithm.filemanagement.ReceiveFiles&version=1.0.0&request=DescribeProcess&service=WPS</dct:references>
+      <dct:references scheme="OGC:WPS-1.0.0-http-describe-process">http://cida.usgs.gov/gdp/utility/WebProcessingService?identifier=gov.usgs.cida.gdp.wps.algorithm.discovery.GetWcsCoverages&version=1.0.0&request=DescribeProcess&service=WPS</dct:references>
+      <dc:source>http://cida.usgs.gov/gdp/utility/WebProcessingService</dc:source>
+    </csw:Record>
+    <csw:Record>
+      <dc:identifier>PYCSW_IDENTIFIER</dc:identifier>
+      <dc:title>gov.usgs.cida.gdp.wps.algorithm.filemanagement.GetWatersGeom</dc:title>
+      <dc:type>software</dc:type>
+      <dct:references scheme="OGC:WPS">http://cida.usgs.gov/gdp/utility/WebProcessingService</dct:references>
+      <dct:references scheme="OGC:WPS-1.1.0-http-get-capabilities">http://cida.usgs.gov/gdp/utility/WebProcessingService?version=1.0.0&request=GetCapabilities&service=WPS</dct:references>
+      <dct:references scheme="OGC:WPS-1.0.0-http-describe-process">http://cida.usgs.gov/gdp/utility/WebProcessingService?identifier=gov.usgs.cida.gdp.wps.algorithm.filemanagement.CreateNewShapefileDataStore&version=1.0.0&request=DescribeProcess&service=WPS</dct:references>
+      <dct:references scheme="OGC:WPS-1.0.0-http-describe-process">http://cida.usgs.gov/gdp/utility/WebProcessingService?identifier=gov.usgs.cida.gdp.wps.algorithm.discovery.GetGridTimeRange&version=1.0.0&request=DescribeProcess&service=WPS</dct:references>
+      <dct:references scheme="OGC:WPS-1.0.0-http-describe-process">http://cida.usgs.gov/gdp/utility/WebProcessingService?identifier=gov.usgs.cida.gdp.wps.algorithm.filemanagement.ReceiveFiles&version=1.0.0&request=DescribeProcess&service=WPS</dct:references>
+      <dct:references scheme="OGC:WPS-1.0.0-http-describe-process">http://cida.usgs.gov/gdp/utility/WebProcessingService?identifier=gov.usgs.cida.gdp.wps.algorithm.discovery.GetWcsCoverages&version=1.0.0&request=DescribeProcess&service=WPS</dct:references>
+      <dct:references scheme="OGC:WPS-1.0.0-http-describe-process">http://cida.usgs.gov/gdp/utility/WebProcessingService?identifier=gov.usgs.cida.gdp.wps.algorithm.filemanagement.GetWatersGeom&version=1.0.0&request=DescribeProcess&service=WPS</dct:references>
+      <dc:source>http://cida.usgs.gov/gdp/utility/WebProcessingService</dc:source>
+    </csw:Record>
+  </csw:SearchResults>
+</csw:GetRecordsResponse>
diff --git a/tests/expected/suites_harvesting_post_Transaction-000-delete-all.xml b/tests/functionaltests/suites/harvesting/expected/post_Transaction-000-delete-all.xml
similarity index 94%
rename from tests/expected/suites_harvesting_post_Transaction-000-delete-all.xml
rename to tests/functionaltests/suites/harvesting/expected/post_Transaction-000-delete-all.xml
index 77b76ef..c400e31 100644
--- a/tests/expected/suites_harvesting_post_Transaction-000-delete-all.xml
+++ b/tests/functionaltests/suites/harvesting/expected/post_Transaction-000-delete-all.xml
@@ -4,6 +4,6 @@
   <csw:TransactionSummary>
     <csw:totalInserted>0</csw:totalInserted>
     <csw:totalUpdated>0</csw:totalUpdated>
-    <csw:totalDeleted>478</csw:totalDeleted>
+    <csw:totalDeleted>131</csw:totalDeleted>
   </csw:TransactionSummary>
 </csw:TransactionResponse>
diff --git a/tests/suites/harvesting/get/requests.txt b/tests/functionaltests/suites/harvesting/get/requests.txt
similarity index 100%
rename from tests/suites/harvesting/get/requests.txt
rename to tests/functionaltests/suites/harvesting/get/requests.txt
diff --git a/tests/suites/harvesting/post/Clear-000-delete-all.xml b/tests/functionaltests/suites/harvesting/post/Clear-000-delete-all.xml
similarity index 100%
rename from tests/suites/harvesting/post/Clear-000-delete-all.xml
rename to tests/functionaltests/suites/harvesting/post/Clear-000-delete-all.xml
diff --git a/tests/suites/harvesting/post/Exception-Havest-csw-404.xml b/tests/functionaltests/suites/harvesting/post/Exception-Havest-csw-404.xml
similarity index 100%
rename from tests/suites/harvesting/post/Exception-Havest-csw-404.xml
rename to tests/functionaltests/suites/harvesting/post/Exception-Havest-csw-404.xml
diff --git a/tests/suites/harvesting/post/GetCapabilities.xml b/tests/functionaltests/suites/harvesting/post/GetCapabilities.xml
similarity index 100%
rename from tests/suites/harvesting/post/GetCapabilities.xml
rename to tests/functionaltests/suites/harvesting/post/GetCapabilities.xml
diff --git a/tests/suites/harvesting/post/GetDomain-parameter.xml b/tests/functionaltests/suites/harvesting/post/GetDomain-parameter.xml
similarity index 100%
rename from tests/suites/harvesting/post/GetDomain-parameter.xml
rename to tests/functionaltests/suites/harvesting/post/GetDomain-parameter.xml
diff --git a/tests/suites/harvesting/post/Harvest-csw-iso.xml b/tests/functionaltests/suites/harvesting/post/Harvest-csw-iso.xml
similarity index 100%
rename from tests/suites/harvesting/post/Harvest-csw-iso.xml
rename to tests/functionaltests/suites/harvesting/post/Harvest-csw-iso.xml
diff --git a/tests/suites/harvesting/post/Harvest-csw-run1.xml b/tests/functionaltests/suites/harvesting/post/Harvest-csw-run1.xml
similarity index 100%
rename from tests/suites/harvesting/post/Harvest-csw-run1.xml
rename to tests/functionaltests/suites/harvesting/post/Harvest-csw-run1.xml
diff --git a/tests/suites/harvesting/post/Harvest-csw-run2.xml b/tests/functionaltests/suites/harvesting/post/Harvest-csw-run2.xml
similarity index 100%
rename from tests/suites/harvesting/post/Harvest-csw-run2.xml
rename to tests/functionaltests/suites/harvesting/post/Harvest-csw-run2.xml
diff --git a/tests/suites/harvesting/post/Harvest-dc.xml b/tests/functionaltests/suites/harvesting/post/Harvest-dc.xml
similarity index 100%
rename from tests/suites/harvesting/post/Harvest-dc.xml
rename to tests/functionaltests/suites/harvesting/post/Harvest-dc.xml
diff --git a/tests/suites/harvesting/post/Harvest-fgdc.xml b/tests/functionaltests/suites/harvesting/post/Harvest-fgdc.xml
similarity index 100%
rename from tests/suites/harvesting/post/Harvest-fgdc.xml
rename to tests/functionaltests/suites/harvesting/post/Harvest-fgdc.xml
diff --git a/tests/suites/harvesting/post/Harvest-iso.xml b/tests/functionaltests/suites/harvesting/post/Harvest-iso.xml
similarity index 100%
rename from tests/suites/harvesting/post/Harvest-iso.xml
rename to tests/functionaltests/suites/harvesting/post/Harvest-iso.xml
diff --git a/tests/suites/harvesting/post/Harvest-rdf.xml b/tests/functionaltests/suites/harvesting/post/Harvest-rdf.xml
similarity index 100%
rename from tests/suites/harvesting/post/Harvest-rdf.xml
rename to tests/functionaltests/suites/harvesting/post/Harvest-rdf.xml
diff --git a/tests/suites/harvesting/post/Harvest-sos100.xml b/tests/functionaltests/suites/harvesting/post/Harvest-sos100.xml
similarity index 100%
rename from tests/suites/harvesting/post/Harvest-sos100.xml
rename to tests/functionaltests/suites/harvesting/post/Harvest-sos100.xml
diff --git a/tests/suites/harvesting/post/Harvest-sos200.xml b/tests/functionaltests/suites/harvesting/post/Harvest-sos200.xml
similarity index 100%
rename from tests/suites/harvesting/post/Harvest-sos200.xml
rename to tests/functionaltests/suites/harvesting/post/Harvest-sos200.xml
diff --git a/tests/suites/harvesting/post/Harvest-waf.xml b/tests/functionaltests/suites/harvesting/post/Harvest-waf.xml
similarity index 100%
rename from tests/suites/harvesting/post/Harvest-waf.xml
rename to tests/functionaltests/suites/harvesting/post/Harvest-waf.xml
diff --git a/tests/suites/harvesting/post/Harvest-wcs.xml b/tests/functionaltests/suites/harvesting/post/Harvest-wcs.xml
similarity index 100%
copy from tests/suites/harvesting/post/Harvest-wcs.xml
copy to tests/functionaltests/suites/harvesting/post/Harvest-wcs.xml
diff --git a/tests/suites/harvesting/post/Harvest-wfs.xml b/tests/functionaltests/suites/harvesting/post/Harvest-wfs110.xml
similarity index 100%
rename from tests/suites/harvesting/post/Harvest-wfs.xml
rename to tests/functionaltests/suites/harvesting/post/Harvest-wfs110.xml
diff --git a/tests/suites/harvesting/post/Harvest-wcs.xml b/tests/functionaltests/suites/harvesting/post/Harvest-wfs200.xml
similarity index 67%
rename from tests/suites/harvesting/post/Harvest-wcs.xml
rename to tests/functionaltests/suites/harvesting/post/Harvest-wfs200.xml
index f59f4cc..9968eb7 100644
--- a/tests/suites/harvesting/post/Harvest-wcs.xml
+++ b/tests/functionaltests/suites/harvesting/post/Harvest-wfs200.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <Harvest xmlns="http://www.opengis.net/cat/csw/2.0.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/cat/csw/2.0.2 http://schemas.opengis.net/csw/2.0.2/CSW-publication.xsd" service="CSW" version="2.0.2">
-  <Source>http://demo.mapserver.org/cgi-bin/wcs</Source>
-  <ResourceType>http://www.opengis.net/wcs</ResourceType>
+    <Source>http://maps.cera.govt.nz/arcgis/services/CERA/CERA_TechClasses_WGS84/MapServer/WFSServer</Source>
+  <ResourceType>http://www.opengis.net/wfs/2.0</ResourceType>
   <ResourceFormat>application/xml</ResourceFormat>
 </Harvest>
diff --git a/tests/suites/harvesting/post/Harvest-wms-run1.xml b/tests/functionaltests/suites/harvesting/post/Harvest-wms-run1.xml
similarity index 100%
rename from tests/suites/harvesting/post/Harvest-wms-run1.xml
rename to tests/functionaltests/suites/harvesting/post/Harvest-wms-run1.xml
diff --git a/tests/suites/harvesting/post/Harvest-wms-run2.xml b/tests/functionaltests/suites/harvesting/post/Harvest-wms-run2.xml
similarity index 100%
rename from tests/suites/harvesting/post/Harvest-wms-run2.xml
rename to tests/functionaltests/suites/harvesting/post/Harvest-wms-run2.xml
diff --git a/tests/suites/harvesting/post/Harvest-wmts.xml b/tests/functionaltests/suites/harvesting/post/Harvest-wmts.xml
similarity index 84%
rename from tests/suites/harvesting/post/Harvest-wmts.xml
rename to tests/functionaltests/suites/harvesting/post/Harvest-wmts.xml
index 93e224f..6d83393 100644
--- a/tests/suites/harvesting/post/Harvest-wmts.xml
+++ b/tests/functionaltests/suites/harvesting/post/Harvest-wmts.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <Harvest xmlns="http://www.opengis.net/cat/csw/2.0.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/cat/csw/2.0.2 http://schemas.opengis.net/csw/2.0.2/CSW-publication.xsd" service="CSW" version="2.0.2">
-  <Source>http://map1c.vis.earthdata.nasa.gov/wmts-geo/wmts.cgi</Source>
+  <Source>http://maps.wien.gv.at/wmts/1.0.0/WMTSCapabilities.xml</Source>
   <ResourceType>http://www.opengis.net/wmts/1.0</ResourceType>
   <ResourceFormat>application/xml</ResourceFormat>
 </Harvest>
diff --git a/tests/suites/harvesting/post/Harvest-wps.xml b/tests/functionaltests/suites/harvesting/post/Harvest-wps.xml
similarity index 100%
rename from tests/suites/harvesting/post/Harvest-wps.xml
rename to tests/functionaltests/suites/harvesting/post/Harvest-wps.xml
diff --git a/tests/suites/harvesting/post/Harvest-zzz-post-GetRecords-filter-ows-dc.xml b/tests/functionaltests/suites/harvesting/post/Harvest-zzz-post-GetRecords-filter-ows-dc.xml
similarity index 100%
rename from tests/suites/harvesting/post/Harvest-zzz-post-GetRecords-filter-ows-dc.xml
rename to tests/functionaltests/suites/harvesting/post/Harvest-zzz-post-GetRecords-filter-ows-dc.xml
diff --git a/tests/suites/harvesting/post/Harvest-zzz-post-GetRecords-filter-sos-abstract-dc.xml b/tests/functionaltests/suites/harvesting/post/Harvest-zzz-post-GetRecords-filter-sos-abstract-dc.xml
similarity index 100%
rename from tests/suites/harvesting/post/Harvest-zzz-post-GetRecords-filter-sos-abstract-dc.xml
rename to tests/functionaltests/suites/harvesting/post/Harvest-zzz-post-GetRecords-filter-sos-abstract-dc.xml
diff --git a/tests/suites/harvesting/post/Harvest-zzz-post-GetRecords-filter-sos-dc.xml b/tests/functionaltests/suites/harvesting/post/Harvest-zzz-post-GetRecords-filter-sos-dc.xml
similarity index 100%
rename from tests/suites/harvesting/post/Harvest-zzz-post-GetRecords-filter-sos-dc.xml
rename to tests/functionaltests/suites/harvesting/post/Harvest-zzz-post-GetRecords-filter-sos-dc.xml
diff --git a/tests/suites/harvesting/post/Harvest-zzz-post-GetRecords-filter-sos-iso.xml b/tests/functionaltests/suites/harvesting/post/Harvest-zzz-post-GetRecords-filter-sos-iso.xml
similarity index 100%
rename from tests/suites/harvesting/post/Harvest-zzz-post-GetRecords-filter-sos-iso.xml
rename to tests/functionaltests/suites/harvesting/post/Harvest-zzz-post-GetRecords-filter-sos-iso.xml
diff --git a/tests/suites/harvesting/post/Harvest-zzz-post-GetRecords-filter-wfs-iso.xml b/tests/functionaltests/suites/harvesting/post/Harvest-zzz-post-GetRecords-filter-wfs-iso.xml
similarity index 100%
rename from tests/suites/harvesting/post/Harvest-zzz-post-GetRecords-filter-wfs-iso.xml
rename to tests/functionaltests/suites/harvesting/post/Harvest-zzz-post-GetRecords-filter-wfs-iso.xml
diff --git a/tests/suites/harvesting/post/Harvest-zzz-post-GetRecords-filter-wms-dc.xml b/tests/functionaltests/suites/harvesting/post/Harvest-zzz-post-GetRecords-filter-wms-dc.xml
similarity index 100%
rename from tests/suites/harvesting/post/Harvest-zzz-post-GetRecords-filter-wms-dc.xml
rename to tests/functionaltests/suites/harvesting/post/Harvest-zzz-post-GetRecords-filter-wms-dc.xml
diff --git a/tests/suites/harvesting/post/Harvest-zzz-post-GetRecords-filter-wms-iso.xml b/tests/functionaltests/suites/harvesting/post/Harvest-zzz-post-GetRecords-filter-wms-iso.xml
similarity index 100%
rename from tests/suites/harvesting/post/Harvest-zzz-post-GetRecords-filter-wms-iso.xml
rename to tests/functionaltests/suites/harvesting/post/Harvest-zzz-post-GetRecords-filter-wms-iso.xml
diff --git a/tests/suites/harvesting/post/Harvest-zzz-post-GetRecords-filter-wms-layer.xml b/tests/functionaltests/suites/harvesting/post/Harvest-zzz-post-GetRecords-filter-wms-layer.xml
similarity index 100%
rename from tests/suites/harvesting/post/Harvest-zzz-post-GetRecords-filter-wms-layer.xml
rename to tests/functionaltests/suites/harvesting/post/Harvest-zzz-post-GetRecords-filter-wms-layer.xml
diff --git a/tests/suites/default/post/GetRecords-all-sortby-bbox.xml b/tests/functionaltests/suites/harvesting/post/Harvest-zzz-post-GetRecords-filter-wps-process.xml
similarity index 58%
rename from tests/suites/default/post/GetRecords-all-sortby-bbox.xml
rename to tests/functionaltests/suites/harvesting/post/Harvest-zzz-post-GetRecords-filter-wps-process.xml
index eace825..3c87edd 100644
--- a/tests/suites/default/post/GetRecords-all-sortby-bbox.xml
+++ b/tests/functionaltests/suites/harvesting/post/Harvest-zzz-post-GetRecords-filter-wps-process.xml
@@ -1,12 +1,14 @@
 <?xml version="1.0" encoding="ISO-8859-1" standalone="no"?>
 <csw:GetRecords xmlns:csw="http://www.opengis.net/cat/csw/2.0.2" xmlns:ogc="http://www.opengis.net/ogc" service="CSW" version="2.0.2" resultType="results" startPosition="1" maxRecords="5" outputFormat="application/xml" outputSchema="http://www.opengis.net/cat/csw/2.0.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/cat/csw/2.0.2 http://schemas.opengis.net/csw/2.0.2/CSW-discovery.xsd">
-    <csw:Query typeNames="csw:Record">
-        <csw:ElementSetName>full</csw:ElementSetName>
-        <ogc:SortBy>
-            <ogc:SortProperty>
-                <ogc:PropertyName>ows:BoundingBox</ogc:PropertyName>
-                <ogc:SortOrder>DESC</ogc:SortOrder>
-            </ogc:SortProperty>
-        </ogc:SortBy>
-    </csw:Query>
+  <csw:Query typeNames="csw:Record">
+    <csw:ElementSetName>full</csw:ElementSetName>
+    <csw:Constraint version="1.1.0">
+      <ogc:Filter>
+        <ogc:PropertyIsEqualTo>
+          <ogc:PropertyName>dc:type</ogc:PropertyName>
+          <ogc:Literal>software</ogc:Literal>
+        </ogc:PropertyIsEqualTo>
+      </ogc:Filter>
+    </csw:Constraint>
+  </csw:Query>
 </csw:GetRecords>
diff --git a/tests/suites/harvesting/post/Transaction-000-delete-all.xml b/tests/functionaltests/suites/harvesting/post/Transaction-000-delete-all.xml
similarity index 100%
rename from tests/suites/harvesting/post/Transaction-000-delete-all.xml
rename to tests/functionaltests/suites/harvesting/post/Transaction-000-delete-all.xml
diff --git a/tests/suites/manager/default.cfg b/tests/functionaltests/suites/manager/default.cfg
similarity index 100%
rename from tests/suites/manager/default.cfg
rename to tests/functionaltests/suites/manager/default.cfg
diff --git a/tests/expected/suites_manager_post_Clear-000-delete-all.xml b/tests/functionaltests/suites/manager/expected/post_Clear-000-delete-all.xml
similarity index 100%
rename from tests/expected/suites_manager_post_Clear-000-delete-all.xml
rename to tests/functionaltests/suites/manager/expected/post_Clear-000-delete-all.xml
diff --git a/tests/expected/suites_manager_post_GetCapabilities.xml b/tests/functionaltests/suites/manager/expected/post_GetCapabilities.xml
similarity index 99%
rename from tests/expected/suites_manager_post_GetCapabilities.xml
rename to tests/functionaltests/suites/manager/expected/post_GetCapabilities.xml
index 7b88658..4931b7d 100644
--- a/tests/expected/suites_manager_post_GetCapabilities.xml
+++ b/tests/functionaltests/suites/manager/expected/post_GetCapabilities.xml
@@ -259,6 +259,7 @@
         <ows:Value>http://www.opengis.net/sos/2.0</ows:Value>
         <ows:Value>http://www.opengis.net/wcs</ows:Value>
         <ows:Value>http://www.opengis.net/wfs</ows:Value>
+        <ows:Value>http://www.opengis.net/wfs/2.0</ows:Value>
         <ows:Value>http://www.opengis.net/wms</ows:Value>
         <ows:Value>http://www.opengis.net/wmts/1.0</ows:Value>
         <ows:Value>http://www.opengis.net/wps/1.0.0</ows:Value>
@@ -284,6 +285,7 @@
         <ows:Value>http://www.opengis.net/sos/2.0</ows:Value>
         <ows:Value>http://www.opengis.net/wcs</ows:Value>
         <ows:Value>http://www.opengis.net/wfs</ows:Value>
+        <ows:Value>http://www.opengis.net/wfs/2.0</ows:Value>
         <ows:Value>http://www.opengis.net/wms</ows:Value>
         <ows:Value>http://www.opengis.net/wmts/1.0</ows:Value>
         <ows:Value>http://www.opengis.net/wps/1.0.0</ows:Value>
diff --git a/tests/expected/suites_harvesting_post_GetDomain-parameter.xml b/tests/functionaltests/suites/manager/expected/post_GetDomain-parameter.xml
similarity index 96%
rename from tests/expected/suites_harvesting_post_GetDomain-parameter.xml
rename to tests/functionaltests/suites/manager/expected/post_GetDomain-parameter.xml
index a681d2a..b47402c 100644
--- a/tests/expected/suites_harvesting_post_GetDomain-parameter.xml
+++ b/tests/functionaltests/suites/manager/expected/post_GetDomain-parameter.xml
@@ -16,6 +16,7 @@
       <csw:Value>http://www.opengis.net/sos/2.0</csw:Value>
       <csw:Value>http://www.opengis.net/wcs</csw:Value>
       <csw:Value>http://www.opengis.net/wfs</csw:Value>
+      <csw:Value>http://www.opengis.net/wfs/2.0</csw:Value>
       <csw:Value>http://www.opengis.net/wms</csw:Value>
       <csw:Value>http://www.opengis.net/wmts/1.0</csw:Value>
       <csw:Value>http://www.opengis.net/wps/1.0.0</csw:Value>
diff --git a/tests/expected/suites_manager_post_Transaction-000-delete-all.xml b/tests/functionaltests/suites/manager/expected/post_Transaction-000-delete-all.xml
similarity index 100%
rename from tests/expected/suites_manager_post_Transaction-000-delete-all.xml
rename to tests/functionaltests/suites/manager/expected/post_Transaction-000-delete-all.xml
diff --git a/tests/expected/suites_manager_post_Transaction-dc-01-insert.xml b/tests/functionaltests/suites/manager/expected/post_Transaction-dc-01-insert.xml
similarity index 100%
rename from tests/expected/suites_manager_post_Transaction-dc-01-insert.xml
rename to tests/functionaltests/suites/manager/expected/post_Transaction-dc-01-insert.xml
diff --git a/tests/expected/suites_manager_post_Transaction-dc-02-update-full.xml b/tests/functionaltests/suites/manager/expected/post_Transaction-dc-02-update-full.xml
similarity index 100%
rename from tests/expected/suites_manager_post_Transaction-dc-02-update-full.xml
rename to tests/functionaltests/suites/manager/expected/post_Transaction-dc-02-update-full.xml
diff --git a/tests/expected/suites_manager_post_Transaction-fgdc-01-insert.xml b/tests/functionaltests/suites/manager/expected/post_Transaction-fgdc-01-insert.xml
similarity index 100%
rename from tests/expected/suites_manager_post_Transaction-fgdc-01-insert.xml
rename to tests/functionaltests/suites/manager/expected/post_Transaction-fgdc-01-insert.xml
diff --git a/tests/expected/suites_manager_post_Transaction-fgdc-02-update-recprop.xml b/tests/functionaltests/suites/manager/expected/post_Transaction-fgdc-02-update-recprop.xml
similarity index 100%
rename from tests/expected/suites_manager_post_Transaction-fgdc-02-update-recprop.xml
rename to tests/functionaltests/suites/manager/expected/post_Transaction-fgdc-02-update-recprop.xml
diff --git a/tests/expected/suites_manager_post_Transaction-fgdc-03-delete-all.xml b/tests/functionaltests/suites/manager/expected/post_Transaction-fgdc-03-delete-all.xml
similarity index 100%
rename from tests/expected/suites_manager_post_Transaction-fgdc-03-delete-all.xml
rename to tests/functionaltests/suites/manager/expected/post_Transaction-fgdc-03-delete-all.xml
diff --git a/tests/expected/suites_manager_post_Transaction-iso-00-delete-all.xml b/tests/functionaltests/suites/manager/expected/post_Transaction-iso-00-delete-all.xml
similarity index 100%
rename from tests/expected/suites_manager_post_Transaction-iso-00-delete-all.xml
rename to tests/functionaltests/suites/manager/expected/post_Transaction-iso-00-delete-all.xml
diff --git a/tests/expected/suites_manager_post_Transaction-iso-01-insert.xml b/tests/functionaltests/suites/manager/expected/post_Transaction-iso-01-insert.xml
similarity index 100%
rename from tests/expected/suites_manager_post_Transaction-iso-01-insert.xml
rename to tests/functionaltests/suites/manager/expected/post_Transaction-iso-01-insert.xml
diff --git a/tests/expected/suites_manager_post_Transaction-iso-02-update-full.xml b/tests/functionaltests/suites/manager/expected/post_Transaction-iso-02-update-full.xml
similarity index 100%
rename from tests/expected/suites_manager_post_Transaction-iso-02-update-full.xml
rename to tests/functionaltests/suites/manager/expected/post_Transaction-iso-02-update-full.xml
diff --git a/tests/expected/suites_manager_post_Transaction-iso-03-update-recprop.xml b/tests/functionaltests/suites/manager/expected/post_Transaction-iso-03-update-recprop.xml
similarity index 100%
rename from tests/expected/suites_manager_post_Transaction-iso-03-update-recprop.xml
rename to tests/functionaltests/suites/manager/expected/post_Transaction-iso-03-update-recprop.xml
diff --git a/tests/expected/suites_manager_post_Transaction-iso-04-update-recprop-no-matches.xml b/tests/functionaltests/suites/manager/expected/post_Transaction-iso-04-update-recprop-no-matches.xml
similarity index 100%
rename from tests/expected/suites_manager_post_Transaction-iso-04-update-recprop-no-matches.xml
rename to tests/functionaltests/suites/manager/expected/post_Transaction-iso-04-update-recprop-no-matches.xml
diff --git a/tests/expected/suites_manager_post_Transaction-iso-05-delete.xml b/tests/functionaltests/suites/manager/expected/post_Transaction-iso-05-delete.xml
similarity index 100%
rename from tests/expected/suites_manager_post_Transaction-iso-05-delete.xml
rename to tests/functionaltests/suites/manager/expected/post_Transaction-iso-05-delete.xml
diff --git a/tests/expected/suites_manager_post_Transaction-xxx-delete-all.xml b/tests/functionaltests/suites/manager/expected/post_Transaction-xxx-delete-all.xml
similarity index 100%
rename from tests/expected/suites_manager_post_Transaction-xxx-delete-all.xml
rename to tests/functionaltests/suites/manager/expected/post_Transaction-xxx-delete-all.xml
diff --git a/tests/suites/manager/post/Clear-000-delete-all.xml b/tests/functionaltests/suites/manager/post/Clear-000-delete-all.xml
similarity index 100%
rename from tests/suites/manager/post/Clear-000-delete-all.xml
rename to tests/functionaltests/suites/manager/post/Clear-000-delete-all.xml
diff --git a/tests/suites/manager/post/GetCapabilities.xml b/tests/functionaltests/suites/manager/post/GetCapabilities.xml
similarity index 100%
rename from tests/suites/manager/post/GetCapabilities.xml
rename to tests/functionaltests/suites/manager/post/GetCapabilities.xml
diff --git a/tests/suites/manager/post/GetDomain-parameter.xml b/tests/functionaltests/suites/manager/post/GetDomain-parameter.xml
similarity index 100%
rename from tests/suites/manager/post/GetDomain-parameter.xml
rename to tests/functionaltests/suites/manager/post/GetDomain-parameter.xml
diff --git a/tests/suites/manager/post/Transaction-000-delete-all.xml b/tests/functionaltests/suites/manager/post/Transaction-000-delete-all.xml
similarity index 100%
rename from tests/suites/manager/post/Transaction-000-delete-all.xml
rename to tests/functionaltests/suites/manager/post/Transaction-000-delete-all.xml
diff --git a/tests/suites/manager/post/Transaction-dc-01-insert.xml b/tests/functionaltests/suites/manager/post/Transaction-dc-01-insert.xml
similarity index 100%
rename from tests/suites/manager/post/Transaction-dc-01-insert.xml
rename to tests/functionaltests/suites/manager/post/Transaction-dc-01-insert.xml
diff --git a/tests/suites/manager/post/Transaction-dc-02-update-full.xml b/tests/functionaltests/suites/manager/post/Transaction-dc-02-update-full.xml
similarity index 100%
rename from tests/suites/manager/post/Transaction-dc-02-update-full.xml
rename to tests/functionaltests/suites/manager/post/Transaction-dc-02-update-full.xml
diff --git a/tests/suites/manager/post/Transaction-fgdc-01-insert.xml b/tests/functionaltests/suites/manager/post/Transaction-fgdc-01-insert.xml
similarity index 100%
rename from tests/suites/manager/post/Transaction-fgdc-01-insert.xml
rename to tests/functionaltests/suites/manager/post/Transaction-fgdc-01-insert.xml
diff --git a/tests/suites/manager/post/Transaction-fgdc-02-update-recprop.xml b/tests/functionaltests/suites/manager/post/Transaction-fgdc-02-update-recprop.xml
similarity index 100%
rename from tests/suites/manager/post/Transaction-fgdc-02-update-recprop.xml
rename to tests/functionaltests/suites/manager/post/Transaction-fgdc-02-update-recprop.xml
diff --git a/tests/suites/manager/post/Transaction-fgdc-03-delete-all.xml b/tests/functionaltests/suites/manager/post/Transaction-fgdc-03-delete-all.xml
similarity index 100%
rename from tests/suites/manager/post/Transaction-fgdc-03-delete-all.xml
rename to tests/functionaltests/suites/manager/post/Transaction-fgdc-03-delete-all.xml
diff --git a/tests/suites/manager/post/Transaction-iso-00-delete-all.xml b/tests/functionaltests/suites/manager/post/Transaction-iso-00-delete-all.xml
similarity index 100%
rename from tests/suites/manager/post/Transaction-iso-00-delete-all.xml
rename to tests/functionaltests/suites/manager/post/Transaction-iso-00-delete-all.xml
diff --git a/tests/suites/manager/post/Transaction-iso-01-insert.xml b/tests/functionaltests/suites/manager/post/Transaction-iso-01-insert.xml
similarity index 100%
rename from tests/suites/manager/post/Transaction-iso-01-insert.xml
rename to tests/functionaltests/suites/manager/post/Transaction-iso-01-insert.xml
diff --git a/tests/suites/manager/post/Transaction-iso-02-update-full.xml b/tests/functionaltests/suites/manager/post/Transaction-iso-02-update-full.xml
similarity index 100%
rename from tests/suites/manager/post/Transaction-iso-02-update-full.xml
rename to tests/functionaltests/suites/manager/post/Transaction-iso-02-update-full.xml
diff --git a/tests/suites/manager/post/Transaction-iso-03-update-recprop.xml b/tests/functionaltests/suites/manager/post/Transaction-iso-03-update-recprop.xml
similarity index 100%
rename from tests/suites/manager/post/Transaction-iso-03-update-recprop.xml
rename to tests/functionaltests/suites/manager/post/Transaction-iso-03-update-recprop.xml
diff --git a/tests/suites/manager/post/Transaction-iso-04-update-recprop-no-matches.xml b/tests/functionaltests/suites/manager/post/Transaction-iso-04-update-recprop-no-matches.xml
similarity index 100%
rename from tests/suites/manager/post/Transaction-iso-04-update-recprop-no-matches.xml
rename to tests/functionaltests/suites/manager/post/Transaction-iso-04-update-recprop-no-matches.xml
diff --git a/tests/suites/manager/post/Transaction-iso-05-delete.xml b/tests/functionaltests/suites/manager/post/Transaction-iso-05-delete.xml
similarity index 100%
rename from tests/suites/manager/post/Transaction-iso-05-delete.xml
rename to tests/functionaltests/suites/manager/post/Transaction-iso-05-delete.xml
diff --git a/tests/suites/manager/post/Transaction-xxx-delete-all.xml b/tests/functionaltests/suites/manager/post/Transaction-xxx-delete-all.xml
similarity index 100%
rename from tests/suites/manager/post/Transaction-xxx-delete-all.xml
rename to tests/functionaltests/suites/manager/post/Transaction-xxx-delete-all.xml
diff --git a/tests/suites/oaipmh/default.cfg b/tests/functionaltests/suites/oaipmh/default.cfg
similarity index 100%
rename from tests/suites/oaipmh/default.cfg
rename to tests/functionaltests/suites/oaipmh/default.cfg
diff --git a/tests/expected/suites_oaipmh_get_GetRecord_bad_metadata_prefix.xml b/tests/functionaltests/suites/oaipmh/expected/get_GetRecord_bad_metadata_prefix.xml
similarity index 100%
rename from tests/expected/suites_oaipmh_get_GetRecord_bad_metadata_prefix.xml
rename to tests/functionaltests/suites/oaipmh/expected/get_GetRecord_bad_metadata_prefix.xml
diff --git a/tests/expected/suites_oaipmh_get_GetRecord_dc.xml b/tests/functionaltests/suites/oaipmh/expected/get_GetRecord_dc.xml
similarity index 100%
rename from tests/expected/suites_oaipmh_get_GetRecord_dc.xml
rename to tests/functionaltests/suites/oaipmh/expected/get_GetRecord_dc.xml
diff --git a/tests/expected/suites_oaipmh_get_GetRecord_iso.xml b/tests/functionaltests/suites/oaipmh/expected/get_GetRecord_iso.xml
similarity index 100%
rename from tests/expected/suites_oaipmh_get_GetRecord_iso.xml
rename to tests/functionaltests/suites/oaipmh/expected/get_GetRecord_iso.xml
diff --git a/tests/expected/suites_oaipmh_get_GetRecord_oai_dc.xml b/tests/functionaltests/suites/oaipmh/expected/get_GetRecord_oai_dc.xml
similarity index 100%
rename from tests/expected/suites_oaipmh_get_GetRecord_oai_dc.xml
rename to tests/functionaltests/suites/oaipmh/expected/get_GetRecord_oai_dc.xml
diff --git a/tests/expected/suites_oaipmh_get_Identify.xml b/tests/functionaltests/suites/oaipmh/expected/get_Identify.xml
similarity index 100%
rename from tests/expected/suites_oaipmh_get_Identify.xml
rename to tests/functionaltests/suites/oaipmh/expected/get_Identify.xml
diff --git a/tests/expected/suites_oaipmh_get_ListIdentifiers_bad_metadata_prefix.xml b/tests/functionaltests/suites/oaipmh/expected/get_ListIdentifiers_bad_metadata_prefix.xml
similarity index 100%
rename from tests/expected/suites_oaipmh_get_ListIdentifiers_bad_metadata_prefix.xml
rename to tests/functionaltests/suites/oaipmh/expected/get_ListIdentifiers_bad_metadata_prefix.xml
diff --git a/tests/expected/suites_oaipmh_get_ListIdentifiers_dc.xml b/tests/functionaltests/suites/oaipmh/expected/get_ListIdentifiers_dc.xml
similarity index 100%
rename from tests/expected/suites_oaipmh_get_ListIdentifiers_dc.xml
rename to tests/functionaltests/suites/oaipmh/expected/get_ListIdentifiers_dc.xml
diff --git a/tests/expected/suites_oaipmh_get_ListIdentifiers_iso.xml b/tests/functionaltests/suites/oaipmh/expected/get_ListIdentifiers_iso.xml
similarity index 100%
rename from tests/expected/suites_oaipmh_get_ListIdentifiers_iso.xml
rename to tests/functionaltests/suites/oaipmh/expected/get_ListIdentifiers_iso.xml
diff --git a/tests/expected/suites_oaipmh_get_ListIdentifiers_missing_metadata_prefix.xml b/tests/functionaltests/suites/oaipmh/expected/get_ListIdentifiers_missing_metadata_prefix.xml
similarity index 100%
rename from tests/expected/suites_oaipmh_get_ListIdentifiers_missing_metadata_prefix.xml
rename to tests/functionaltests/suites/oaipmh/expected/get_ListIdentifiers_missing_metadata_prefix.xml
diff --git a/tests/expected/suites_oaipmh_get_ListIdentifiers_oai_dc.xml b/tests/functionaltests/suites/oaipmh/expected/get_ListIdentifiers_oai_dc.xml
similarity index 100%
rename from tests/expected/suites_oaipmh_get_ListIdentifiers_oai_dc.xml
rename to tests/functionaltests/suites/oaipmh/expected/get_ListIdentifiers_oai_dc.xml
diff --git a/tests/expected/suites_oaipmh_get_ListMetadataFormats.xml b/tests/functionaltests/suites/oaipmh/expected/get_ListMetadataFormats.xml
similarity index 100%
rename from tests/expected/suites_oaipmh_get_ListMetadataFormats.xml
rename to tests/functionaltests/suites/oaipmh/expected/get_ListMetadataFormats.xml
diff --git a/tests/expected/suites_oaipmh_get_ListRecords_dc.xml b/tests/functionaltests/suites/oaipmh/expected/get_ListRecords_dc.xml
similarity index 100%
rename from tests/expected/suites_oaipmh_get_ListRecords_dc.xml
rename to tests/functionaltests/suites/oaipmh/expected/get_ListRecords_dc.xml
diff --git a/tests/expected/suites_oaipmh_get_ListRecords_dc_bad_metadata_prefix.xml b/tests/functionaltests/suites/oaipmh/expected/get_ListRecords_dc_bad_metadata_prefix.xml
similarity index 100%
rename from tests/expected/suites_oaipmh_get_ListRecords_dc_bad_metadata_prefix.xml
rename to tests/functionaltests/suites/oaipmh/expected/get_ListRecords_dc_bad_metadata_prefix.xml
diff --git a/tests/expected/suites_oaipmh_get_ListRecords_iso19139.xml b/tests/functionaltests/suites/oaipmh/expected/get_ListRecords_iso19139.xml
similarity index 100%
rename from tests/expected/suites_oaipmh_get_ListRecords_iso19139.xml
rename to tests/functionaltests/suites/oaipmh/expected/get_ListRecords_iso19139.xml
diff --git a/tests/expected/suites_oaipmh_get_ListRecords_oai_dc.xml b/tests/functionaltests/suites/oaipmh/expected/get_ListRecords_oai_dc.xml
similarity index 100%
rename from tests/expected/suites_oaipmh_get_ListRecords_oai_dc.xml
rename to tests/functionaltests/suites/oaipmh/expected/get_ListRecords_oai_dc.xml
diff --git a/tests/expected/suites_oaipmh_get_ListSets.xml b/tests/functionaltests/suites/oaipmh/expected/get_ListSets.xml
similarity index 100%
rename from tests/expected/suites_oaipmh_get_ListSets.xml
rename to tests/functionaltests/suites/oaipmh/expected/get_ListSets.xml
diff --git a/tests/expected/suites_oaipmh_get_bad_verb.xml b/tests/functionaltests/suites/oaipmh/expected/get_bad_verb.xml
similarity index 100%
rename from tests/expected/suites_oaipmh_get_bad_verb.xml
rename to tests/functionaltests/suites/oaipmh/expected/get_bad_verb.xml
diff --git a/tests/expected/suites_oaipmh_get_empty.xml b/tests/functionaltests/suites/oaipmh/expected/get_empty.xml
similarity index 100%
rename from tests/expected/suites_oaipmh_get_empty.xml
rename to tests/functionaltests/suites/oaipmh/expected/get_empty.xml
diff --git a/tests/expected/suites_oaipmh_get_empty_with_amp.xml b/tests/functionaltests/suites/oaipmh/expected/get_empty_with_amp.xml
similarity index 100%
rename from tests/expected/suites_oaipmh_get_empty_with_amp.xml
rename to tests/functionaltests/suites/oaipmh/expected/get_empty_with_amp.xml
diff --git a/tests/expected/suites_oaipmh_get_illegal_verb.xml b/tests/functionaltests/suites/oaipmh/expected/get_illegal_verb.xml
similarity index 100%
rename from tests/expected/suites_oaipmh_get_illegal_verb.xml
rename to tests/functionaltests/suites/oaipmh/expected/get_illegal_verb.xml
diff --git a/tests/functionaltests/suites/oaipmh/get/requests.txt b/tests/functionaltests/suites/oaipmh/get/requests.txt
new file mode 100644
index 0000000..bf69552
--- /dev/null
+++ b/tests/functionaltests/suites/oaipmh/get/requests.txt
@@ -0,0 +1,20 @@
+empty,mode=oaipmh
+empty_with_amp,mode=oaipmh&
+bad_verb,mode=oaipmh&verb=foo
+illegal_verb,mode=oaipmh&verb=foo&foo=bar
+Identify,mode=oaipmh&verb=Identify
+ListSets,mode=oaipmh&verb=ListSets
+ListMetadataFormats,mode=oaipmh&verb=ListMetadataFormats
+GetRecord_dc,mode=oaipmh&verb=GetRecord&identifier=urn:uuid:19887a8a-f6b0-4a63-ae56-7fba0e17801f&metadataPrefix=csw-record
+GetRecord_bad_metadata_prefix,mode=oaipmh&verb=GetRecord&identifier=urn:uuid:19887a8a-f6b0-4a63-ae56-7fba0e17801f&metadataPrefix=csw-recordd
+GetRecord_oai_dc,mode=oaipmh&verb=GetRecord&identifier=urn:uuid:19887a8a-f6b0-4a63-ae56-7fba0e17801f&metadataPrefix=oai_dc
+GetRecord_iso,mode=oaipmh&verb=GetRecord&identifier=urn:uuid:19887a8a-f6b0-4a63-ae56-7fba0e17801f&metadataPrefix=iso19139
+ListIdentifiers_missing_metadata_prefix,mode=oaipmh&verb=ListIdentifiers
+ListIdentifiers_dc,mode=oaipmh&verb=ListIdentifiers&metadataPrefix=csw-record
+ListIdentifiers_iso,mode=oaipmh&verb=ListIdentifiers&metadataPrefix=iso19139
+ListIdentifiers_oai_dc,mode=oaipmh&verb=ListIdentifiers&metadataPrefix=oai_dc
+ListIdentifiers_bad_metadata_prefix,mode=oaipmh&verb=ListIdentifiers&metadataPrefix=foo
+ListRecords_dc,mode=oaipmh&verb=ListRecords&metadataPrefix=csw-record
+ListRecords_dc_bad_metadata_prefix,mode=oaipmh&verb=ListRecords&metadataPrefix=csw-recording
+ListRecords_oai_dc,mode=oaipmh&verb=ListRecords&metadataPrefix=oai_dc
+ListRecords_iso19139,mode=oaipmh&verb=ListRecords&metadataPrefix=iso19139
diff --git a/tests/suites/repofilter/default.cfg b/tests/functionaltests/suites/repofilter/default.cfg
similarity index 100%
rename from tests/suites/repofilter/default.cfg
rename to tests/functionaltests/suites/repofilter/default.cfg
diff --git a/tests/expected/suites_repofilter_post_GetRecordById-masked.xml b/tests/functionaltests/suites/repofilter/expected/post_GetRecordById-masked.xml
similarity index 100%
rename from tests/expected/suites_repofilter_post_GetRecordById-masked.xml
rename to tests/functionaltests/suites/repofilter/expected/post_GetRecordById-masked.xml
diff --git a/tests/expected/suites_repofilter_post_GetRecords-all.xml b/tests/functionaltests/suites/repofilter/expected/post_GetRecords-all.xml
similarity index 100%
rename from tests/expected/suites_repofilter_post_GetRecords-all.xml
rename to tests/functionaltests/suites/repofilter/expected/post_GetRecords-all.xml
diff --git a/tests/suites/repofilter/post/GetRecordById-masked.xml b/tests/functionaltests/suites/repofilter/post/GetRecordById-masked.xml
similarity index 100%
rename from tests/suites/repofilter/post/GetRecordById-masked.xml
rename to tests/functionaltests/suites/repofilter/post/GetRecordById-masked.xml
diff --git a/tests/suites/repofilter/post/GetRecords-all.xml b/tests/functionaltests/suites/repofilter/post/GetRecords-all.xml
similarity index 100%
rename from tests/suites/repofilter/post/GetRecords-all.xml
rename to tests/functionaltests/suites/repofilter/post/GetRecords-all.xml
diff --git a/tests/suites/sru/default.cfg b/tests/functionaltests/suites/sru/default.cfg
similarity index 100%
rename from tests/suites/sru/default.cfg
rename to tests/functionaltests/suites/sru/default.cfg
diff --git a/tests/expected/suites_sru_get_explain.xml b/tests/functionaltests/suites/sru/expected/get_explain.xml
similarity index 100%
rename from tests/expected/suites_sru_get_explain.xml
rename to tests/functionaltests/suites/sru/expected/get_explain.xml
diff --git a/tests/expected/suites_sru_get_search.xml b/tests/functionaltests/suites/sru/expected/get_search.xml
similarity index 100%
rename from tests/expected/suites_sru_get_search.xml
rename to tests/functionaltests/suites/sru/expected/get_search.xml
diff --git a/tests/expected/suites_sru_get_search_cql.xml b/tests/functionaltests/suites/sru/expected/get_search_cql.xml
similarity index 100%
rename from tests/expected/suites_sru_get_search_cql.xml
rename to tests/functionaltests/suites/sru/expected/get_search_cql.xml
diff --git a/tests/expected/suites_sru_get_search_maxrecords.xml b/tests/functionaltests/suites/sru/expected/get_search_maxrecords.xml
similarity index 100%
rename from tests/expected/suites_sru_get_search_maxrecords.xml
rename to tests/functionaltests/suites/sru/expected/get_search_maxrecords.xml
diff --git a/tests/expected/suites_sru_get_search_startrecord_maxrecords.xml b/tests/functionaltests/suites/sru/expected/get_search_startrecord_maxrecords.xml
similarity index 100%
rename from tests/expected/suites_sru_get_search_startrecord_maxrecords.xml
rename to tests/functionaltests/suites/sru/expected/get_search_startrecord_maxrecords.xml
diff --git a/tests/functionaltests/suites/sru/get/requests.txt b/tests/functionaltests/suites/sru/get/requests.txt
new file mode 100644
index 0000000..3db4b8c
--- /dev/null
+++ b/tests/functionaltests/suites/sru/get/requests.txt
@@ -0,0 +1,5 @@
+explain,mode=sru
+search,mode=sru&version=1.1&operation=searchRetrieve&query=lor
+search_maxrecords,mode=sru&operation=searchRetrieve&query=lor&maximumRecords=2
+search_startrecord_maxrecords,mode=sru&operation=searchRetrieve&query=lor&maximumRecords=2&startRecord=1
+search_cql,mode=sru&operation=searchRetrieve&query=dc:title%20like%20'%lor%'&maximumRecords=5
diff --git a/tests/suites/utf-8/default.cfg b/tests/functionaltests/suites/utf-8/default.cfg
similarity index 100%
rename from tests/suites/utf-8/default.cfg
rename to tests/functionaltests/suites/utf-8/default.cfg
diff --git a/tests/expected/suites_utf-8_post_GetCapabilities.xml b/tests/functionaltests/suites/utf-8/expected/post_GetCapabilities.xml
similarity index 100%
rename from tests/expected/suites_utf-8_post_GetCapabilities.xml
rename to tests/functionaltests/suites/utf-8/expected/post_GetCapabilities.xml
diff --git a/tests/suites/utf-8/post/GetCapabilities.xml b/tests/functionaltests/suites/utf-8/post/GetCapabilities.xml
similarity index 100%
rename from tests/suites/utf-8/post/GetCapabilities.xml
rename to tests/functionaltests/suites/utf-8/post/GetCapabilities.xml
diff --git a/tests/functionaltests/test_suites_functional.py b/tests/functionaltests/test_suites_functional.py
new file mode 100644
index 0000000..cba50c1
--- /dev/null
+++ b/tests/functionaltests/test_suites_functional.py
@@ -0,0 +1,395 @@
+# =================================================================
+#
+# Authors: Ricardo Garcia Silva <ricardo.garcia.silva at gmail.com>
+#          Tom Kralidis <tomkralidis at gmail.com>
+#
+# Copyright (c) 2017 Ricardo Garcia Silva
+# Copyright (c) 2017 Tom Kralidis
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation
+# files (the "Software"), to deal in the Software without
+# restriction, including without limitation the rights to use,
+# copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following
+# conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+#
+# =================================================================
+"""Functional tests for several test suites"""
+
+import codecs
+from difflib import SequenceMatcher
+from difflib import unified_diff
+from io import BytesIO
+import json
+import os
+import re
+import wsgiref.util
+
+from lxml import etree
+from lxml import objectify
+import pytest
+
+from pycsw import server
+
+pytestmark = pytest.mark.functional
+
+
+def test_suites(test_identifier, use_xml_canonicalisation,
+                save_results_directory, configuration, request_method,
+                request_data, expected_result, normalize_identifier_fields):
+    """Test suites.
+
+    This function is automatically parametrized by pytest as a result of the
+    ``conftest:pytest_generate_tests`` function. The input parameters are thus
+    supplied by pytest as a result of discovering and parsing the existing
+    test suites located under ``tests/functionaltests/suites``.
+
+    Parameters
+    ----------
+    configuration: SafeConfigParser
+        The configuration to use with the pycsw server instance under test
+    request_method: str
+        The HTTP method of the request. Either GET or POST.
+    request_data: str
+        Either the path to the request file, for POST requests, or the request
+        parameters, for GET requests
+    expected_result: str
+        Path to the file that holds the expected result
+    normalize_identifier_fields: bool
+        Whether to normalize the identifier fields in responses. This
+        parameter is used only in the 'harvesting' and 'manager' suites
+    use_xml_canonicalisation: bool
+        Whether to compare results with their expected values by using xml
+        canonicalisation or simply by doing a diff.
+    save_results_directory: str
+        Path to a directory where to test results should be saved to. A value
+        of ``None`` (the default) means that results will not get saved to
+        disk.
+
+    """
+
+    request_environment = _prepare_wsgi_test_environment(request_method,
+                                                         request_data)
+    pycsw_server = server.Csw(rtconfig=configuration, env=request_environment)
+    encoding = "utf-8"
+    status, raw_contents = pycsw_server.dispatch_wsgi()
+    contents = raw_contents.decode(encoding)
+    with codecs.open(expected_result, encoding=encoding) as fh:
+        expected = fh.read()
+    normalized_result = _normalize(
+        contents,
+        normalize_identifiers=normalize_identifier_fields
+    )
+    if use_xml_canonicalisation:
+        print("Comparing results using XML canonicalization...")
+        matches_expected = _compare_with_xml_canonicalisation(
+            normalized_result, expected)
+    else:
+        print("Comparing results using diffs...")
+        matches_expected = _compare_without_xml_canonicalisation(
+            normalized_result, expected)
+    if not matches_expected and use_xml_canonicalisation:
+        print("expected: {0}".format(expected))
+        print("response: {0}".format(normalized_result))
+    if save_results_directory is not None:
+        _save_test_result(save_results_directory, normalized_result,
+                          test_identifier, encoding)
+    assert matches_expected
+
+
+def _compare_with_xml_canonicalisation(normalized_result, expected):
+    try:
+        matches_expected = _test_xml_result(normalized_result, expected)
+    except etree.XMLSyntaxError:
+        # the file is either not XML (perhaps JSON?) or malformed
+        matches_expected = _test_json_result(normalized_result, expected)
+    except etree.C14NError:
+        print("XML canonicalisation has failed. Trying to compare result "
+              "with expected using difflib")
+        matches_expected = _test_xml_diff(normalized_result, expected)
+    return matches_expected
+
+
+def _compare_without_xml_canonicalisation(normalized_result, expected):
+    return _test_xml_diff(normalized_result, expected)
+
+
+def _prepare_wsgi_test_environment(request_method, request_data):
+    """Set up a testing environment for tests.
+
+    Parameters
+    ----------
+    request_method: str
+        The HTTP method of the request. Sould be either GET or POST.
+    request_data: str
+        Either the path to the request file, for POST requests or the request
+        parameters, for GET requests.
+
+    Returns
+    -------
+    request_environment: dict
+        A mapping with the environment variables to use in the test
+
+    """
+
+    request_environment = {
+        "REQUEST_METHOD": request_method.upper(),
+        "QUERY_STRING": "",
+        "REMOTE_ADDR": "127.0.0.1"
+    }
+    if request_method == "POST":
+        print("request_path: {0}".format(request_data))
+        request_buffer = BytesIO()
+        encoding = "utf-8"
+        with codecs.open(request_data, encoding=encoding) as fh:
+            contents = fh.read()
+            request_buffer.write(contents.encode(encoding))
+            request_environment["CONTENT_LENGTH"] = request_buffer.tell()
+            request_buffer.seek(0)
+            request_environment["wsgi.input"] = request_buffer
+    else:
+        print("Request contents: {0}".format(request_data))
+        request_environment["QUERY_STRING"] = request_data
+    wsgiref.util.setup_testing_defaults(request_environment)
+    return request_environment
+
+
+def _test_xml_result(result, expected, encoding="utf-8"):
+    """Compare the XML test results with an expected value.
+
+    This function compares the test result with the expected values by
+    performing XML canonicalization (c14n)[1]_, which compares the semantic
+    meanings of both XML files.
+
+    Parameters
+    ----------
+    result: str
+        The result of running the test as a unicode string
+    expected: str
+        The expected outcome as a unicode string.
+
+    Returns
+    -------
+    bool
+        Whether the result matches the expectations or not.
+
+    Raises
+    ------
+    etree.XMLSyntaxError
+        If any of the input parameters is not a valid XMl.
+    etree.C14NError
+        If any of the input parameters cannot be canonicalized. This may
+        happen if there are relative namespace URIs in any of the XML
+        documents, as they are explicitly not allowed when doing XML c14n
+
+    References
+    ----------
+    .. [1] http://www.w3.org/TR/xml-c14n
+
+    """
+
+    result_element = etree.fromstring(result.encode(encoding))
+    expected_element = etree.fromstring(expected.encode(encoding))
+    result_buffer = BytesIO()
+    result_tree = result_element.getroottree()
+    objectify.deannotate(result_tree, cleanup_namespaces=True)
+    result_tree.write_c14n(result_buffer)
+    expected_buffer = BytesIO()
+    expected_tree = expected_element.getroottree()
+    objectify.deannotate(expected_tree, cleanup_namespaces=True)
+    expected_tree.write_c14n(expected_buffer)
+    matches = result_buffer.getvalue() == expected_buffer.getvalue()
+    return matches
+
+
+def _test_json_result(result, expected, encoding="utf-8"):
+    """Compare the JSON test results with an expected value.
+
+    Parameters
+    ----------
+    result: str
+        The result of running the test.
+    expected: str
+        The expected outcome.
+
+    Returns
+    -------
+    bool
+        Whether the result matches the expectations or not.
+
+    """
+
+    result_dict = json.loads(result, encoding=encoding)
+    expected_dict = json.loads(expected, encoding=encoding)
+    return result_dict == expected_dict
+
+
+def _test_xml_diff(result, expected):
+    """Compare two XML strings by using python's ``difflib.SequenceMatcher``.
+
+    This is a character-by-character comparison and does not take into account
+    the semantic meaning of XML elements and attributes.
+
+    Parameters
+    ----------
+    result: str
+        The result of running the test.
+    expected: str
+        The expected outcome.
+
+    Returns
+    -------
+    bool
+        Whether the result matches the expectations or not.
+
+    """
+
+    sequence_matcher = SequenceMatcher(None, result, expected)
+    ratio = sequence_matcher.ratio()
+    matches = ratio == pytest.approx(1.0)
+    if not matches:
+        print("Result does not match expected.")
+        diff = unified_diff(result.splitlines(), expected.splitlines())
+        print("\n".join(list(diff)))
+    return matches
+
+
+def _normalize(sresult, normalize_identifiers=False):
+    """Normalize test output so it can be compared with the expected result.
+
+    Several dynamic elements of a pycsw response (such as time,
+    updateSequence, etc) are replaced with static constants to ease comparison.
+
+    Parameters
+    ----------
+    sresult: str
+        The test result as a unicode string.
+    normalize_identifiers: bool, optional
+        Whether identifier fields should be normalized.
+
+    Returns
+    -------
+    str
+        The normalized response.
+
+    """
+
+    # XML responses
+    version = re.search(r'<!-- (.*) -->', sresult)
+    updatesequence = re.search(r'updateSequence="(\S+)"', sresult)
+    timestamp = re.search(r'timestamp="(.*)"', sresult)
+    timestamp2 = re.search(r'timeStamp="(.*)"', sresult)
+    timestamp3 = re.search(
+        r'<oai:responseDate>(.*)</oai:responseDate>',
+        sresult
+    )
+    timestamp4 = re.search(
+        r'<oai:earliestDatestamp>(.*)</oai:earliestDatestamp>',
+        sresult
+    )
+    zrhost = re.search(r'<zr:host>(.*)</zr:host>', sresult)
+    zrport = re.search(r'<zr:port>(.*)</zr:port>', sresult)
+    elapsed_time = re.search(r'elapsedTime="(.*)"', sresult)
+    expires = re.search(r'expires="(.*?)"', sresult)
+    atom_updated = re.findall(r'<atom:updated>(.*)</atom:updated>',
+                              sresult)
+    if version:
+        sresult = sresult.replace(version.group(0),
+                                  r'<!-- PYCSW_VERSION -->')
+    if updatesequence:
+        sresult = sresult.replace(updatesequence.group(0),
+                                  r'updateSequence="PYCSW_UPDATESEQUENCE"')
+    if timestamp:
+        sresult = sresult.replace(timestamp.group(0),
+                                  r'timestamp="PYCSW_TIMESTAMP"')
+    if timestamp2:
+        sresult = sresult.replace(timestamp2.group(0),
+                                  r'timeStamp="PYCSW_TIMESTAMP"')
+    if timestamp3:
+        sresult = sresult.replace(
+            timestamp3.group(0),
+            r'<oai:responseDate>PYCSW_TIMESTAMP</oai:responseDate>'
+        )
+    if timestamp4:
+        sresult = sresult.replace(
+            timestamp4.group(0),
+            r'<oai:earliestDatestamp>PYCSW_TIMESTAMP</oai:earliestDatestamp>'
+        )
+    if zrport:
+        sresult = sresult.replace(zrport.group(0),
+                                  r'<zr:port>PYCSW_PORT</zr:port>')
+    if zrhost:
+        sresult = sresult.replace(zrhost.group(0),
+                                  r'<zr:host>PYCSW_HOST</zr:host>')
+    if elapsed_time:
+        sresult = sresult.replace(elapsed_time.group(0),
+                                  r'elapsedTime="PYCSW_ELAPSED_TIME"')
+    if expires:
+        sresult = sresult.replace(expires.group(0),
+                                  r'expires="PYCSW_EXPIRES"')
+    for au in atom_updated:
+        sresult = sresult.replace(au, r'PYCSW_TIMESTAMP')
+    # for csw:HarvestResponse documents, mask identifiers
+    # which are dynamically generated for OWS endpoints
+    if sresult.find(r'HarvestResponse') != -1:
+        identifier = re.findall(
+            r'<dc:identifier>(\S+)</dc:identifier>',
+            sresult
+        )
+        for i in identifier:
+            sresult = sresult.replace(i, r'PYCSW_IDENTIFIER')
+    # JSON responses
+    timestamp = re.search(r'"@timestamp": "(.*?)"', sresult)
+
+    if timestamp:
+        sresult = sresult.replace(timestamp.group(0),
+                                  r'"@timestamp": "PYCSW_TIMESTAMP"')
+    # harvesting-based GetRecords/GetRecordById responses
+    if normalize_identifiers:
+        dcid = re.findall(
+            r'<dc:identifier>(urn:uuid.*)</dc:identifier>',
+            sresult
+        )
+        isoid = re.findall(r'id="(urn:uuid.*)"', sresult)
+        isoid2 = re.findall(
+            r'<gco:CharacterString>(urn:uuid.*)</gco',
+            sresult
+        )
+        for d in dcid:
+            sresult = sresult.replace(d, r'PYCSW_IDENTIFIER')
+        for i in isoid:
+            sresult = sresult.replace(i, r'PYCSW_IDENTIFIER')
+        for i2 in isoid2:
+            sresult = sresult.replace(i2, r'PYCSW_IDENTIFIER')
+    return sresult
+
+
+def _save_test_result(target_directory_path, test_result, filename, encoding):
+    """Save the input test result to disk"""
+    full_directory_path = os.path.abspath(
+        os.path.expanduser(os.path.expandvars(target_directory_path)))
+    try:
+        os.makedirs(full_directory_path)
+    except OSError as exc:
+        if exc.errno == 17:  # directory already exists
+            pass
+        else:
+            raise
+    target_path = os.path.join(full_directory_path, filename)
+    with codecs.open(target_path, "w", encoding=encoding) as fh:
+        fh.write(test_result)
+    return target_path
diff --git a/tests/gen_html.py b/tests/gen_html.py
index b8f4ebe..373b577 100644
--- a/tests/gen_html.py
+++ b/tests/gen_html.py
@@ -28,9 +28,7 @@
 #
 # =================================================================
 
-import csv
 import os
-from six.moves.urllib.parse import quote
 
 JQUERY_VERSION = '1.9.0'
 
@@ -104,12 +102,12 @@ print('''
                         <select class="xml">
                             <option value="none">Select a CSW Request</option>''')
 
-for root, dirs, files in os.walk('suites'):
+for root, dirs, files in os.walk('functionaltests/suites'):
     if files:
         for sfile in files:
             if os.path.splitext(sfile)[1] in ['.xml']:  # it's a POST request
                 query = '%s%s%s' % (root.replace(os.sep, '/'), '/', sfile)
-                print('                            <option value="tests/suites/%s/default.cfg,%s">%s</option>' % (root.split(os.sep)[1], query, query))
+                print('                            <option value="tests/functionaltests/suites/%s/default.cfg,%s">%s</option>' % (root.split(os.sep)[1], query, query))
 print('''
                         </select>
                         <input type="button" class="send" value="Send"/>
@@ -133,16 +131,21 @@ print('''
             <ul>
 ''')
 
-for root, dirs, files in os.walk('suites'):
+for root, dirs, files in os.walk('functionaltests/suites'):
     if files:
         for sfile in files:
             if sfile == 'requests.txt':  # it's a list of GET requests
-                with open('%s%s%s' % (root.replace(os.sep, '/'), '/', sfile)) as f:
-                    gets = csv.reader(f)
-                    for row in gets:
-                        baseurl, query_string = row[1].split('?')
-                        query = '%s?%s' % (baseurl.replace('PYCSW_SERVER', '../csw.py'), query_string.replace('&', '&'))
-                        print('<li><a href="%s">%s</a></li>' % (query, row[0]))
+                file_path = os.path.join(root, sfile)
+                with open(file_path) as f:
+                    for line in f:
+                        name, query_string = line.strip().partition(",")[::2]
+                        baseurl = "../csw.py"
+                        query = "{baseurl}?{query_string}".format(
+                            baseurl=baseurl,
+                            query_string=query_string.replace("&", "&")
+                        )
+                        print('<li><a href={query!r}>{name}</a></li>'.format(
+                            query=query, name=name))
 print('''
             </ul>
         <hr/>
diff --git a/tests/index.html b/tests/index.html
index 18155ec..c55adfe 100644
--- a/tests/index.html
+++ b/tests/index.html
@@ -66,219 +66,575 @@
                     <td>
                         <select class="xml">
                             <option value="none">Select a CSW Request</option>
-                            <option value="tests/suites/apiso/default.cfg,suites/apiso/data/3e9a8c05.xml">suites/apiso/data/3e9a8c05.xml</option>
-                            <option value="tests/suites/apiso/default.cfg,suites/apiso/data/T_aerfo_RAS_1991_GR800P001800000012.xml">suites/apiso/data/T_aerfo_RAS_1991_GR800P001800000012.xml</option>
-                            <option value="tests/suites/apiso/default.cfg,suites/apiso/data/T_aerfo_RAS_1991_GR800P001800000013.xml">suites/apiso/data/T_aerfo_RAS_1991_GR800P001800000013.xml</option>
-                            <option value="tests/suites/apiso/default.cfg,suites/apiso/data/T_aerfo_RAS_1991_GR800P001800000014.xml">suites/apiso/data/T_aerfo_RAS_1991_GR800P001800000014.xml</option>
-                            <option value="tests/suites/apiso/default.cfg,suites/apiso/data/T_aerfo_RAS_1991_GR800P001800000015.xml">suites/apiso/data/T_aerfo_RAS_1991_GR800P001800000015.xml</option>
-                            <option value="tests/suites/apiso/default.cfg,suites/apiso/data/T_ortho_RAS_1998_284404.xml">suites/apiso/data/T_ortho_RAS_1998_284404.xml</option>
-                            <option value="tests/suites/apiso/default.cfg,suites/apiso/data/T_ortho_RAS_1998_288395.xml">suites/apiso/data/T_ortho_RAS_1998_288395.xml</option>
-                            <option value="tests/suites/apiso/default.cfg,suites/apiso/data/T_ortho_RAS_1998_288398.xml">suites/apiso/data/T_ortho_RAS_1998_288398.xml</option>
-                            <option value="tests/suites/apiso/default.cfg,suites/apiso/data/T_ortho_RAS_1998_288401.xml">suites/apiso/data/T_ortho_RAS_1998_288401.xml</option>
-                            <option value="tests/suites/apiso/default.cfg,suites/apiso/data/T_ortho_RAS_1998_288404.xml">suites/apiso/data/T_ortho_RAS_1998_288404.xml</option>
-                            <option value="tests/suites/apiso/default.cfg,suites/apiso/data/T_pmoed_DTM_1996_276395.xml">suites/apiso/data/T_pmoed_DTM_1996_276395.xml</option>
-                            <option value="tests/suites/apiso/default.cfg,suites/apiso/data/T_pmoed_DTM_1996_276398.xml">suites/apiso/data/T_pmoed_DTM_1996_276398.xml</option>
-                            <option value="tests/suites/apiso/default.cfg,suites/apiso/data/T_pmoed_DTM_1996_276401.xml">suites/apiso/data/T_pmoed_DTM_1996_276401.xml</option>
-                            <option value="tests/suites/apiso/default.cfg,suites/apiso/data/T_pmoed_DTM_1996_276404.xml">suites/apiso/data/T_pmoed_DTM_1996_276404.xml</option>
-                            <option value="tests/suites/apiso/default.cfg,suites/apiso/data/T_pmoed_DTM_1996_280395.xml">suites/apiso/data/T_pmoed_DTM_1996_280395.xml</option>
-                            <option value="tests/suites/apiso/default.cfg,suites/apiso/data/pacioos-NS06agg.xml">suites/apiso/data/pacioos-NS06agg.xml</option>
-                            <option value="tests/suites/apiso/default.cfg,suites/apiso/data/test.xml">suites/apiso/data/test.xml</option>
-                            <option value="tests/suites/apiso/default.cfg,suites/apiso/post/DescribeRecord.xml">suites/apiso/post/DescribeRecord.xml</option>
-                            <option value="tests/suites/apiso/default.cfg,suites/apiso/post/GetCapabilities.xml">suites/apiso/post/GetCapabilities.xml</option>
-                            <option value="tests/suites/apiso/default.cfg,suites/apiso/post/GetDomain-property.xml">suites/apiso/post/GetDomain-property.xml</option>
-                            <option value="tests/suites/apiso/default.cfg,suites/apiso/post/GetRecordById-brief.xml">suites/apiso/post/GetRecordById-brief.xml</option>
-                            <option value="tests/suites/apiso/default.cfg,suites/apiso/post/GetRecordById-full-dc.xml">suites/apiso/post/GetRecordById-full-dc.xml</option>
-                            <option value="tests/suites/apiso/default.cfg,suites/apiso/post/GetRecordById-full.xml">suites/apiso/post/GetRecordById-full.xml</option>
-                            <option value="tests/suites/apiso/default.cfg,suites/apiso/post/GetRecordById-srv-brief.xml">suites/apiso/post/GetRecordById-srv-brief.xml</option>
-                            <option value="tests/suites/apiso/default.cfg,suites/apiso/post/GetRecords-all-csw-output.xml">suites/apiso/post/GetRecords-all-csw-output.xml</option>
-                            <option value="tests/suites/apiso/default.cfg,suites/apiso/post/GetRecords-all.xml">suites/apiso/post/GetRecords-all.xml</option>
-                            <option value="tests/suites/apiso/default.cfg,suites/apiso/post/GetRecords-cql-title.xml">suites/apiso/post/GetRecords-cql-title.xml</option>
-                            <option value="tests/suites/apiso/default.cfg,suites/apiso/post/GetRecords-elementname.xml">suites/apiso/post/GetRecords-elementname.xml</option>
-                            <option value="tests/suites/apiso/default.cfg,suites/apiso/post/GetRecords-filter-and-nested-spatial-or-dateline.xml">suites/apiso/post/GetRecords-filter-and-nested-spatial-or-dateline.xml</option>
-                            <option value="tests/suites/apiso/default.cfg,suites/apiso/post/GetRecords-filter-anytext.xml">suites/apiso/post/GetRecords-filter-anytext.xml</option>
-                            <option value="tests/suites/apiso/default.cfg,suites/apiso/post/GetRecords-filter-bbox-csw-output.xml">suites/apiso/post/GetRecords-filter-bbox-csw-output.xml</option>
-                            <option value="tests/suites/apiso/default.cfg,suites/apiso/post/GetRecords-filter-bbox.xml">suites/apiso/post/GetRecords-filter-bbox.xml</option>
-                            <option value="tests/suites/apiso/default.cfg,suites/apiso/post/GetRecords-filter-servicetype.xml">suites/apiso/post/GetRecords-filter-servicetype.xml</option>
-                            <option value="tests/suites/atom/default.cfg,suites/atom/post/DescribeRecord.xml">suites/atom/post/DescribeRecord.xml</option>
-                            <option value="tests/suites/atom/default.cfg,suites/atom/post/GetCapabilities.xml">suites/atom/post/GetCapabilities.xml</option>
-                            <option value="tests/suites/atom/default.cfg,suites/atom/post/GetRecords-filter-bbox.xml">suites/atom/post/GetRecords-filter-bbox.xml</option>
-                            <option value="tests/suites/cite/default.cfg,suites/cite/data/Record_19887a8a-f6b0-4a63-ae56-7fba0e17801f.xml">suites/cite/data/Record_19887a8a-f6b0-4a63-ae56-7fba0e17801f.xml</option>
-                            <option value="tests/suites/cite/default.cfg,suites/cite/data/Record_1ef30a8b-876d-4828-9246-c37ab4510bbd.xml">suites/cite/data/Record_1ef30a8b-876d-4828-9246-c37ab4510bbd.xml</option>
-                            <option value="tests/suites/cite/default.cfg,suites/cite/data/Record_66ae76b7-54ba-489b-a582-0f0633d96493.xml">suites/cite/data/Record_66ae76b7-54ba-489b-a582-0f0633d96493.xml</option>
-                            <option value="tests/suites/cite/default.cfg,suites/cite/data/Record_6a3de50b-fa66-4b58-a0e6-ca146fdd18d4.xml">suites/cite/data/Record_6a3de50b-fa66-4b58-a0e6-ca146fdd18d4.xml</option>
-                            <option value="tests/suites/cite/default.cfg,suites/cite/data/Record_784e2afd-a9fd-44a6-9a92-a3848371c8ec.xml">suites/cite/data/Record_784e2afd-a9fd-44a6-9a92-a3848371c8ec.xml</option>
-                            <option value="tests/suites/cite/default.cfg,suites/cite/data/Record_829babb0-b2f1-49e1-8cd5-7b489fe71a1e.xml">suites/cite/data/Record_829babb0-b2f1-49e1-8cd5-7b489fe71a1e.xml</option>
-                            <option value="tests/suites/cite/default.cfg,suites/cite/data/Record_88247b56-4cbc-4df9-9860-db3f8042e357.xml">suites/cite/data/Record_88247b56-4cbc-4df9-9860-db3f8042e357.xml</option>
-                            <option value="tests/suites/cite/default.cfg,suites/cite/data/Record_94bc9c83-97f6-4b40-9eb8-a8e8787a5c63.xml">suites/cite/data/Record_94bc9c83-97f6-4b40-9eb8-a8e8787a5c63.xml</option>
-                            <option value="tests/suites/cite/default.cfg,suites/cite/data/Record_9a669547-b69b-469f-a11f-2d875366bbdc.xml">suites/cite/data/Record_9a669547-b69b-469f-a11f-2d875366bbdc.xml</option>
-                            <option value="tests/suites/cite/default.cfg,suites/cite/data/Record_a06af396-3105-442d-8b40-22b57a90d2f2.xml">suites/cite/data/Record_a06af396-3105-442d-8b40-22b57a90d2f2.xml</option>
-                            <option value="tests/suites/cite/default.cfg,suites/cite/data/Record_ab42a8c4-95e8-4630-bf79-33e59241605a.xml">suites/cite/data/Record_ab42a8c4-95e8-4630-bf79-33e59241605a.xml</option>
-                            <option value="tests/suites/cite/default.cfg,suites/cite/data/Record_e9330592-0932-474b-be34-c3a3bb67c7db.xml">suites/cite/data/Record_e9330592-0932-474b-be34-c3a3bb67c7db.xml</option>
-                            <option value="tests/suites/cite/default.cfg,suites/cite/post/0c976d98-c896-4b10-b1fe-a22ef50434e7.xml">suites/cite/post/0c976d98-c896-4b10-b1fe-a22ef50434e7.xml</option>
-                            <option value="tests/suites/cite/default.cfg,suites/cite/post/19d2a6ed-be28-4866-ae15-e3bb634486cb.xml">suites/cite/post/19d2a6ed-be28-4866-ae15-e3bb634486cb.xml</option>
-                            <option value="tests/suites/cite/default.cfg,suites/cite/post/1ab55aa3-6685-4595-8ecd-45987a7b8b59.xml">suites/cite/post/1ab55aa3-6685-4595-8ecd-45987a7b8b59.xml</option>
-                            <option value="tests/suites/cite/default.cfg,suites/cite/post/1c958b7a-ca09-4c38-98bd-ef1d1d28cc14.xml">suites/cite/post/1c958b7a-ca09-4c38-98bd-ef1d1d28cc14.xml</option>
-                            <option value="tests/suites/cite/default.cfg,suites/cite/post/1c97fc1a-61cd-4c1d-8054-933e17a6c5ee.xml">suites/cite/post/1c97fc1a-61cd-4c1d-8054-933e17a6c5ee.xml</option>
-                            <option value="tests/suites/cite/default.cfg,suites/cite/post/2102a460-5d62-465f-9668-d70b3faafbfa.xml">suites/cite/post/2102a460-5d62-465f-9668-d70b3faafbfa.xml</option>
-                            <option value="tests/suites/cite/default.cfg,suites/cite/post/225f455a-0035-486b-a94e-fee7ae881b2b.xml">suites/cite/post/225f455a-0035-486b-a94e-fee7ae881b2b.xml</option>
-                            <option value="tests/suites/cite/default.cfg,suites/cite/post/2d53ffea-60e4-4652-abf5-36eb23042fd5.xml">suites/cite/post/2d53ffea-60e4-4652-abf5-36eb23042fd5.xml</option>
-                            <option value="tests/suites/cite/default.cfg,suites/cite/post/34a019a9-1581-42cb-9827-fbfdda2773b7.xml">suites/cite/post/34a019a9-1581-42cb-9827-fbfdda2773b7.xml</option>
-                            <option value="tests/suites/cite/default.cfg,suites/cite/post/3e76fd38-e035-41c9-83dc-61356f680c97.xml">suites/cite/post/3e76fd38-e035-41c9-83dc-61356f680c97.xml</option>
-                            <option value="tests/suites/cite/default.cfg,suites/cite/post/418a6fb0-a89c-4a94-afc9-3f8168eb2980.xml">suites/cite/post/418a6fb0-a89c-4a94-afc9-3f8168eb2980.xml</option>
-                            <option value="tests/suites/cite/default.cfg,suites/cite/post/420b745e-0c4b-404e-9f2d-61fa580ff05a.xml">suites/cite/post/420b745e-0c4b-404e-9f2d-61fa580ff05a.xml</option>
-                            <option value="tests/suites/cite/default.cfg,suites/cite/post/4735d649-a2b1-42fd-a101-14e1d7e4607f.xml">suites/cite/post/4735d649-a2b1-42fd-a101-14e1d7e4607f.xml</option>
-                            <option value="tests/suites/cite/default.cfg,suites/cite/post/5c5861bc-f742-40a5-9998-5342615d674b.xml">suites/cite/post/5c5861bc-f742-40a5-9998-5342615d674b.xml</option>
-                            <option value="tests/suites/cite/default.cfg,suites/cite/post/6e736fd0-c266-4852-9eb3-0656f5d0f5c4.xml">suites/cite/post/6e736fd0-c266-4852-9eb3-0656f5d0f5c4.xml</option>
-                            <option value="tests/suites/cite/default.cfg,suites/cite/post/73f1551c-e269-4ef9-9dae-e535b5eebfc7.xml">suites/cite/post/73f1551c-e269-4ef9-9dae-e535b5eebfc7.xml</option>
-                            <option value="tests/suites/cite/default.cfg,suites/cite/post/78297c88-4850-4927-adc6-511cd9a3d539.xml">suites/cite/post/78297c88-4850-4927-adc6-511cd9a3d539.xml</option>
-                            <option value="tests/suites/cite/default.cfg,suites/cite/post/7c89cdf5-0def-4cfb-8c55-2b8ffea5d92f.xml">suites/cite/post/7c89cdf5-0def-4cfb-8c55-2b8ffea5d92f.xml</option>
-                            <option value="tests/suites/cite/default.cfg,suites/cite/post/7e2cd105-daec-4d25-bc8e-d49d21364912.xml">suites/cite/post/7e2cd105-daec-4d25-bc8e-d49d21364912.xml</option>
-                            <option value="tests/suites/cite/default.cfg,suites/cite/post/87f2f670-9cd6-4907-b82c-1b46a7dd2a78.xml">suites/cite/post/87f2f670-9cd6-4907-b82c-1b46a7dd2a78.xml</option>
-                            <option value="tests/suites/cite/default.cfg,suites/cite/post/88b4e1ba-3bd4-4cbe-81e5-e004056d6ca3.xml">suites/cite/post/88b4e1ba-3bd4-4cbe-81e5-e004056d6ca3.xml</option>
-                            <option value="tests/suites/cite/default.cfg,suites/cite/post/898cd63b-2585-4ec0-8720-d554bd324174.xml">suites/cite/post/898cd63b-2585-4ec0-8720-d554bd324174.xml</option>
-                            <option value="tests/suites/cite/default.cfg,suites/cite/post/8fb13dc3-5818-45e2-9e29-46abc16e7d38.xml">suites/cite/post/8fb13dc3-5818-45e2-9e29-46abc16e7d38.xml</option>
-                            <option value="tests/suites/cite/default.cfg,suites/cite/post/928c1896-52d4-4ac7-9832-f98e3eb65f02.xml">suites/cite/post/928c1896-52d4-4ac7-9832-f98e3eb65f02.xml</option>
-                            <option value="tests/suites/cite/default.cfg,suites/cite/post/93bdbb9d-2734-4f01-92fb-48634cca41de.xml">suites/cite/post/93bdbb9d-2734-4f01-92fb-48634cca41de.xml</option>
-                            <option value="tests/suites/cite/default.cfg,suites/cite/post/948b39d5-bb4f-45b8-a8f2-4ff9501aaedd.xml">suites/cite/post/948b39d5-bb4f-45b8-a8f2-4ff9501aaedd.xml</option>
-                            <option value="tests/suites/cite/default.cfg,suites/cite/post/9fd64fcc-f69c-4626-b72e-5c7776a29aa9.xml">suites/cite/post/9fd64fcc-f69c-4626-b72e-5c7776a29aa9.xml</option>
-                            <option value="tests/suites/cite/default.cfg,suites/cite/post/a06d04ab-e0d0-4a86-bfe8-71460f41fe37.xml">suites/cite/post/a06d04ab-e0d0-4a86-bfe8-71460f41fe37.xml</option>
-                            <option value="tests/suites/cite/default.cfg,suites/cite/post/ad61686c-d304-42d1-b845-8c1f3070c83e.xml">suites/cite/post/ad61686c-d304-42d1-b845-8c1f3070c83e.xml</option>
-                            <option value="tests/suites/cite/default.cfg,suites/cite/post/af39c020-7b1d-429c-b474-f45c3164cb79.xml">suites/cite/post/af39c020-7b1d-429c-b474-f45c3164cb79.xml</option>
-                            <option value="tests/suites/cite/default.cfg,suites/cite/post/b90e2de6-3d25-4298-a13e-dc9492a8fc73.xml">suites/cite/post/b90e2de6-3d25-4298-a13e-dc9492a8fc73.xml</option>
-                            <option value="tests/suites/cite/default.cfg,suites/cite/post/ba9b0107-dcee-46ef-823a-a2e25a911a96.xml">suites/cite/post/ba9b0107-dcee-46ef-823a-a2e25a911a96.xml</option>
-                            <option value="tests/suites/cite/default.cfg,suites/cite/post/bb66ebc5-7121-48b5-9f53-b56537d9561b.xml">suites/cite/post/bb66ebc5-7121-48b5-9f53-b56537d9561b.xml</option>
-                            <option value="tests/suites/cite/default.cfg,suites/cite/post/c02d1c85-df9f-45ee-bea7-345c35e02a98.xml">suites/cite/post/c02d1c85-df9f-45ee-bea7-345c35e02a98.xml</option>
-                            <option value="tests/suites/cite/default.cfg,suites/cite/post/c311a342-72e3-4983-be39-868e6ed9740f.xml">suites/cite/post/c311a342-72e3-4983-be39-868e6ed9740f.xml</option>
-                            <option value="tests/suites/cite/default.cfg,suites/cite/post/c38916c2-4bc6-446d-b7aa-ab006d6ba31c.xml">suites/cite/post/c38916c2-4bc6-446d-b7aa-ab006d6ba31c.xml</option>
-                            <option value="tests/suites/cite/default.cfg,suites/cite/post/c8588f47-8e65-45f5-ad34-ff4524cad84d.xml">suites/cite/post/c8588f47-8e65-45f5-ad34-ff4524cad84d.xml</option>
-                            <option value="tests/suites/cite/default.cfg,suites/cite/post/da228d4c-e1be-43d7-9ccb-c3f27ee32541.xml">suites/cite/post/da228d4c-e1be-43d7-9ccb-c3f27ee32541.xml</option>
-                            <option value="tests/suites/cite/default.cfg,suites/cite/post/dc92c2c4-87d8-4a13-964e-ff9b0e0c27b3.xml">suites/cite/post/dc92c2c4-87d8-4a13-964e-ff9b0e0c27b3.xml</option>
-                            <option value="tests/suites/cite/default.cfg,suites/cite/post/dcb13791-379e-4739-bcd4-dbaa69f0efdb.xml">suites/cite/post/dcb13791-379e-4739-bcd4-dbaa69f0efdb.xml</option>
-                            <option value="tests/suites/cite/default.cfg,suites/cite/post/e308f030-c097-4036-a838-44bad74c9ef7.xml">suites/cite/post/e308f030-c097-4036-a838-44bad74c9ef7.xml</option>
-                            <option value="tests/suites/cite/default.cfg,suites/cite/post/e6e9efb2-e2b7-4b0a-a3a2-7deea3f9b8e2.xml">suites/cite/post/e6e9efb2-e2b7-4b0a-a3a2-7deea3f9b8e2.xml</option>
-                            <option value="tests/suites/cite/default.cfg,suites/cite/post/f7976c55-a156-4421-8199-bc0487da4b0f.xml">suites/cite/post/f7976c55-a156-4421-8199-bc0487da4b0f.xml</option>
-                            <option value="tests/suites/cite/default.cfg,suites/cite/post/f7d79701-f10b-4087-a33c-f62df0a04fd1.xml">suites/cite/post/f7d79701-f10b-4087-a33c-f62df0a04fd1.xml</option>
-                            <option value="tests/suites/cite/default.cfg,suites/cite/post/fc1bc094-88f1-4851-bc2b-dfc56be9f3c7.xml">suites/cite/post/fc1bc094-88f1-4851-bc2b-dfc56be9f3c7.xml</option>
-                            <option value="tests/suites/cite/default.cfg,suites/cite/post/fe20960f-a26c-4f13-852d-470a0d3233f9.xml">suites/cite/post/fe20960f-a26c-4f13-852d-470a0d3233f9.xml</option>
-                            <option value="tests/suites/csw30/default.cfg,suites/csw30/post/Exception-GetDomain-parametername-bad.xml">suites/csw30/post/Exception-GetDomain-parametername-bad.xml</option>
-                            <option value="tests/suites/csw30/default.cfg,suites/csw30/post/Exception-GetDomain-valuereference-bad.xml">suites/csw30/post/Exception-GetDomain-valuereference-bad.xml</option>
-                            <option value="tests/suites/csw30/default.cfg,suites/csw30/post/Exception-GetRecordById-404.xml">suites/csw30/post/Exception-GetRecordById-404.xml</option>
-                            <option value="tests/suites/csw30/default.cfg,suites/csw30/post/Exception-GetRecordById-bad-esn.xml">suites/csw30/post/Exception-GetRecordById-bad-esn.xml</option>
-                            <option value="tests/suites/csw30/default.cfg,suites/csw30/post/Exception-bad-xml.xml">suites/csw30/post/Exception-bad-xml.xml</option>
-                            <option value="tests/suites/csw30/default.cfg,suites/csw30/post/Exception-not-xml.xml">suites/csw30/post/Exception-not-xml.xml</option>
-                            <option value="tests/suites/csw30/default.cfg,suites/csw30/post/GetCapabilities.xml">suites/csw30/post/GetCapabilities.xml</option>
-                            <option value="tests/suites/csw30/default.cfg,suites/csw30/post/GetDomain-parametername.xml">suites/csw30/post/GetDomain-parametername.xml</option>
-                            <option value="tests/suites/csw30/default.cfg,suites/csw30/post/GetDomain-valuereference.xml">suites/csw30/post/GetDomain-valuereference.xml</option>
-                            <option value="tests/suites/csw30/default.cfg,suites/csw30/post/GetRecordById-dc-full.xml">suites/csw30/post/GetRecordById-dc-full.xml</option>
-                            <option value="tests/suites/csw30/default.cfg,suites/csw30/post/GetRecordById-dc.xml">suites/csw30/post/GetRecordById-dc.xml</option>
-                            <option value="tests/suites/default/default.cfg,suites/default/post/DescribeRecord-json.xml">suites/default/post/DescribeRecord-json.xml</option>
-                            <option value="tests/suites/default/default.cfg,suites/default/post/DescribeRecord.xml">suites/default/post/DescribeRecord.xml</option>
-                            <option value="tests/suites/default/default.cfg,suites/default/post/Exception-GetRecords-badsrsname.xml">suites/default/post/Exception-GetRecords-badsrsname.xml</option>
-                            <option value="tests/suites/default/default.cfg,suites/default/post/Exception-GetRecords-elementname.xml">suites/default/post/Exception-GetRecords-elementname.xml</option>
-                            <option value="tests/suites/default/default.cfg,suites/default/post/Exception-GetRecords-invalid-xml.xml">suites/default/post/Exception-GetRecords-invalid-xml.xml</option>
-                            <option value="tests/suites/default/default.cfg,suites/default/post/GetCapabilities-SOAP.xml">suites/default/post/GetCapabilities-SOAP.xml</option>
-                            <option value="tests/suites/default/default.cfg,suites/default/post/GetCapabilities-sections.xml">suites/default/post/GetCapabilities-sections.xml</option>
-                            <option value="tests/suites/default/default.cfg,suites/default/post/GetCapabilities-updatesequence.xml">suites/default/post/GetCapabilities-updatesequence.xml</option>
-                            <option value="tests/suites/default/default.cfg,suites/default/post/GetCapabilities.xml">suites/default/post/GetCapabilities.xml</option>
-                            <option value="tests/suites/default/default.cfg,suites/default/post/GetDomain-parameter.xml">suites/default/post/GetDomain-parameter.xml</option>
-                            <option value="tests/suites/default/default.cfg,suites/default/post/GetDomain-property.xml">suites/default/post/GetDomain-property.xml</option>
-                            <option value="tests/suites/default/default.cfg,suites/default/post/GetRecordById-json.xml">suites/default/post/GetRecordById-json.xml</option>
-                            <option value="tests/suites/default/default.cfg,suites/default/post/GetRecordById.xml">suites/default/post/GetRecordById.xml</option>
-                            <option value="tests/suites/default/default.cfg,suites/default/post/GetRecords-all-json.xml">suites/default/post/GetRecords-all-json.xml</option>
-                            <option value="tests/suites/default/default.cfg,suites/default/post/GetRecords-all-resulttype-hits.xml">suites/default/post/GetRecords-all-resulttype-hits.xml</option>
-                            <option value="tests/suites/default/default.cfg,suites/default/post/GetRecords-all-resulttype-validate.xml">suites/default/post/GetRecords-all-resulttype-validate.xml</option>
-                            <option value="tests/suites/default/default.cfg,suites/default/post/GetRecords-all-sortby-bbox.xml">suites/default/post/GetRecords-all-sortby-bbox.xml</option>
-                            <option value="tests/suites/default/default.cfg,suites/default/post/GetRecords-all.xml">suites/default/post/GetRecords-all.xml</option>
-                            <option value="tests/suites/default/default.cfg,suites/default/post/GetRecords-bbox-filter-crs84.xml">suites/default/post/GetRecords-bbox-filter-crs84.xml</option>
-                            <option value="tests/suites/default/default.cfg,suites/default/post/GetRecords-cql-title-and-abstract.xml">suites/default/post/GetRecords-cql-title-and-abstract.xml</option>
-                            <option value="tests/suites/default/default.cfg,suites/default/post/GetRecords-cql-title.xml">suites/default/post/GetRecords-cql-title.xml</option>
-                            <option value="tests/suites/default/default.cfg,suites/default/post/GetRecords-distributedsearch.xml">suites/default/post/GetRecords-distributedsearch.xml</option>
-                            <option value="tests/suites/default/default.cfg,suites/default/post/GetRecords-elementname.xml">suites/default/post/GetRecords-elementname.xml</option>
-                            <option value="tests/suites/default/default.cfg,suites/default/post/GetRecords-end.xml">suites/default/post/GetRecords-end.xml</option>
-                            <option value="tests/suites/default/default.cfg,suites/default/post/GetRecords-filter-and-bbox-freetext.xml">suites/default/post/GetRecords-filter-and-bbox-freetext.xml</option>
-                            <option value="tests/suites/default/default.cfg,suites/default/post/GetRecords-filter-and-nested-or.xml">suites/default/post/GetRecords-filter-and-nested-or.xml</option>
-                            <option value="tests/suites/default/default.cfg,suites/default/post/GetRecords-filter-and-nested-or2.xml">suites/default/post/GetRecords-filter-and-nested-or2.xml</option>
-                            <option value="tests/suites/default/default.cfg,suites/default/post/GetRecords-filter-anytext-and-not.xml">suites/default/post/GetRecords-filter-anytext-and-not.xml</option>
-                            <option value="tests/suites/default/default.cfg,suites/default/post/GetRecords-filter-anytext-equal.xml">suites/default/post/GetRecords-filter-anytext-equal.xml</option>
-                            <option value="tests/suites/default/default.cfg,suites/default/post/GetRecords-filter-anytext.xml">suites/default/post/GetRecords-filter-anytext.xml</option>
-                            <option value="tests/suites/default/default.cfg,suites/default/post/GetRecords-filter-bbox-reproject.xml">suites/default/post/GetRecords-filter-bbox-reproject.xml</option>
-                            <option value="tests/suites/default/default.cfg,suites/default/post/GetRecords-filter-bbox-sortby.xml">suites/default/post/GetRecords-filter-bbox-sortby.xml</option>
-                            <option value="tests/suites/default/default.cfg,suites/default/post/GetRecords-filter-bbox.xml">suites/default/post/GetRecords-filter-bbox.xml</option>
-                            <option value="tests/suites/default/default.cfg,suites/default/post/GetRecords-filter-between.xml">suites/default/post/GetRecords-filter-between.xml</option>
-                            <option value="tests/suites/default/default.cfg,suites/default/post/GetRecords-filter-function-bad.xml">suites/default/post/GetRecords-filter-function-bad.xml</option>
-                            <option value="tests/suites/default/default.cfg,suites/default/post/GetRecords-filter-function.xml">suites/default/post/GetRecords-filter-function.xml</option>
-                            <option value="tests/suites/default/default.cfg,suites/default/post/GetRecords-filter-not-bbox.xml">suites/default/post/GetRecords-filter-not-bbox.xml</option>
-                            <option value="tests/suites/default/default.cfg,suites/default/post/GetRecords-filter-or-bbox-freetext.xml">suites/default/post/GetRecords-filter-or-bbox-freetext.xml</option>
-                            <option value="tests/suites/default/default.cfg,suites/default/post/GetRecords-filter-or-nested-and.xml">suites/default/post/GetRecords-filter-or-nested-and.xml</option>
-                            <option value="tests/suites/default/default.cfg,suites/default/post/GetRecords-filter-or-title-abstract.xml">suites/default/post/GetRecords-filter-or-title-abstract.xml</option>
-                            <option value="tests/suites/default/default.cfg,suites/default/post/GetRecords-maxrecords.xml">suites/default/post/GetRecords-maxrecords.xml</option>
-                            <option value="tests/suites/default/default.cfg,suites/default/post/GetRecords-requestid.xml">suites/default/post/GetRecords-requestid.xml</option>
-                            <option value="tests/suites/default/default.cfg,suites/default/post/Harvest-default.xml">suites/default/post/Harvest-default.xml</option>
-                            <option value="tests/suites/default/default.cfg,suites/default/post/Harvest-response-handler.xml">suites/default/post/Harvest-response-handler.xml</option>
-                            <option value="tests/suites/default/default.cfg,suites/default/post/Transaction-delete.xml">suites/default/post/Transaction-delete.xml</option>
-                            <option value="tests/suites/default/default.cfg,suites/default/post/Transaction-insert.xml">suites/default/post/Transaction-insert.xml</option>
-                            <option value="tests/suites/default/default.cfg,suites/default/post/Transaction-update-full.xml">suites/default/post/Transaction-update-full.xml</option>
-                            <option value="tests/suites/default/default.cfg,suites/default/post/Transaction-update-recordproperty.xml">suites/default/post/Transaction-update-recordproperty.xml</option>
-                            <option value="tests/suites/dif/default.cfg,suites/dif/post/DescribeRecord.xml">suites/dif/post/DescribeRecord.xml</option>
-                            <option value="tests/suites/dif/default.cfg,suites/dif/post/GetCapabilities.xml">suites/dif/post/GetCapabilities.xml</option>
-                            <option value="tests/suites/dif/default.cfg,suites/dif/post/GetRecords-filter-bbox.xml">suites/dif/post/GetRecords-filter-bbox.xml</option>
-                            <option value="tests/suites/ebrim/default.cfg,suites/ebrim/post/DescribeRecord.xml">suites/ebrim/post/DescribeRecord.xml</option>
-                            <option value="tests/suites/ebrim/default.cfg,suites/ebrim/post/GetCapabilities.xml">suites/ebrim/post/GetCapabilities.xml</option>
-                            <option value="tests/suites/ebrim/default.cfg,suites/ebrim/post/GetRecords-filter-bbox-full.xml">suites/ebrim/post/GetRecords-filter-bbox-full.xml</option>
-                            <option value="tests/suites/ebrim/default.cfg,suites/ebrim/post/GetRecords-filter-bbox.xml">suites/ebrim/post/GetRecords-filter-bbox.xml</option>
-                            <option value="tests/suites/fgdc/default.cfg,suites/fgdc/post/DescribeRecord.xml">suites/fgdc/post/DescribeRecord.xml</option>
-                            <option value="tests/suites/fgdc/default.cfg,suites/fgdc/post/GetCapabilities.xml">suites/fgdc/post/GetCapabilities.xml</option>
-                            <option value="tests/suites/fgdc/default.cfg,suites/fgdc/post/GetRecords-filter-bbox.xml">suites/fgdc/post/GetRecords-filter-bbox.xml</option>
-                            <option value="tests/suites/gm03/default.cfg,suites/gm03/post/GetCapabilities.xml">suites/gm03/post/GetCapabilities.xml</option>
-                            <option value="tests/suites/gm03/default.cfg,suites/gm03/post/GetRecords-filter-bbox.xml">suites/gm03/post/GetRecords-filter-bbox.xml</option>
-                            <option value="tests/suites/harvesting/default.cfg,suites/harvesting/post/Clear-000-delete-all.xml">suites/harvesting/post/Clear-000-delete-all.xml</option>
-                            <option value="tests/suites/harvesting/default.cfg,suites/harvesting/post/Exception-Havest-csw-404.xml">suites/harvesting/post/Exception-Havest-csw-404.xml</option>
-                            <option value="tests/suites/harvesting/default.cfg,suites/harvesting/post/GetCapabilities.xml">suites/harvesting/post/GetCapabilities.xml</option>
-                            <option value="tests/suites/harvesting/default.cfg,suites/harvesting/post/GetDomain-parameter.xml">suites/harvesting/post/GetDomain-parameter.xml</option>
-                            <option value="tests/suites/harvesting/default.cfg,suites/harvesting/post/Harvest-csw-iso.xml">suites/harvesting/post/Harvest-csw-iso.xml</option>
-                            <option value="tests/suites/harvesting/default.cfg,suites/harvesting/post/Harvest-csw-run1.xml">suites/harvesting/post/Harvest-csw-run1.xml</option>
-                            <option value="tests/suites/harvesting/default.cfg,suites/harvesting/post/Harvest-csw-run2.xml">suites/harvesting/post/Harvest-csw-run2.xml</option>
-                            <option value="tests/suites/harvesting/default.cfg,suites/harvesting/post/Harvest-dc.xml">suites/harvesting/post/Harvest-dc.xml</option>
-                            <option value="tests/suites/harvesting/default.cfg,suites/harvesting/post/Harvest-fgdc.xml">suites/harvesting/post/Harvest-fgdc.xml</option>
-                            <option value="tests/suites/harvesting/default.cfg,suites/harvesting/post/Harvest-iso.xml">suites/harvesting/post/Harvest-iso.xml</option>
-                            <option value="tests/suites/harvesting/default.cfg,suites/harvesting/post/Harvest-rdf.xml">suites/harvesting/post/Harvest-rdf.xml</option>
-                            <option value="tests/suites/harvesting/default.cfg,suites/harvesting/post/Harvest-sos100.xml">suites/harvesting/post/Harvest-sos100.xml</option>
-                            <option value="tests/suites/harvesting/default.cfg,suites/harvesting/post/Harvest-sos200.xml">suites/harvesting/post/Harvest-sos200.xml</option>
-                            <option value="tests/suites/harvesting/default.cfg,suites/harvesting/post/Harvest-waf.xml">suites/harvesting/post/Harvest-waf.xml</option>
-                            <option value="tests/suites/harvesting/default.cfg,suites/harvesting/post/Harvest-wcs.xml">suites/harvesting/post/Harvest-wcs.xml</option>
-                            <option value="tests/suites/harvesting/default.cfg,suites/harvesting/post/Harvest-wfs.xml">suites/harvesting/post/Harvest-wfs.xml</option>
-                            <option value="tests/suites/harvesting/default.cfg,suites/harvesting/post/Harvest-wms-run1.xml">suites/harvesting/post/Harvest-wms-run1.xml</option>
-                            <option value="tests/suites/harvesting/default.cfg,suites/harvesting/post/Harvest-wms-run2.xml">suites/harvesting/post/Harvest-wms-run2.xml</option>
-                            <option value="tests/suites/harvesting/default.cfg,suites/harvesting/post/Harvest-wmts.xml">suites/harvesting/post/Harvest-wmts.xml</option>
-                            <option value="tests/suites/harvesting/default.cfg,suites/harvesting/post/Harvest-wps.xml">suites/harvesting/post/Harvest-wps.xml</option>
-                            <option value="tests/suites/harvesting/default.cfg,suites/harvesting/post/Harvest-zzz-post-GetRecords-filter-ows-dc.xml">suites/harvesting/post/Harvest-zzz-post-GetRecords-filter-ows-dc.xml</option>
-                            <option value="tests/suites/harvesting/default.cfg,suites/harvesting/post/Harvest-zzz-post-GetRecords-filter-sos-abstract-dc.xml">suites/harvesting/post/Harvest-zzz-post-GetRecords-filter-sos-abstract-dc.xml</option>
-                            <option value="tests/suites/harvesting/default.cfg,suites/harvesting/post/Harvest-zzz-post-GetRecords-filter-sos-dc.xml">suites/harvesting/post/Harvest-zzz-post-GetRecords-filter-sos-dc.xml</option>
-                            <option value="tests/suites/harvesting/default.cfg,suites/harvesting/post/Harvest-zzz-post-GetRecords-filter-sos-iso.xml">suites/harvesting/post/Harvest-zzz-post-GetRecords-filter-sos-iso.xml</option>
-                            <option value="tests/suites/harvesting/default.cfg,suites/harvesting/post/Harvest-zzz-post-GetRecords-filter-wfs-iso.xml">suites/harvesting/post/Harvest-zzz-post-GetRecords-filter-wfs-iso.xml</option>
-                            <option value="tests/suites/harvesting/default.cfg,suites/harvesting/post/Harvest-zzz-post-GetRecords-filter-wms-dc.xml">suites/harvesting/post/Harvest-zzz-post-GetRecords-filter-wms-dc.xml</option>
-                            <option value="tests/suites/harvesting/default.cfg,suites/harvesting/post/Harvest-zzz-post-GetRecords-filter-wms-iso.xml">suites/harvesting/post/Harvest-zzz-post-GetRecords-filter-wms-iso.xml</option>
-                            <option value="tests/suites/harvesting/default.cfg,suites/harvesting/post/Harvest-zzz-post-GetRecords-filter-wms-layer.xml">suites/harvesting/post/Harvest-zzz-post-GetRecords-filter-wms-layer.xml</option>
-                            <option value="tests/suites/harvesting/default.cfg,suites/harvesting/post/Transaction-000-delete-all.xml">suites/harvesting/post/Transaction-000-delete-all.xml</option>
-                            <option value="tests/suites/manager/default.cfg,suites/manager/post/Clear-000-delete-all.xml">suites/manager/post/Clear-000-delete-all.xml</option>
-                            <option value="tests/suites/manager/default.cfg,suites/manager/post/GetCapabilities.xml">suites/manager/post/GetCapabilities.xml</option>
-                            <option value="tests/suites/manager/default.cfg,suites/manager/post/GetDomain-parameter.xml">suites/manager/post/GetDomain-parameter.xml</option>
-                            <option value="tests/suites/manager/default.cfg,suites/manager/post/Transaction-000-delete-all.xml">suites/manager/post/Transaction-000-delete-all.xml</option>
-                            <option value="tests/suites/manager/default.cfg,suites/manager/post/Transaction-dc-01-insert.xml">suites/manager/post/Transaction-dc-01-insert.xml</option>
-                            <option value="tests/suites/manager/default.cfg,suites/manager/post/Transaction-dc-02-update-full.xml">suites/manager/post/Transaction-dc-02-update-full.xml</option>
-                            <option value="tests/suites/manager/default.cfg,suites/manager/post/Transaction-fgdc-01-insert.xml">suites/manager/post/Transaction-fgdc-01-insert.xml</option>
-                            <option value="tests/suites/manager/default.cfg,suites/manager/post/Transaction-fgdc-02-update-recprop.xml">suites/manager/post/Transaction-fgdc-02-update-recprop.xml</option>
-                            <option value="tests/suites/manager/default.cfg,suites/manager/post/Transaction-fgdc-03-delete-all.xml">suites/manager/post/Transaction-fgdc-03-delete-all.xml</option>
-                            <option value="tests/suites/manager/default.cfg,suites/manager/post/Transaction-iso-00-delete-all.xml">suites/manager/post/Transaction-iso-00-delete-all.xml</option>
-                            <option value="tests/suites/manager/default.cfg,suites/manager/post/Transaction-iso-01-insert.xml">suites/manager/post/Transaction-iso-01-insert.xml</option>
-                            <option value="tests/suites/manager/default.cfg,suites/manager/post/Transaction-iso-02-update-full.xml">suites/manager/post/Transaction-iso-02-update-full.xml</option>
-                            <option value="tests/suites/manager/default.cfg,suites/manager/post/Transaction-iso-03-update-recprop.xml">suites/manager/post/Transaction-iso-03-update-recprop.xml</option>
-                            <option value="tests/suites/manager/default.cfg,suites/manager/post/Transaction-iso-04-update-recprop-no-matches.xml">suites/manager/post/Transaction-iso-04-update-recprop-no-matches.xml</option>
-                            <option value="tests/suites/manager/default.cfg,suites/manager/post/Transaction-iso-05-delete.xml">suites/manager/post/Transaction-iso-05-delete.xml</option>
-                            <option value="tests/suites/manager/default.cfg,suites/manager/post/Transaction-xxx-delete-all.xml">suites/manager/post/Transaction-xxx-delete-all.xml</option>
-                            <option value="tests/suites/repofilter/default.cfg,suites/repofilter/post/GetRecordById-masked.xml">suites/repofilter/post/GetRecordById-masked.xml</option>
-                            <option value="tests/suites/repofilter/default.cfg,suites/repofilter/post/GetRecords-all.xml">suites/repofilter/post/GetRecords-all.xml</option>
-                            <option value="tests/suites/utf-8/default.cfg,suites/utf-8/post/GetCapabilities.xml">suites/utf-8/post/GetCapabilities.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/fgdc/expected/post_GetRecords-filter-bbox.xml">functionaltests/suites/fgdc/expected/post_GetRecords-filter-bbox.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/fgdc/expected/post_DescribeRecord.xml">functionaltests/suites/fgdc/expected/post_DescribeRecord.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/fgdc/expected/post_GetCapabilities.xml">functionaltests/suites/fgdc/expected/post_GetCapabilities.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/fgdc/post/DescribeRecord.xml">functionaltests/suites/fgdc/post/DescribeRecord.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/fgdc/post/GetCapabilities.xml">functionaltests/suites/fgdc/post/GetCapabilities.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/fgdc/post/GetRecords-filter-bbox.xml">functionaltests/suites/fgdc/post/GetRecords-filter-bbox.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/harvesting/expected/post_Harvest-csw-iso.xml">functionaltests/suites/harvesting/expected/post_Harvest-csw-iso.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/harvesting/expected/post_Harvest-wfs200.xml">functionaltests/suites/harvesting/expected/post_Harvest-wfs200.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/harvesting/expected/get_Exception-Harvest-missing-source.xml">functionaltests/suites/harvesting/expected/get_Exception-Harvest-missing-source.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/harvesting/expected/post_Harvest-wfs110.xml">functionaltests/suites/harvesting/expected/post_Harvest-wfs110.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/harvesting/expected/get_Exception-Harvest-waf-bad-value.xml">functionaltests/suites/harvesting/expected/get_Exception-Harvest-waf-bad-value.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/harvesting/expected/post_Exception-Havest-csw-404.xml">functionaltests/suites/harvesting/expected/post_Exception-Havest-csw-404.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/harvesting/expected/post_Harvest-fgdc.xml">functionaltests/suites/harvesting/expected/post_Harvest-fgdc.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/harvesting/expected/post_Harvest-wms-run2.xml">functionaltests/suites/harvesting/expected/post_Harvest-wms-run2.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/harvesting/expected/post_Transaction-000-delete-all.xml">functionaltests/suites/harvesting/expected/post_Transaction-000-delete-all.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/harvesting/expected/post_Harvest-csw-run1.xml">functionaltests/suites/harvesting/expected/post_Harvest-csw-run1.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/harvesting/expected/post_Harvest-csw-run2.xml">functionaltests/suites/harvesting/expected/post_Harvest-csw-run2.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/harvesting/expected/post_Harvest-wmts.xml">functionaltests/suites/harvesting/expected/post_Harvest-wmts.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/harvesting/expected/post_Harvest-zzz-post-GetRecords-filter-wps-process.xml">functionaltests/suites/harvesting/expected/post_Harvest-zzz-post-GetRecords-filter-wps-process.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/harvesting/expected/post_Harvest-wps.xml">functionaltests/suites/harvesting/expected/post_Harvest-wps.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/harvesting/expected/post_Harvest-zzz-post-GetRecords-filter-ows-dc.xml">functionaltests/suites/harvesting/expected/post_Harvest-zzz-post-GetRecords-filter-ows-dc.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/harvesting/expected/post_Clear-000-delete-all.xml">functionaltests/suites/harvesting/expected/post_Clear-000-delete-all.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/harvesting/expected/get_Exception-Harvest-missing-resourcetype.xml">functionaltests/suites/harvesting/expected/get_Exception-Harvest-missing-resourcetype.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/harvesting/expected/post_Harvest-zzz-post-GetRecords-filter-wms-iso.xml">functionaltests/suites/harvesting/expected/post_Harvest-zzz-post-GetRecords-filter-wms-iso.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/harvesting/expected/post_Harvest-waf.xml">functionaltests/suites/harvesting/expected/post_Harvest-waf.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/harvesting/expected/post_Harvest-zzz-post-GetRecords-filter-sos-dc.xml">functionaltests/suites/harvesting/expected/post_Harvest-zzz-post-GetRecords-filter-sos-dc.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/harvesting/expected/post_GetCapabilities.xml">functionaltests/suites/harvesting/expected/post_GetCapabilities.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/harvesting/expected/post_Harvest-wcs.xml">functionaltests/suites/harvesting/expected/post_Harvest-wcs.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/harvesting/expected/post_Harvest-dc.xml">functionaltests/suites/harvesting/expected/post_Harvest-dc.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/harvesting/expected/post_Harvest-rdf.xml">functionaltests/suites/harvesting/expected/post_Harvest-rdf.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/harvesting/expected/post_GetDomain-parameter.xml">functionaltests/suites/harvesting/expected/post_GetDomain-parameter.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/harvesting/expected/post_Harvest-sos100.xml">functionaltests/suites/harvesting/expected/post_Harvest-sos100.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/harvesting/expected/get_Exception-Harvest-invalid-resourcetype.xml">functionaltests/suites/harvesting/expected/get_Exception-Harvest-invalid-resourcetype.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/harvesting/expected/post_Harvest-sos200.xml">functionaltests/suites/harvesting/expected/post_Harvest-sos200.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/harvesting/expected/post_Harvest-zzz-post-GetRecords-filter-wms-dc.xml">functionaltests/suites/harvesting/expected/post_Harvest-zzz-post-GetRecords-filter-wms-dc.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/harvesting/expected/post_Harvest-wms-run1.xml">functionaltests/suites/harvesting/expected/post_Harvest-wms-run1.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/harvesting/expected/post_Harvest-zzz-post-GetRecords-filter-sos-abstract-dc.xml">functionaltests/suites/harvesting/expected/post_Harvest-zzz-post-GetRecords-filter-sos-abstract-dc.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/harvesting/expected/post_Harvest-zzz-post-GetRecords-filter-wfs-iso.xml">functionaltests/suites/harvesting/expected/post_Harvest-zzz-post-GetRecords-filter-wfs-iso.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/harvesting/expected/post_Harvest-iso.xml">functionaltests/suites/harvesting/expected/post_Harvest-iso.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/harvesting/expected/post_Harvest-zzz-post-GetRecords-filter-wms-layer.xml">functionaltests/suites/harvesting/expected/post_Harvest-zzz-post-GetRecords-filter-wms-layer.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/harvesting/expected/post_Harvest-zzz-post-GetRecords-filter-sos-iso.xml">functionaltests/suites/harvesting/expected/post_Harvest-zzz-post-GetRecords-filter-sos-iso.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/harvesting/expected/get_Exception-Harvest-waf-no-records-found.xml">functionaltests/suites/harvesting/expected/get_Exception-Harvest-waf-no-records-found.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/harvesting/post/Harvest-dc.xml">functionaltests/suites/harvesting/post/Harvest-dc.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/harvesting/post/Harvest-wfs200.xml">functionaltests/suites/harvesting/post/Harvest-wfs200.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/harvesting/post/Harvest-zzz-post-GetRecords-filter-wps-process.xml">functionaltests/suites/harvesting/post/Harvest-zzz-post-GetRecords-filter-wps-process.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/harvesting/post/Harvest-zzz-post-GetRecords-filter-sos-abstract-dc.xml">functionaltests/suites/harvesting/post/Harvest-zzz-post-GetRecords-filter-sos-abstract-dc.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/harvesting/post/Harvest-zzz-post-GetRecords-filter-wms-layer.xml">functionaltests/suites/harvesting/post/Harvest-zzz-post-GetRecords-filter-wms-layer.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/harvesting/post/Harvest-zzz-post-GetRecords-filter-wfs-iso.xml">functionaltests/suites/harvesting/post/Harvest-zzz-post-GetRecords-filter-wfs-iso.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/harvesting/post/Harvest-rdf.xml">functionaltests/suites/harvesting/post/Harvest-rdf.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/harvesting/post/Harvest-sos200.xml">functionaltests/suites/harvesting/post/Harvest-sos200.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/harvesting/post/Harvest-zzz-post-GetRecords-filter-wms-dc.xml">functionaltests/suites/harvesting/post/Harvest-zzz-post-GetRecords-filter-wms-dc.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/harvesting/post/Harvest-wmts.xml">functionaltests/suites/harvesting/post/Harvest-wmts.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/harvesting/post/Exception-Havest-csw-404.xml">functionaltests/suites/harvesting/post/Exception-Havest-csw-404.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/harvesting/post/Harvest-wms-run2.xml">functionaltests/suites/harvesting/post/Harvest-wms-run2.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/harvesting/post/Harvest-zzz-post-GetRecords-filter-ows-dc.xml">functionaltests/suites/harvesting/post/Harvest-zzz-post-GetRecords-filter-ows-dc.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/harvesting/post/Transaction-000-delete-all.xml">functionaltests/suites/harvesting/post/Transaction-000-delete-all.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/harvesting/post/Harvest-sos100.xml">functionaltests/suites/harvesting/post/Harvest-sos100.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/harvesting/post/GetDomain-parameter.xml">functionaltests/suites/harvesting/post/GetDomain-parameter.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/harvesting/post/Harvest-wps.xml">functionaltests/suites/harvesting/post/Harvest-wps.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/harvesting/post/GetCapabilities.xml">functionaltests/suites/harvesting/post/GetCapabilities.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/harvesting/post/Harvest-zzz-post-GetRecords-filter-sos-iso.xml">functionaltests/suites/harvesting/post/Harvest-zzz-post-GetRecords-filter-sos-iso.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/harvesting/post/Harvest-fgdc.xml">functionaltests/suites/harvesting/post/Harvest-fgdc.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/harvesting/post/Harvest-iso.xml">functionaltests/suites/harvesting/post/Harvest-iso.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/harvesting/post/Harvest-wcs.xml">functionaltests/suites/harvesting/post/Harvest-wcs.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/harvesting/post/Harvest-wms-run1.xml">functionaltests/suites/harvesting/post/Harvest-wms-run1.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/harvesting/post/Harvest-csw-run1.xml">functionaltests/suites/harvesting/post/Harvest-csw-run1.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/harvesting/post/Harvest-zzz-post-GetRecords-filter-sos-dc.xml">functionaltests/suites/harvesting/post/Harvest-zzz-post-GetRecords-filter-sos-dc.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/harvesting/post/Harvest-zzz-post-GetRecords-filter-wms-iso.xml">functionaltests/suites/harvesting/post/Harvest-zzz-post-GetRecords-filter-wms-iso.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/harvesting/post/Harvest-csw-run2.xml">functionaltests/suites/harvesting/post/Harvest-csw-run2.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/harvesting/post/Harvest-waf.xml">functionaltests/suites/harvesting/post/Harvest-waf.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/harvesting/post/Harvest-csw-iso.xml">functionaltests/suites/harvesting/post/Harvest-csw-iso.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/harvesting/post/Harvest-wfs110.xml">functionaltests/suites/harvesting/post/Harvest-wfs110.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/harvesting/post/Clear-000-delete-all.xml">functionaltests/suites/harvesting/post/Clear-000-delete-all.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/oaipmh/expected/get_GetRecord_iso.xml">functionaltests/suites/oaipmh/expected/get_GetRecord_iso.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/oaipmh/expected/get_ListRecords_dc_bad_metadata_prefix.xml">functionaltests/suites/oaipmh/expected/get_ListRecords_dc_bad_metadata_prefix.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/oaipmh/expected/get_ListMetadataFormats.xml">functionaltests/suites/oaipmh/expected/get_ListMetadataFormats.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/oaipmh/expected/get_bad_verb.xml">functionaltests/suites/oaipmh/expected/get_bad_verb.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/oaipmh/expected/get_Identify.xml">functionaltests/suites/oaipmh/expected/get_Identify.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/oaipmh/expected/get_ListIdentifiers_bad_metadata_prefix.xml">functionaltests/suites/oaipmh/expected/get_ListIdentifiers_bad_metadata_prefix.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/oaipmh/expected/get_ListIdentifiers_missing_metadata_prefix.xml">functionaltests/suites/oaipmh/expected/get_ListIdentifiers_missing_metadata_prefix.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/oaipmh/expected/get_GetRecord_oai_dc.xml">functionaltests/suites/oaipmh/expected/get_GetRecord_oai_dc.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/oaipmh/expected/get_empty_with_amp.xml">functionaltests/suites/oaipmh/expected/get_empty_with_amp.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/oaipmh/expected/get_ListRecords_dc.xml">functionaltests/suites/oaipmh/expected/get_ListRecords_dc.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/oaipmh/expected/get_ListIdentifiers_iso.xml">functionaltests/suites/oaipmh/expected/get_ListIdentifiers_iso.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/oaipmh/expected/get_GetRecord_bad_metadata_prefix.xml">functionaltests/suites/oaipmh/expected/get_GetRecord_bad_metadata_prefix.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/oaipmh/expected/get_ListIdentifiers_dc.xml">functionaltests/suites/oaipmh/expected/get_ListIdentifiers_dc.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/oaipmh/expected/get_empty.xml">functionaltests/suites/oaipmh/expected/get_empty.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/oaipmh/expected/get_GetRecord_dc.xml">functionaltests/suites/oaipmh/expected/get_GetRecord_dc.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/oaipmh/expected/get_ListRecords_iso19139.xml">functionaltests/suites/oaipmh/expected/get_ListRecords_iso19139.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/oaipmh/expected/get_illegal_verb.xml">functionaltests/suites/oaipmh/expected/get_illegal_verb.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/oaipmh/expected/get_ListIdentifiers_oai_dc.xml">functionaltests/suites/oaipmh/expected/get_ListIdentifiers_oai_dc.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/oaipmh/expected/get_ListSets.xml">functionaltests/suites/oaipmh/expected/get_ListSets.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/oaipmh/expected/get_ListRecords_oai_dc.xml">functionaltests/suites/oaipmh/expected/get_ListRecords_oai_dc.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/get_ad0c0571-09ed-436a-9a4f-a5de744c88fe.xml">functionaltests/suites/csw30/expected/get_ad0c0571-09ed-436a-9a4f-a5de744c88fe.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/get_0e1dca37-477a-4060-99fe-7799b52d656c.xml">functionaltests/suites/csw30/expected/get_0e1dca37-477a-4060-99fe-7799b52d656c.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/get_dff3ec6b-bb2d-4887-bd17-8fcf15def042.xml">functionaltests/suites/csw30/expected/get_dff3ec6b-bb2d-4887-bd17-8fcf15def042.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/get_1bcb42a9-538c-4f0a-9d4c-d6f10b720aa6.xml">functionaltests/suites/csw30/expected/get_1bcb42a9-538c-4f0a-9d4c-d6f10b720aa6.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/get_5a015f6a-bf14-4977-b1e3-6577eb0223c8.xml">functionaltests/suites/csw30/expected/get_5a015f6a-bf14-4977-b1e3-6577eb0223c8.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/get_002258f0-627f-457f-b2ad-025777c77ac8.xml">functionaltests/suites/csw30/expected/get_002258f0-627f-457f-b2ad-025777c77ac8.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/get_e7704509-3441-458f-8ef0-e333c6b6043f.xml">functionaltests/suites/csw30/expected/get_e7704509-3441-458f-8ef0-e333c6b6043f.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/get_GetRepositoryItem.xml">functionaltests/suites/csw30/expected/get_GetRepositoryItem.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/get_5c3a2390-1fb9-43f0-b96c-f48c7a69c990.xml">functionaltests/suites/csw30/expected/get_5c3a2390-1fb9-43f0-b96c-f48c7a69c990.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/post_Exception-GetRecordById-404.xml">functionaltests/suites/csw30/expected/post_Exception-GetRecordById-404.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/get_6a5e247b-0961-4b8a-a0d6-35a491d9cfe7.xml">functionaltests/suites/csw30/expected/get_6a5e247b-0961-4b8a-a0d6-35a491d9cfe7.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/get_7630d230-e142-4a09-accf-f091000b90cd.xml">functionaltests/suites/csw30/expected/get_7630d230-e142-4a09-accf-f091000b90cd.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/get_da859e34-91fc-495a-8c09-285a40c0900b.xml">functionaltests/suites/csw30/expected/get_da859e34-91fc-495a-8c09-285a40c0900b.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/get_461bd4c5-6623-490d-9036-d91a2201e87b.xml">functionaltests/suites/csw30/expected/get_461bd4c5-6623-490d-9036-d91a2201e87b.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/get_92d4844d-57d5-4cf3-8f47-ba50e369dc04.xml">functionaltests/suites/csw30/expected/get_92d4844d-57d5-4cf3-8f47-ba50e369dc04.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/get_f89dd4e1-3a81-4433-afd2-a3fa1bdb1e18.xml">functionaltests/suites/csw30/expected/get_f89dd4e1-3a81-4433-afd2-a3fa1bdb1e18.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/get_GetCapabilities-base-url.xml">functionaltests/suites/csw30/expected/get_GetCapabilities-base-url.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/get_de016645-6d5c-4855-943c-2db07ae9f49a.xml">functionaltests/suites/csw30/expected/get_de016645-6d5c-4855-943c-2db07ae9f49a.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/get_cb43d8c3-e14c-4a9f-9231-4384b7dd21f3.xml">functionaltests/suites/csw30/expected/get_cb43d8c3-e14c-4a9f-9231-4384b7dd21f3.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/get_9c0e2a4b-b4e6-41c0-b630-c8c99fc89ff3.xml">functionaltests/suites/csw30/expected/get_9c0e2a4b-b4e6-41c0-b630-c8c99fc89ff3.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/get_d03c6fd3-e821-4a26-b62f-d20a474e25af.xml">functionaltests/suites/csw30/expected/get_d03c6fd3-e821-4a26-b62f-d20a474e25af.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/post_Exception-bad-xml.xml">functionaltests/suites/csw30/expected/post_Exception-bad-xml.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/get_c03d173a-3f42-4956-89c8-1fe02c3a0873.xml">functionaltests/suites/csw30/expected/get_c03d173a-3f42-4956-89c8-1fe02c3a0873.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/get_604d9379-741c-42e5-b4cf-92e56c87fa64.xml">functionaltests/suites/csw30/expected/get_604d9379-741c-42e5-b4cf-92e56c87fa64.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/post_GetDomain-parametername.xml">functionaltests/suites/csw30/expected/post_GetDomain-parametername.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/post_GetRecordById-dc.xml">functionaltests/suites/csw30/expected/post_GetRecordById-dc.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/get_3dcd1b15-73d2-4b7d-a3e3-ff15bf14aae4.xml">functionaltests/suites/csw30/expected/get_3dcd1b15-73d2-4b7d-a3e3-ff15bf14aae4.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/get_1869e495-1a61-4713-8285-76d1336ee1a6.xml">functionaltests/suites/csw30/expected/get_1869e495-1a61-4713-8285-76d1336ee1a6.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/post_Exception-GetRecordById-bad-esn.xml">functionaltests/suites/csw30/expected/post_Exception-GetRecordById-bad-esn.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/get_GetCapabilities-no-version.xml">functionaltests/suites/csw30/expected/get_GetCapabilities-no-version.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/get_Exception-GetRecordById-404.xml">functionaltests/suites/csw30/expected/get_Exception-GetRecordById-404.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/get_GetDomain-parameter.xml">functionaltests/suites/csw30/expected/get_GetDomain-parameter.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/get_5e9e67dc-18d6-4645-8111-c6263c88a61f.xml">functionaltests/suites/csw30/expected/get_5e9e67dc-18d6-4645-8111-c6263c88a61f.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/get_62ad94c2-b558-4265-a427-23d6677975d6.xml">functionaltests/suites/csw30/expected/get_62ad94c2-b558-4265-a427-23d6677975d6.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/get_8184ae4f-536d-4978-8b28-ad703be96967.xml">functionaltests/suites/csw30/expected/get_8184ae4f-536d-4978-8b28-ad703be96967.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/post_GetDomain-valuereference.xml">functionaltests/suites/csw30/expected/post_GetDomain-valuereference.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/get_5496894a-3877-4f62-a20b-5d7126f94925.xml">functionaltests/suites/csw30/expected/get_5496894a-3877-4f62-a20b-5d7126f94925.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/post_GetCapabilities.xml">functionaltests/suites/csw30/expected/post_GetCapabilities.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/get_GetDomain-value-reference.xml">functionaltests/suites/csw30/expected/get_GetDomain-value-reference.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/get_0bdf8457-971e-4ed1-be4a-5feca4dcd8fa.xml">functionaltests/suites/csw30/expected/get_0bdf8457-971e-4ed1-be4a-5feca4dcd8fa.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/get_9000ec29-5649-474e-b2d6-55c00f8a52c0.xml">functionaltests/suites/csw30/expected/get_9000ec29-5649-474e-b2d6-55c00f8a52c0.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/get_91914d35-7bbf-45e6-9b37-5ef484869a4e.xml">functionaltests/suites/csw30/expected/get_91914d35-7bbf-45e6-9b37-5ef484869a4e.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/get_2499a9c9-8d33-449c-bc92-d494adfcc84d.xml">functionaltests/suites/csw30/expected/get_2499a9c9-8d33-449c-bc92-d494adfcc84d.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/get_baa4a7d0-0c01-42b6-adc3-0d03e9949fa3.xml">functionaltests/suites/csw30/expected/get_baa4a7d0-0c01-42b6-adc3-0d03e9949fa3.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/get_Exception-GetDomain-value-reference.xml">functionaltests/suites/csw30/expected/get_Exception-GetDomain-value-reference.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/get_43cd6471-6ac7-45bd-8ff9-148cb2de9a52.xml">functionaltests/suites/csw30/expected/get_43cd6471-6ac7-45bd-8ff9-148cb2de9a52.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/get_f1223a49-6d08-44ff-97fe-4c32cbbfad82.xml">functionaltests/suites/csw30/expected/get_f1223a49-6d08-44ff-97fe-4c32cbbfad82.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/post_GetRecordById-dc-full.xml">functionaltests/suites/csw30/expected/post_GetRecordById-dc-full.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/get_6a9d0558-9d87-495b-b999-b49a3ef1cf99.xml">functionaltests/suites/csw30/expected/get_6a9d0558-9d87-495b-b999-b49a3ef1cf99.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/get_dc246fb8-5af5-4fda-82bb-c18b3ecd439c.xml">functionaltests/suites/csw30/expected/get_dc246fb8-5af5-4fda-82bb-c18b3ecd439c.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/get_60e6af95-d5fc-465a-82e2-fd2e6d85e4af.xml">functionaltests/suites/csw30/expected/get_60e6af95-d5fc-465a-82e2-fd2e6d85e4af.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/get_13c87956-51a4-4780-a8e9-6e0b5c0bb473.xml">functionaltests/suites/csw30/expected/get_13c87956-51a4-4780-a8e9-6e0b5c0bb473.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/get_0bbcf862-5211-4351-9988-63f8bec49c98.xml">functionaltests/suites/csw30/expected/get_0bbcf862-5211-4351-9988-63f8bec49c98.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/post_Exception-not-xml.xml">functionaltests/suites/csw30/expected/post_Exception-not-xml.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/get_88f63a89-664f-4315-b4f8-04a0b33803a7.xml">functionaltests/suites/csw30/expected/get_88f63a89-664f-4315-b4f8-04a0b33803a7.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/get_8987f8f0-4d93-4481-968c-a2ccbd6b8be2.xml">functionaltests/suites/csw30/expected/get_8987f8f0-4d93-4481-968c-a2ccbd6b8be2.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/get_Exception-GetDomain.xml">functionaltests/suites/csw30/expected/get_Exception-GetDomain.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/get_22f44168-2ccf-4801-ad96-204212566d56.xml">functionaltests/suites/csw30/expected/get_22f44168-2ccf-4801-ad96-204212566d56.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/get_e38e6bfb-8ac4-4ae4-8b87-0aafbc8d3c6b.xml">functionaltests/suites/csw30/expected/get_e38e6bfb-8ac4-4ae4-8b87-0aafbc8d3c6b.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/get_9d7ffac8-9798-428d-8e27-3cd12497ee6b.xml">functionaltests/suites/csw30/expected/get_9d7ffac8-9798-428d-8e27-3cd12497ee6b.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/get_8e5fa0f6-3f29-4d1f-abe2-d9866f3def98.xml">functionaltests/suites/csw30/expected/get_8e5fa0f6-3f29-4d1f-abe2-d9866f3def98.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/get_397fe17a-d5b4-4f96-8cc4-4ce467ed4d0a.xml">functionaltests/suites/csw30/expected/get_397fe17a-d5b4-4f96-8cc4-4ce467ed4d0a.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/get_b9a07a54-75a8-45bd-b341-2823600211e3.xml">functionaltests/suites/csw30/expected/get_b9a07a54-75a8-45bd-b341-2823600211e3.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/get_Exception-GetRecordById-dc.xml.xml">functionaltests/suites/csw30/expected/get_Exception-GetRecordById-dc.xml.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/post_Exception-GetDomain-valuereference-bad.xml">functionaltests/suites/csw30/expected/post_Exception-GetDomain-valuereference-bad.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/get_GetCapabilities.xml">functionaltests/suites/csw30/expected/get_GetCapabilities.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/get_d4ccbf96-a529-480e-a53d-5b88dc1dea7f.xml">functionaltests/suites/csw30/expected/get_d4ccbf96-a529-480e-a53d-5b88dc1dea7f.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/get_6e9cba43-5e27-415d-adbd-a92851c2c173.xml">functionaltests/suites/csw30/expected/get_6e9cba43-5e27-415d-adbd-a92851c2c173.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/get_b2aafc3f-4f35-47bc-affd-08590972deae.xml">functionaltests/suites/csw30/expected/get_b2aafc3f-4f35-47bc-affd-08590972deae.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/get_7e82446a-b5dc-43fe-9a73-4cc1f2f2f0bf.xml">functionaltests/suites/csw30/expected/get_7e82446a-b5dc-43fe-9a73-4cc1f2f2f0bf.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/get_2b06a5c8-0df2-4af1-8d2e-a425de11c845.xml">functionaltests/suites/csw30/expected/get_2b06a5c8-0df2-4af1-8d2e-a425de11c845.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/get_d94c801a-1207-4897-b84a-53f3a192515b.xml">functionaltests/suites/csw30/expected/get_d94c801a-1207-4897-b84a-53f3a192515b.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/post_Exception-GetDomain-parametername-bad.xml">functionaltests/suites/csw30/expected/post_Exception-GetDomain-parametername-bad.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/get_OpenSearch-description.xml">functionaltests/suites/csw30/expected/get_OpenSearch-description.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/get_0d8bbdec-0846-42ca-8dc8-b7f4cba41d67.xml">functionaltests/suites/csw30/expected/get_0d8bbdec-0846-42ca-8dc8-b7f4cba41d67.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/get_af502903-f4ee-47ee-b76e-af878d238bcc.xml">functionaltests/suites/csw30/expected/get_af502903-f4ee-47ee-b76e-af878d238bcc.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/get_Exception-GetRepositoryItem-notfound.xml">functionaltests/suites/csw30/expected/get_Exception-GetRepositoryItem-notfound.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/get_e67ca935-d65d-4d8c-8302-1405333dded0.xml">functionaltests/suites/csw30/expected/get_e67ca935-d65d-4d8c-8302-1405333dded0.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/get_045c600d-973d-41eb-9f60-eba1b717b720.xml">functionaltests/suites/csw30/expected/get_045c600d-973d-41eb-9f60-eba1b717b720.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/get_b6069623-f7d8-4021-8582-98f0aea0f763.xml">functionaltests/suites/csw30/expected/get_b6069623-f7d8-4021-8582-98f0aea0f763.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/get_abc90c8c-5868-4405-a73e-64c849be3b2a.xml">functionaltests/suites/csw30/expected/get_abc90c8c-5868-4405-a73e-64c849be3b2a.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/get_Exception-invalid-request.xml">functionaltests/suites/csw30/expected/get_Exception-invalid-request.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/get_bfe20134-d1da-42ef-9c0f-8e1307bbf92b.xml">functionaltests/suites/csw30/expected/get_bfe20134-d1da-42ef-9c0f-8e1307bbf92b.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/get_2ba1418a-444d-4cce-9cfe-4c94efcf8b55.xml">functionaltests/suites/csw30/expected/get_2ba1418a-444d-4cce-9cfe-4c94efcf8b55.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/get_4566d2ec-1283-4a02-baed-a74fc5b47e37.xml">functionaltests/suites/csw30/expected/get_4566d2ec-1283-4a02-baed-a74fc5b47e37.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/get_151d982f-ebd3-4cb2-b507-a667713a1e92.xml">functionaltests/suites/csw30/expected/get_151d982f-ebd3-4cb2-b507-a667713a1e92.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/get_bfbe6409-f64a-4c89-acb3-50f260a5c743.xml">functionaltests/suites/csw30/expected/get_bfbe6409-f64a-4c89-acb3-50f260a5c743.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/get_8025978e-1a35-4d70-80c2-e8329e0c7864.xml">functionaltests/suites/csw30/expected/get_8025978e-1a35-4d70-80c2-e8329e0c7864.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/get_6bd790c9-6019-4652-9c91-330a894d6700.xml">functionaltests/suites/csw30/expected/get_6bd790c9-6019-4652-9c91-330a894d6700.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/get_28e569df-8596-4128-8d9a-29ad03138915.xml">functionaltests/suites/csw30/expected/get_28e569df-8596-4128-8d9a-29ad03138915.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/get_27f4f39c-d92a-4e3c-b961-c6aa8c24e513.xml">functionaltests/suites/csw30/expected/get_27f4f39c-d92a-4e3c-b961-c6aa8c24e513.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/get_405e1ff1-5c75-4846-a28b-cfaff2a6921a.xml">functionaltests/suites/csw30/expected/get_405e1ff1-5c75-4846-a28b-cfaff2a6921a.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/expected/get_a2f18643-e24e-4fa5-b780-6de4a2dbc814.xml">functionaltests/suites/csw30/expected/get_a2f18643-e24e-4fa5-b780-6de4a2dbc814.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/post/GetDomain-valuereference.xml">functionaltests/suites/csw30/post/GetDomain-valuereference.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/post/GetDomain-parametername.xml">functionaltests/suites/csw30/post/GetDomain-parametername.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/post/GetRecordById-dc.xml">functionaltests/suites/csw30/post/GetRecordById-dc.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/post/Exception-GetDomain-valuereference-bad.xml">functionaltests/suites/csw30/post/Exception-GetDomain-valuereference-bad.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/post/GetCapabilities.xml">functionaltests/suites/csw30/post/GetCapabilities.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/post/Exception-not-xml.xml">functionaltests/suites/csw30/post/Exception-not-xml.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/post/Exception-GetRecordById-404.xml">functionaltests/suites/csw30/post/Exception-GetRecordById-404.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/post/Exception-GetDomain-parametername-bad.xml">functionaltests/suites/csw30/post/Exception-GetDomain-parametername-bad.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/post/Exception-bad-xml.xml">functionaltests/suites/csw30/post/Exception-bad-xml.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/post/GetRecordById-dc-full.xml">functionaltests/suites/csw30/post/GetRecordById-dc-full.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/csw30/post/Exception-GetRecordById-bad-esn.xml">functionaltests/suites/csw30/post/Exception-GetRecordById-bad-esn.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/repofilter/expected/post_GetRecordById-masked.xml">functionaltests/suites/repofilter/expected/post_GetRecordById-masked.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/repofilter/expected/post_GetRecords-all.xml">functionaltests/suites/repofilter/expected/post_GetRecords-all.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/repofilter/post/GetRecordById-masked.xml">functionaltests/suites/repofilter/post/GetRecordById-masked.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/repofilter/post/GetRecords-all.xml">functionaltests/suites/repofilter/post/GetRecords-all.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/dif/expected/post_GetRecords-filter-bbox.xml">functionaltests/suites/dif/expected/post_GetRecords-filter-bbox.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/dif/expected/post_DescribeRecord.xml">functionaltests/suites/dif/expected/post_DescribeRecord.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/dif/expected/post_GetCapabilities.xml">functionaltests/suites/dif/expected/post_GetCapabilities.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/dif/post/DescribeRecord.xml">functionaltests/suites/dif/post/DescribeRecord.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/dif/post/GetCapabilities.xml">functionaltests/suites/dif/post/GetCapabilities.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/dif/post/GetRecords-filter-bbox.xml">functionaltests/suites/dif/post/GetRecords-filter-bbox.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/apiso-inspire/expected/get_GetCapabilities-lang.xml">functionaltests/suites/apiso-inspire/expected/get_GetCapabilities-lang.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/apiso-inspire/expected/get_GetCapabilities.xml">functionaltests/suites/apiso-inspire/expected/get_GetCapabilities.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/atom/expected/get_opensearch-ogc-time.xml">functionaltests/suites/atom/expected/get_opensearch-ogc-time.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/atom/expected/post_GetRecords-filter-bbox.xml">functionaltests/suites/atom/expected/post_GetRecords-filter-bbox.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/atom/expected/post_DescribeRecord.xml">functionaltests/suites/atom/expected/post_DescribeRecord.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/atom/expected/get_opensearch-ogc-count-and-page1.xml">functionaltests/suites/atom/expected/get_opensearch-ogc-count-and-page1.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/atom/expected/get_opensearch-ogc-timeend.xml">functionaltests/suites/atom/expected/get_opensearch-ogc-timeend.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/atom/expected/get_opensearch-ogc-bbox.xml">functionaltests/suites/atom/expected/get_opensearch-ogc-bbox.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/atom/expected/get_opensearch-ogc-q-and-bbox.xml">functionaltests/suites/atom/expected/get_opensearch-ogc-q-and-bbox.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/atom/expected/get_opensearch.xml">functionaltests/suites/atom/expected/get_opensearch.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/atom/expected/get_opensearch-ogc-q.xml">functionaltests/suites/atom/expected/get_opensearch-ogc-q.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/atom/expected/post_GetCapabilities.xml">functionaltests/suites/atom/expected/post_GetCapabilities.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/atom/expected/get_opensearch-ogc-count-and-page2.xml">functionaltests/suites/atom/expected/get_opensearch-ogc-count-and-page2.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/atom/expected/get_opensearch-ogc-bbox-and-time.xml">functionaltests/suites/atom/expected/get_opensearch-ogc-bbox-and-time.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/atom/expected/get_opensearch-ogc-q-and-time.xml">functionaltests/suites/atom/expected/get_opensearch-ogc-q-and-time.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/atom/expected/get_opensearch-ogc-timestart.xml">functionaltests/suites/atom/expected/get_opensearch-ogc-timestart.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/atom/expected/get_opensearch-description.xml">functionaltests/suites/atom/expected/get_opensearch-description.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/atom/post/DescribeRecord.xml">functionaltests/suites/atom/post/DescribeRecord.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/atom/post/GetCapabilities.xml">functionaltests/suites/atom/post/GetCapabilities.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/atom/post/GetRecords-filter-bbox.xml">functionaltests/suites/atom/post/GetRecords-filter-bbox.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/expected/post_6e736fd0-c266-4852-9eb3-0656f5d0f5c4.xml">functionaltests/suites/cite/expected/post_6e736fd0-c266-4852-9eb3-0656f5d0f5c4.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/expected/post_4735d649-a2b1-42fd-a101-14e1d7e4607f.xml">functionaltests/suites/cite/expected/post_4735d649-a2b1-42fd-a101-14e1d7e4607f.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/expected/post_fe20960f-a26c-4f13-852d-470a0d3233f9.xml">functionaltests/suites/cite/expected/post_fe20960f-a26c-4f13-852d-470a0d3233f9.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/expected/post_898cd63b-2585-4ec0-8720-d554bd324174.xml">functionaltests/suites/cite/expected/post_898cd63b-2585-4ec0-8720-d554bd324174.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/expected/post_19d2a6ed-be28-4866-ae15-e3bb634486cb.xml">functionaltests/suites/cite/expected/post_19d2a6ed-be28-4866-ae15-e3bb634486cb.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/expected/post_2d53ffea-60e4-4652-abf5-36eb23042fd5.xml">functionaltests/suites/cite/expected/post_2d53ffea-60e4-4652-abf5-36eb23042fd5.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/expected/post_34a019a9-1581-42cb-9827-fbfdda2773b7.xml">functionaltests/suites/cite/expected/post_34a019a9-1581-42cb-9827-fbfdda2773b7.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/expected/get_3a8a3c47-455f-4f49-9078-03119f3e70b3.xml">functionaltests/suites/cite/expected/get_3a8a3c47-455f-4f49-9078-03119f3e70b3.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/expected/post_0c976d98-c896-4b10-b1fe-a22ef50434e7.xml">functionaltests/suites/cite/expected/post_0c976d98-c896-4b10-b1fe-a22ef50434e7.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/expected/post_2102a460-5d62-465f-9668-d70b3faafbfa.xml">functionaltests/suites/cite/expected/post_2102a460-5d62-465f-9668-d70b3faafbfa.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/expected/get_2ab7d1fa-885b-459f-80e4-b6282eab4f8c.xml">functionaltests/suites/cite/expected/get_2ab7d1fa-885b-459f-80e4-b6282eab4f8c.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/expected/post_c38916c2-4bc6-446d-b7aa-ab006d6ba31c.xml">functionaltests/suites/cite/expected/post_c38916c2-4bc6-446d-b7aa-ab006d6ba31c.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/expected/post_78297c88-4850-4927-adc6-511cd9a3d539.xml">functionaltests/suites/cite/expected/post_78297c88-4850-4927-adc6-511cd9a3d539.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/expected/post_8fb13dc3-5818-45e2-9e29-46abc16e7d38.xml">functionaltests/suites/cite/expected/post_8fb13dc3-5818-45e2-9e29-46abc16e7d38.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/expected/post_bb66ebc5-7121-48b5-9f53-b56537d9561b.xml">functionaltests/suites/cite/expected/post_bb66ebc5-7121-48b5-9f53-b56537d9561b.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/expected/post_ba9b0107-dcee-46ef-823a-a2e25a911a96.xml">functionaltests/suites/cite/expected/post_ba9b0107-dcee-46ef-823a-a2e25a911a96.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/expected/get_4e38092f-1586-44b8-988e-0acfa5855916.xml">functionaltests/suites/cite/expected/get_4e38092f-1586-44b8-988e-0acfa5855916.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/expected/post_928c1896-52d4-4ac7-9832-f98e3eb65f02.xml">functionaltests/suites/cite/expected/post_928c1896-52d4-4ac7-9832-f98e3eb65f02.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/expected/post_1c958b7a-ca09-4c38-98bd-ef1d1d28cc14.xml">functionaltests/suites/cite/expected/post_1c958b7a-ca09-4c38-98bd-ef1d1d28cc14.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/expected/post_dcb13791-379e-4739-bcd4-dbaa69f0efdb.xml">functionaltests/suites/cite/expected/post_dcb13791-379e-4739-bcd4-dbaa69f0efdb.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/expected/post_e308f030-c097-4036-a838-44bad74c9ef7.xml">functionaltests/suites/cite/expected/post_e308f030-c097-4036-a838-44bad74c9ef7.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/expected/get_4515831f-834a-4699-95f6-ab0c2cbfcfd0.xml">functionaltests/suites/cite/expected/get_4515831f-834a-4699-95f6-ab0c2cbfcfd0.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/expected/get_8e2232ed-05d9-44ae-8b04-0911cbe6a507.xml">functionaltests/suites/cite/expected/get_8e2232ed-05d9-44ae-8b04-0911cbe6a507.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/expected/post_948b39d5-bb4f-45b8-a8f2-4ff9501aaedd.xml">functionaltests/suites/cite/expected/post_948b39d5-bb4f-45b8-a8f2-4ff9501aaedd.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/expected/get_48f26761-3a9d-48db-bee1-da089f5fb857.xml">functionaltests/suites/cite/expected/get_48f26761-3a9d-48db-bee1-da089f5fb857.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/expected/post_e6e9efb2-e2b7-4b0a-a3a2-7deea3f9b8e2.xml">functionaltests/suites/cite/expected/post_e6e9efb2-e2b7-4b0a-a3a2-7deea3f9b8e2.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/expected/get_b81c3595-06d6-4693-82ea-1ff8650755ac.xml">functionaltests/suites/cite/expected/get_b81c3595-06d6-4693-82ea-1ff8650755ac.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/expected/post_c02d1c85-df9f-45ee-bea7-345c35e02a98.xml">functionaltests/suites/cite/expected/post_c02d1c85-df9f-45ee-bea7-345c35e02a98.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/expected/post_93bdbb9d-2734-4f01-92fb-48634cca41de.xml">functionaltests/suites/cite/expected/post_93bdbb9d-2734-4f01-92fb-48634cca41de.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/expected/post_1c97fc1a-61cd-4c1d-8054-933e17a6c5ee.xml">functionaltests/suites/cite/expected/post_1c97fc1a-61cd-4c1d-8054-933e17a6c5ee.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/expected/post_f7976c55-a156-4421-8199-bc0487da4b0f.xml">functionaltests/suites/cite/expected/post_f7976c55-a156-4421-8199-bc0487da4b0f.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/expected/post_da228d4c-e1be-43d7-9ccb-c3f27ee32541.xml">functionaltests/suites/cite/expected/post_da228d4c-e1be-43d7-9ccb-c3f27ee32541.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/expected/get_c4ea754f-c158-4d8d-8253-dc8f86021b52.xml">functionaltests/suites/cite/expected/get_c4ea754f-c158-4d8d-8253-dc8f86021b52.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/expected/post_c311a342-72e3-4983-be39-868e6ed9740f.xml">functionaltests/suites/cite/expected/post_c311a342-72e3-4983-be39-868e6ed9740f.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/expected/post_ad61686c-d304-42d1-b845-8c1f3070c83e.xml">functionaltests/suites/cite/expected/post_ad61686c-d304-42d1-b845-8c1f3070c83e.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/expected/get_6a4f57ca-a1bd-4802-89c2-44860dbdb0f0.xml">functionaltests/suites/cite/expected/get_6a4f57ca-a1bd-4802-89c2-44860dbdb0f0.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/expected/post_c8588f47-8e65-45f5-ad34-ff4524cad84d.xml">functionaltests/suites/cite/expected/post_c8588f47-8e65-45f5-ad34-ff4524cad84d.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/expected/post_af39c020-7b1d-429c-b474-f45c3164cb79.xml">functionaltests/suites/cite/expected/post_af39c020-7b1d-429c-b474-f45c3164cb79.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/expected/post_73f1551c-e269-4ef9-9dae-e535b5eebfc7.xml">functionaltests/suites/cite/expected/post_73f1551c-e269-4ef9-9dae-e535b5eebfc7.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/expected/get_9bfd17fa-15dc-4a10-8fa7-b3cff7013dd7.xml">functionaltests/suites/cite/expected/get_9bfd17fa-15dc-4a10-8fa7-b3cff7013dd7.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/expected/post_3e76fd38-e035-41c9-83dc-61356f680c97.xml">functionaltests/suites/cite/expected/post_3e76fd38-e035-41c9-83dc-61356f680c97.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/expected/get_f997f25e-c865-4d53-a362-0ed1846337f2.xml">functionaltests/suites/cite/expected/get_f997f25e-c865-4d53-a362-0ed1846337f2.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/expected/post_225f455a-0035-486b-a94e-fee7ae881b2b.xml">functionaltests/suites/cite/expected/post_225f455a-0035-486b-a94e-fee7ae881b2b.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/expected/get_80f31def-4185-48b9-983a-960566918eae.xml">functionaltests/suites/cite/expected/get_80f31def-4185-48b9-983a-960566918eae.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/expected/post_420b745e-0c4b-404e-9f2d-61fa580ff05a.xml">functionaltests/suites/cite/expected/post_420b745e-0c4b-404e-9f2d-61fa580ff05a.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/expected/get_27e17158-c57a-4493-92ac-dba8934cf462.xml">functionaltests/suites/cite/expected/get_27e17158-c57a-4493-92ac-dba8934cf462.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/expected/get_37aa90e2-6ff0-420c-af15-8b9463099a73.xml">functionaltests/suites/cite/expected/get_37aa90e2-6ff0-420c-af15-8b9463099a73.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/expected/post_b90e2de6-3d25-4298-a13e-dc9492a8fc73.xml">functionaltests/suites/cite/expected/post_b90e2de6-3d25-4298-a13e-dc9492a8fc73.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/expected/get_5ab5db18-c87a-4fbf-a8d8-b7289b09ac81.xml">functionaltests/suites/cite/expected/get_5ab5db18-c87a-4fbf-a8d8-b7289b09ac81.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/expected/post_7e2cd105-daec-4d25-bc8e-d49d21364912.xml">functionaltests/suites/cite/expected/post_7e2cd105-daec-4d25-bc8e-d49d21364912.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/expected/post_87f2f670-9cd6-4907-b82c-1b46a7dd2a78.xml">functionaltests/suites/cite/expected/post_87f2f670-9cd6-4907-b82c-1b46a7dd2a78.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/expected/get_27f69b66-5f05-4311-a89c-73ca55c2686b.xml">functionaltests/suites/cite/expected/get_27f69b66-5f05-4311-a89c-73ca55c2686b.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/expected/post_88b4e1ba-3bd4-4cbe-81e5-e004056d6ca3.xml">functionaltests/suites/cite/expected/post_88b4e1ba-3bd4-4cbe-81e5-e004056d6ca3.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/expected/post_9fd64fcc-f69c-4626-b72e-5c7776a29aa9.xml">functionaltests/suites/cite/expected/post_9fd64fcc-f69c-4626-b72e-5c7776a29aa9.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/expected/get_6c375703-9c00-4aef-bec7-d2e964f849eb.xml">functionaltests/suites/cite/expected/get_6c375703-9c00-4aef-bec7-d2e964f849eb.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/expected/post_5c5861bc-f742-40a5-9998-5342615d674b.xml">functionaltests/suites/cite/expected/post_5c5861bc-f742-40a5-9998-5342615d674b.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/expected/post_a06d04ab-e0d0-4a86-bfe8-71460f41fe37.xml">functionaltests/suites/cite/expected/post_a06d04ab-e0d0-4a86-bfe8-71460f41fe37.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/expected/post_1ab55aa3-6685-4595-8ecd-45987a7b8b59.xml">functionaltests/suites/cite/expected/post_1ab55aa3-6685-4595-8ecd-45987a7b8b59.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/expected/get_f4692ec5-9547-4a05-88ab-e6154af2640a.xml">functionaltests/suites/cite/expected/get_f4692ec5-9547-4a05-88ab-e6154af2640a.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/expected/post_7c89cdf5-0def-4cfb-8c55-2b8ffea5d92f.xml">functionaltests/suites/cite/expected/post_7c89cdf5-0def-4cfb-8c55-2b8ffea5d92f.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/expected/get_ba5fc729-3b71-47a0-b7d0-42ec565cd185.xml">functionaltests/suites/cite/expected/get_ba5fc729-3b71-47a0-b7d0-42ec565cd185.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/expected/post_fc1bc094-88f1-4851-bc2b-dfc56be9f3c7.xml">functionaltests/suites/cite/expected/post_fc1bc094-88f1-4851-bc2b-dfc56be9f3c7.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/expected/post_dc92c2c4-87d8-4a13-964e-ff9b0e0c27b3.xml">functionaltests/suites/cite/expected/post_dc92c2c4-87d8-4a13-964e-ff9b0e0c27b3.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/expected/get_477b23a3-baa9-47c8-9541-5fe27735ed49.xml">functionaltests/suites/cite/expected/get_477b23a3-baa9-47c8-9541-5fe27735ed49.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/expected/post_f7d79701-f10b-4087-a33c-f62df0a04fd1.xml">functionaltests/suites/cite/expected/post_f7d79701-f10b-4087-a33c-f62df0a04fd1.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/expected/get_55c38f00-2553-42c1-99ab-33edbb561ad7.xml">functionaltests/suites/cite/expected/get_55c38f00-2553-42c1-99ab-33edbb561ad7.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/expected/post_418a6fb0-a89c-4a94-afc9-3f8168eb2980.xml">functionaltests/suites/cite/expected/post_418a6fb0-a89c-4a94-afc9-3f8168eb2980.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/expected/get_9697f0aa-3b6a-4125-83a5-61e8826127c4.xml">functionaltests/suites/cite/expected/get_9697f0aa-3b6a-4125-83a5-61e8826127c4.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/post/7e2cd105-daec-4d25-bc8e-d49d21364912.xml">functionaltests/suites/cite/post/7e2cd105-daec-4d25-bc8e-d49d21364912.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/post/0c976d98-c896-4b10-b1fe-a22ef50434e7.xml">functionaltests/suites/cite/post/0c976d98-c896-4b10-b1fe-a22ef50434e7.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/post/c02d1c85-df9f-45ee-bea7-345c35e02a98.xml">functionaltests/suites/cite/post/c02d1c85-df9f-45ee-bea7-345c35e02a98.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/post/f7976c55-a156-4421-8199-bc0487da4b0f.xml">functionaltests/suites/cite/post/f7976c55-a156-4421-8199-bc0487da4b0f.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/post/225f455a-0035-486b-a94e-fee7ae881b2b.xml">functionaltests/suites/cite/post/225f455a-0035-486b-a94e-fee7ae881b2b.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/post/898cd63b-2585-4ec0-8720-d554bd324174.xml">functionaltests/suites/cite/post/898cd63b-2585-4ec0-8720-d554bd324174.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/post/2d53ffea-60e4-4652-abf5-36eb23042fd5.xml">functionaltests/suites/cite/post/2d53ffea-60e4-4652-abf5-36eb23042fd5.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/post/3e76fd38-e035-41c9-83dc-61356f680c97.xml">functionaltests/suites/cite/post/3e76fd38-e035-41c9-83dc-61356f680c97.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/post/7c89cdf5-0def-4cfb-8c55-2b8ffea5d92f.xml">functionaltests/suites/cite/post/7c89cdf5-0def-4cfb-8c55-2b8ffea5d92f.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/post/dcb13791-379e-4739-bcd4-dbaa69f0efdb.xml">functionaltests/suites/cite/post/dcb13791-379e-4739-bcd4-dbaa69f0efdb.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/post/2102a460-5d62-465f-9668-d70b3faafbfa.xml">functionaltests/suites/cite/post/2102a460-5d62-465f-9668-d70b3faafbfa.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/post/fc1bc094-88f1-4851-bc2b-dfc56be9f3c7.xml">functionaltests/suites/cite/post/fc1bc094-88f1-4851-bc2b-dfc56be9f3c7.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/post/88b4e1ba-3bd4-4cbe-81e5-e004056d6ca3.xml">functionaltests/suites/cite/post/88b4e1ba-3bd4-4cbe-81e5-e004056d6ca3.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/post/19d2a6ed-be28-4866-ae15-e3bb634486cb.xml">functionaltests/suites/cite/post/19d2a6ed-be28-4866-ae15-e3bb634486cb.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/post/9fd64fcc-f69c-4626-b72e-5c7776a29aa9.xml">functionaltests/suites/cite/post/9fd64fcc-f69c-4626-b72e-5c7776a29aa9.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/post/73f1551c-e269-4ef9-9dae-e535b5eebfc7.xml">functionaltests/suites/cite/post/73f1551c-e269-4ef9-9dae-e535b5eebfc7.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/post/c311a342-72e3-4983-be39-868e6ed9740f.xml">functionaltests/suites/cite/post/c311a342-72e3-4983-be39-868e6ed9740f.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/post/c38916c2-4bc6-446d-b7aa-ab006d6ba31c.xml">functionaltests/suites/cite/post/c38916c2-4bc6-446d-b7aa-ab006d6ba31c.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/post/ad61686c-d304-42d1-b845-8c1f3070c83e.xml">functionaltests/suites/cite/post/ad61686c-d304-42d1-b845-8c1f3070c83e.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/post/420b745e-0c4b-404e-9f2d-61fa580ff05a.xml">functionaltests/suites/cite/post/420b745e-0c4b-404e-9f2d-61fa580ff05a.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/post/b90e2de6-3d25-4298-a13e-dc9492a8fc73.xml">functionaltests/suites/cite/post/b90e2de6-3d25-4298-a13e-dc9492a8fc73.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/post/f7d79701-f10b-4087-a33c-f62df0a04fd1.xml">functionaltests/suites/cite/post/f7d79701-f10b-4087-a33c-f62df0a04fd1.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/post/5c5861bc-f742-40a5-9998-5342615d674b.xml">functionaltests/suites/cite/post/5c5861bc-f742-40a5-9998-5342615d674b.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/post/ba9b0107-dcee-46ef-823a-a2e25a911a96.xml">functionaltests/suites/cite/post/ba9b0107-dcee-46ef-823a-a2e25a911a96.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/post/78297c88-4850-4927-adc6-511cd9a3d539.xml">functionaltests/suites/cite/post/78297c88-4850-4927-adc6-511cd9a3d539.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/post/1c958b7a-ca09-4c38-98bd-ef1d1d28cc14.xml">functionaltests/suites/cite/post/1c958b7a-ca09-4c38-98bd-ef1d1d28cc14.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/post/418a6fb0-a89c-4a94-afc9-3f8168eb2980.xml">functionaltests/suites/cite/post/418a6fb0-a89c-4a94-afc9-3f8168eb2980.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/post/6e736fd0-c266-4852-9eb3-0656f5d0f5c4.xml">functionaltests/suites/cite/post/6e736fd0-c266-4852-9eb3-0656f5d0f5c4.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/post/948b39d5-bb4f-45b8-a8f2-4ff9501aaedd.xml">functionaltests/suites/cite/post/948b39d5-bb4f-45b8-a8f2-4ff9501aaedd.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/post/fe20960f-a26c-4f13-852d-470a0d3233f9.xml">functionaltests/suites/cite/post/fe20960f-a26c-4f13-852d-470a0d3233f9.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/post/af39c020-7b1d-429c-b474-f45c3164cb79.xml">functionaltests/suites/cite/post/af39c020-7b1d-429c-b474-f45c3164cb79.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/post/e308f030-c097-4036-a838-44bad74c9ef7.xml">functionaltests/suites/cite/post/e308f030-c097-4036-a838-44bad74c9ef7.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/post/1c97fc1a-61cd-4c1d-8054-933e17a6c5ee.xml">functionaltests/suites/cite/post/1c97fc1a-61cd-4c1d-8054-933e17a6c5ee.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/post/da228d4c-e1be-43d7-9ccb-c3f27ee32541.xml">functionaltests/suites/cite/post/da228d4c-e1be-43d7-9ccb-c3f27ee32541.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/post/34a019a9-1581-42cb-9827-fbfdda2773b7.xml">functionaltests/suites/cite/post/34a019a9-1581-42cb-9827-fbfdda2773b7.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/post/87f2f670-9cd6-4907-b82c-1b46a7dd2a78.xml">functionaltests/suites/cite/post/87f2f670-9cd6-4907-b82c-1b46a7dd2a78.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/post/e6e9efb2-e2b7-4b0a-a3a2-7deea3f9b8e2.xml">functionaltests/suites/cite/post/e6e9efb2-e2b7-4b0a-a3a2-7deea3f9b8e2.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/post/bb66ebc5-7121-48b5-9f53-b56537d9561b.xml">functionaltests/suites/cite/post/bb66ebc5-7121-48b5-9f53-b56537d9561b.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/post/1ab55aa3-6685-4595-8ecd-45987a7b8b59.xml">functionaltests/suites/cite/post/1ab55aa3-6685-4595-8ecd-45987a7b8b59.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/post/4735d649-a2b1-42fd-a101-14e1d7e4607f.xml">functionaltests/suites/cite/post/4735d649-a2b1-42fd-a101-14e1d7e4607f.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/post/dc92c2c4-87d8-4a13-964e-ff9b0e0c27b3.xml">functionaltests/suites/cite/post/dc92c2c4-87d8-4a13-964e-ff9b0e0c27b3.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/post/a06d04ab-e0d0-4a86-bfe8-71460f41fe37.xml">functionaltests/suites/cite/post/a06d04ab-e0d0-4a86-bfe8-71460f41fe37.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/post/928c1896-52d4-4ac7-9832-f98e3eb65f02.xml">functionaltests/suites/cite/post/928c1896-52d4-4ac7-9832-f98e3eb65f02.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/post/c8588f47-8e65-45f5-ad34-ff4524cad84d.xml">functionaltests/suites/cite/post/c8588f47-8e65-45f5-ad34-ff4524cad84d.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/post/93bdbb9d-2734-4f01-92fb-48634cca41de.xml">functionaltests/suites/cite/post/93bdbb9d-2734-4f01-92fb-48634cca41de.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/post/8fb13dc3-5818-45e2-9e29-46abc16e7d38.xml">functionaltests/suites/cite/post/8fb13dc3-5818-45e2-9e29-46abc16e7d38.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/data/Record_1ef30a8b-876d-4828-9246-c37ab4510bbd.xml">functionaltests/suites/cite/data/Record_1ef30a8b-876d-4828-9246-c37ab4510bbd.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/data/Record_88247b56-4cbc-4df9-9860-db3f8042e357.xml">functionaltests/suites/cite/data/Record_88247b56-4cbc-4df9-9860-db3f8042e357.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/data/Record_94bc9c83-97f6-4b40-9eb8-a8e8787a5c63.xml">functionaltests/suites/cite/data/Record_94bc9c83-97f6-4b40-9eb8-a8e8787a5c63.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/data/Record_a06af396-3105-442d-8b40-22b57a90d2f2.xml">functionaltests/suites/cite/data/Record_a06af396-3105-442d-8b40-22b57a90d2f2.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/data/Record_6a3de50b-fa66-4b58-a0e6-ca146fdd18d4.xml">functionaltests/suites/cite/data/Record_6a3de50b-fa66-4b58-a0e6-ca146fdd18d4.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/data/Record_19887a8a-f6b0-4a63-ae56-7fba0e17801f.xml">functionaltests/suites/cite/data/Record_19887a8a-f6b0-4a63-ae56-7fba0e17801f.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/data/Record_9a669547-b69b-469f-a11f-2d875366bbdc.xml">functionaltests/suites/cite/data/Record_9a669547-b69b-469f-a11f-2d875366bbdc.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/data/Record_784e2afd-a9fd-44a6-9a92-a3848371c8ec.xml">functionaltests/suites/cite/data/Record_784e2afd-a9fd-44a6-9a92-a3848371c8ec.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/data/Record_66ae76b7-54ba-489b-a582-0f0633d96493.xml">functionaltests/suites/cite/data/Record_66ae76b7-54ba-489b-a582-0f0633d96493.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/data/Record_e9330592-0932-474b-be34-c3a3bb67c7db.xml">functionaltests/suites/cite/data/Record_e9330592-0932-474b-be34-c3a3bb67c7db.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/data/Record_ab42a8c4-95e8-4630-bf79-33e59241605a.xml">functionaltests/suites/cite/data/Record_ab42a8c4-95e8-4630-bf79-33e59241605a.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/cite/data/Record_829babb0-b2f1-49e1-8cd5-7b489fe71a1e.xml">functionaltests/suites/cite/data/Record_829babb0-b2f1-49e1-8cd5-7b489fe71a1e.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/apiso/expected/post_GetDomain-property.xml">functionaltests/suites/apiso/expected/post_GetDomain-property.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/apiso/expected/post_GetRecords-filter-bbox.xml">functionaltests/suites/apiso/expected/post_GetRecords-filter-bbox.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/apiso/expected/post_DescribeRecord.xml">functionaltests/suites/apiso/expected/post_DescribeRecord.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/apiso/expected/post_GetRecords-filter-bbox-csw-output.xml">functionaltests/suites/apiso/expected/post_GetRecords-filter-bbox-csw-output.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/apiso/expected/post_GetRecordById-srv-brief.xml">functionaltests/suites/apiso/expected/post_GetRecordById-srv-brief.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/apiso/expected/post_GetCapabilities.xml">functionaltests/suites/apiso/expected/post_GetCapabilities.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/apiso/expected/post_GetRecords-cql-title.xml">functionaltests/suites/apiso/expected/post_GetRecords-cql-title.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/apiso/expected/post_GetRecords-filter-and-nested-spatial-or-dateline.xml">functionaltests/suites/apiso/expected/post_GetRecords-filter-and-nested-spatial-or-dateline.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/apiso/expected/post_GetRecords-filter-servicetype.xml">functionaltests/suites/apiso/expected/post_GetRecords-filter-servicetype.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/apiso/expected/post_GetRecordById-full.xml">functionaltests/suites/apiso/expected/post_GetRecordById-full.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/apiso/expected/post_GetRecordById-brief.xml">functionaltests/suites/apiso/expected/post_GetRecordById-brief.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/apiso/expected/post_GetRecords-all.xml">functionaltests/suites/apiso/expected/post_GetRecords-all.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/apiso/expected/post_GetRecords-elementname.xml">functionaltests/suites/apiso/expected/post_GetRecords-elementname.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/apiso/expected/post_GetRecords-filter-anytext.xml">functionaltests/suites/apiso/expected/post_GetRecords-filter-anytext.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/apiso/expected/post_GetRecords-all-csw-output.xml">functionaltests/suites/apiso/expected/post_GetRecords-all-csw-output.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/apiso/expected/post_GetRecordById-full-dc.xml">functionaltests/suites/apiso/expected/post_GetRecordById-full-dc.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/apiso/post/GetRecords-filter-and-nested-spatial-or-dateline.xml">functionaltests/suites/apiso/post/GetRecords-filter-and-nested-spatial-or-dateline.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/apiso/post/GetRecordById-full-dc.xml">functionaltests/suites/apiso/post/GetRecordById-full-dc.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/apiso/post/GetDomain-property.xml">functionaltests/suites/apiso/post/GetDomain-property.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/apiso/post/GetRecordById-srv-brief.xml">functionaltests/suites/apiso/post/GetRecordById-srv-brief.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/apiso/post/GetRecordById-full.xml">functionaltests/suites/apiso/post/GetRecordById-full.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/apiso/post/GetRecords-cql-title.xml">functionaltests/suites/apiso/post/GetRecords-cql-title.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/apiso/post/GetRecords-all-csw-output.xml">functionaltests/suites/apiso/post/GetRecords-all-csw-output.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/apiso/post/GetRecordById-brief.xml">functionaltests/suites/apiso/post/GetRecordById-brief.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/apiso/post/DescribeRecord.xml">functionaltests/suites/apiso/post/DescribeRecord.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/apiso/post/GetCapabilities.xml">functionaltests/suites/apiso/post/GetCapabilities.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/apiso/post/GetRecords-elementname.xml">functionaltests/suites/apiso/post/GetRecords-elementname.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/apiso/post/GetRecords-all.xml">functionaltests/suites/apiso/post/GetRecords-all.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/apiso/post/GetRecords-filter-bbox.xml">functionaltests/suites/apiso/post/GetRecords-filter-bbox.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/apiso/post/GetRecords-filter-servicetype.xml">functionaltests/suites/apiso/post/GetRecords-filter-servicetype.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/apiso/post/GetRecords-filter-anytext.xml">functionaltests/suites/apiso/post/GetRecords-filter-anytext.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/apiso/post/GetRecords-filter-bbox-csw-output.xml">functionaltests/suites/apiso/post/GetRecords-filter-bbox-csw-output.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/apiso/data/T_ortho_RAS_1998_288395.xml">functionaltests/suites/apiso/data/T_ortho_RAS_1998_288395.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/apiso/data/T_pmoed_DTM_1996_276398.xml">functionaltests/suites/apiso/data/T_pmoed_DTM_1996_276398.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/apiso/data/pacioos-NS06agg.xml">functionaltests/suites/apiso/data/pacioos-NS06agg.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/apiso/data/T_aerfo_RAS_1991_GR800P001800000013.xml">functionaltests/suites/apiso/data/T_aerfo_RAS_1991_GR800P001800000013.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/apiso/data/3e9a8c05.xml">functionaltests/suites/apiso/data/3e9a8c05.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/apiso/data/T_aerfo_RAS_1991_GR800P001800000012.xml">functionaltests/suites/apiso/data/T_aerfo_RAS_1991_GR800P001800000012.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/apiso/data/T_pmoed_DTM_1996_280395.xml">functionaltests/suites/apiso/data/T_pmoed_DTM_1996_280395.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/apiso/data/test.xml">functionaltests/suites/apiso/data/test.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/apiso/data/T_pmoed_DTM_1996_276401.xml">functionaltests/suites/apiso/data/T_pmoed_DTM_1996_276401.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/apiso/data/T_ortho_RAS_1998_288398.xml">functionaltests/suites/apiso/data/T_ortho_RAS_1998_288398.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/apiso/data/T_ortho_RAS_1998_288404.xml">functionaltests/suites/apiso/data/T_ortho_RAS_1998_288404.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/apiso/data/T_pmoed_DTM_1996_276395.xml">functionaltests/suites/apiso/data/T_pmoed_DTM_1996_276395.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/apiso/data/T_ortho_RAS_1998_288401.xml">functionaltests/suites/apiso/data/T_ortho_RAS_1998_288401.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/apiso/data/T_aerfo_RAS_1991_GR800P001800000014.xml">functionaltests/suites/apiso/data/T_aerfo_RAS_1991_GR800P001800000014.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/apiso/data/T_ortho_RAS_1998_284404.xml">functionaltests/suites/apiso/data/T_ortho_RAS_1998_284404.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/apiso/data/T_pmoed_DTM_1996_276404.xml">functionaltests/suites/apiso/data/T_pmoed_DTM_1996_276404.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/apiso/data/T_aerfo_RAS_1991_GR800P001800000015.xml">functionaltests/suites/apiso/data/T_aerfo_RAS_1991_GR800P001800000015.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/gm03/expected/post_GetRecords-filter-bbox.xml">functionaltests/suites/gm03/expected/post_GetRecords-filter-bbox.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/gm03/expected/post_GetCapabilities.xml">functionaltests/suites/gm03/expected/post_GetCapabilities.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/gm03/post/GetCapabilities.xml">functionaltests/suites/gm03/post/GetCapabilities.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/gm03/post/GetRecords-filter-bbox.xml">functionaltests/suites/gm03/post/GetRecords-filter-bbox.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/manager/expected/post_Transaction-iso-05-delete.xml">functionaltests/suites/manager/expected/post_Transaction-iso-05-delete.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/manager/expected/post_Transaction-iso-03-update-recprop.xml">functionaltests/suites/manager/expected/post_Transaction-iso-03-update-recprop.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/manager/expected/post_Transaction-000-delete-all.xml">functionaltests/suites/manager/expected/post_Transaction-000-delete-all.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/manager/expected/post_Transaction-dc-01-insert.xml">functionaltests/suites/manager/expected/post_Transaction-dc-01-insert.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/manager/expected/post_Transaction-iso-04-update-recprop-no-matches.xml">functionaltests/suites/manager/expected/post_Transaction-iso-04-update-recprop-no-matches.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/manager/expected/post_Transaction-iso-01-insert.xml">functionaltests/suites/manager/expected/post_Transaction-iso-01-insert.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/manager/expected/post_Clear-000-delete-all.xml">functionaltests/suites/manager/expected/post_Clear-000-delete-all.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/manager/expected/post_Transaction-dc-02-update-full.xml">functionaltests/suites/manager/expected/post_Transaction-dc-02-update-full.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/manager/expected/post_GetCapabilities.xml">functionaltests/suites/manager/expected/post_GetCapabilities.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/manager/expected/post_Transaction-fgdc-02-update-recprop.xml">functionaltests/suites/manager/expected/post_Transaction-fgdc-02-update-recprop.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/manager/expected/post_Transaction-xxx-delete-all.xml">functionaltests/suites/manager/expected/post_Transaction-xxx-delete-all.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/manager/expected/post_GetDomain-parameter.xml">functionaltests/suites/manager/expected/post_GetDomain-parameter.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/manager/expected/post_Transaction-iso-00-delete-all.xml">functionaltests/suites/manager/expected/post_Transaction-iso-00-delete-all.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/manager/expected/post_Transaction-fgdc-01-insert.xml">functionaltests/suites/manager/expected/post_Transaction-fgdc-01-insert.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/manager/expected/post_Transaction-fgdc-03-delete-all.xml">functionaltests/suites/manager/expected/post_Transaction-fgdc-03-delete-all.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/manager/expected/post_Transaction-iso-02-update-full.xml">functionaltests/suites/manager/expected/post_Transaction-iso-02-update-full.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/manager/post/Transaction-xxx-delete-all.xml">functionaltests/suites/manager/post/Transaction-xxx-delete-all.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/manager/post/Transaction-fgdc-03-delete-all.xml">functionaltests/suites/manager/post/Transaction-fgdc-03-delete-all.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/manager/post/Transaction-iso-02-update-full.xml">functionaltests/suites/manager/post/Transaction-iso-02-update-full.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/manager/post/Transaction-iso-01-insert.xml">functionaltests/suites/manager/post/Transaction-iso-01-insert.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/manager/post/Transaction-fgdc-01-insert.xml">functionaltests/suites/manager/post/Transaction-fgdc-01-insert.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/manager/post/Transaction-dc-02-update-full.xml">functionaltests/suites/manager/post/Transaction-dc-02-update-full.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/manager/post/Transaction-000-delete-all.xml">functionaltests/suites/manager/post/Transaction-000-delete-all.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/manager/post/GetDomain-parameter.xml">functionaltests/suites/manager/post/GetDomain-parameter.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/manager/post/GetCapabilities.xml">functionaltests/suites/manager/post/GetCapabilities.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/manager/post/Transaction-dc-01-insert.xml">functionaltests/suites/manager/post/Transaction-dc-01-insert.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/manager/post/Transaction-iso-03-update-recprop.xml">functionaltests/suites/manager/post/Transaction-iso-03-update-recprop.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/manager/post/Transaction-iso-00-delete-all.xml">functionaltests/suites/manager/post/Transaction-iso-00-delete-all.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/manager/post/Transaction-iso-05-delete.xml">functionaltests/suites/manager/post/Transaction-iso-05-delete.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/manager/post/Transaction-iso-04-update-recprop-no-matches.xml">functionaltests/suites/manager/post/Transaction-iso-04-update-recprop-no-matches.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/manager/post/Clear-000-delete-all.xml">functionaltests/suites/manager/post/Clear-000-delete-all.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/manager/post/Transaction-fgdc-02-update-recprop.xml">functionaltests/suites/manager/post/Transaction-fgdc-02-update-recprop.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/expected/post_GetDomain-property.xml">functionaltests/suites/default/expected/post_GetDomain-property.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/expected/post_GetRecords-end.xml">functionaltests/suites/default/expected/post_GetRecords-end.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/expected/post_GetRecords-filter-or-title-abstract.xml">functionaltests/suites/default/expected/post_GetRecords-filter-or-title-abstract.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/expected/get_Exception-GetRepositoryItem-version-invalid.xml">functionaltests/suites/default/expected/get_Exception-GetRepositoryItem-version-invalid.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/expected/post_GetRecords-filter-bbox.xml">functionaltests/suites/default/expected/post_GetRecords-filter-bbox.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/expected/post_GetRecords-all-sortby-bbox.xml">functionaltests/suites/default/expected/post_GetRecords-all-sortby-bbox.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/expected/post_GetRecords-cql-title-and-abstract.xml">functionaltests/suites/default/expected/post_GetRecords-cql-title-and-abstract.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/expected/post_DescribeRecord.xml">functionaltests/suites/default/expected/post_DescribeRecord.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/expected/post_GetRecords-filter-anytext-and-not.xml">functionaltests/suites/default/expected/post_GetRecords-filter-anytext-and-not.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/expected/get_GetRecords-filter-cql-title-with-spaces-or-abstract-with-spaces.xml">functionaltests/suites/default/expected/get_GetRecords-filter-cql-title-with-spaces-or-abstract-with-spaces.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/expected/post_Transaction-update-full.xml">functionaltests/suites/default/expected/post_Transaction-update-full.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/expected/get_Exception-GetRepositoryItem-service-invalid1.xml">functionaltests/suites/default/expected/get_Exception-GetRepositoryItem-service-invalid1.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/expected/post_GetRecords-all-resulttype-hits.xml">functionaltests/suites/default/expected/post_GetRecords-all-resulttype-hits.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/expected/post_Harvest-default.xml">functionaltests/suites/default/expected/post_Harvest-default.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/expected/get_GetRecords-sortby-invalid-propertyname.xml">functionaltests/suites/default/expected/get_GetRecords-sortby-invalid-propertyname.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/expected/post_DescribeRecord-json.xml">functionaltests/suites/default/expected/post_DescribeRecord-json.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/expected/post_GetRecords-all-resulttype-validate.xml">functionaltests/suites/default/expected/post_GetRecords-all-resulttype-validate.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/expected/post_GetRecords-filter-and-nested-or.xml">functionaltests/suites/default/expected/post_GetRecords-filter-and-nested-or.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/expected/get_GetRepositoryItem.xml">functionaltests/suites/default/expected/get_GetRepositoryItem.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/expected/post_GetCapabilities-SOAP.xml">functionaltests/suites/default/expected/post_GetCapabilities-SOAP.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/expected/post_GetRecordById.xml">functionaltests/suites/default/expected/post_GetRecordById.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/expected/post_GetRecords-bbox-filter-crs84.xml">functionaltests/suites/default/expected/post_GetRecords-bbox-filter-crs84.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/expected/post_GetRecords-filter-or-bbox-freetext.xml">functionaltests/suites/default/expected/post_GetRecords-filter-or-bbox-freetext.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/expected/get_GetRecords-sortby-asc.xml">functionaltests/suites/default/expected/get_GetRecords-sortby-asc.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/expected/get_GetRecords-filter-cql-title-or-abstract-with-spaces.xml">functionaltests/suites/default/expected/get_GetRecords-filter-cql-title-or-abstract-with-spaces.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/expected/post_GetRecords-filter-between.xml">functionaltests/suites/default/expected/post_GetRecords-filter-between.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/expected/get_GetRecords-empty-maxrecords.xml">functionaltests/suites/default/expected/get_GetRecords-empty-maxrecords.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/expected/post_GetRecords-filter-anytext-equal.xml">functionaltests/suites/default/expected/post_GetRecords-filter-anytext-equal.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/expected/post_GetRecords-filter-not-bbox.xml">functionaltests/suites/default/expected/post_GetRecords-filter-not-bbox.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/expected/post_GetRecords-filter-bbox-sortby.xml">functionaltests/suites/default/expected/post_GetRecords-filter-bbox-sortby.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/expected/post_GetRecords-maxrecords.xml">functionaltests/suites/default/expected/post_GetRecords-maxrecords.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/expected/post_Transaction-insert.xml">functionaltests/suites/default/expected/post_Transaction-insert.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/expected/get_GetRecords-filter-cql-title-with-spaces-or-abstract.xml">functionaltests/suites/default/expected/get_GetRecords-filter-cql-title-with-spaces-or-abstract.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/expected/get_GetRecords-sortby-desc.xml">functionaltests/suites/default/expected/get_GetRecords-sortby-desc.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/expected/post_GetRecords-all-json.xml">functionaltests/suites/default/expected/post_GetRecords-all-json.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/expected/post_Transaction-update-recordproperty.xml">functionaltests/suites/default/expected/post_Transaction-update-recordproperty.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/expected/post_GetRecords-requestid.xml">functionaltests/suites/default/expected/post_GetRecords-requestid.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/expected/post_GetCapabilities.xml">functionaltests/suites/default/expected/post_GetCapabilities.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/expected/get_GetRecords-filter-cql-title.xml">functionaltests/suites/default/expected/get_GetRecords-filter-cql-title.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/expected/post_GetRecords-cql-title.xml">functionaltests/suites/default/expected/post_GetRecords-cql-title.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/expected/post_Exception-GetRecords-invalid-xml.xml">functionaltests/suites/default/expected/post_Exception-GetRecords-invalid-xml.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/expected/post_GetRecords-filter-and-bbox-freetext.xml">functionaltests/suites/default/expected/post_GetRecords-filter-and-bbox-freetext.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/expected/get_GetRecords-filter-cql-title-with-spaces.xml">functionaltests/suites/default/expected/get_GetRecords-filter-cql-title-with-spaces.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/expected/post_GetDomain-parameter.xml">functionaltests/suites/default/expected/post_GetDomain-parameter.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/expected/post_GetRecords-filter-function-bad.xml">functionaltests/suites/default/expected/post_GetRecords-filter-function-bad.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/expected/post_GetRecords-filter-and-nested-or2.xml">functionaltests/suites/default/expected/post_GetRecords-filter-and-nested-or2.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/expected/post_GetRecords-filter-bbox-reproject.xml">functionaltests/suites/default/expected/post_GetRecords-filter-bbox-reproject.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/expected/post_GetRecordById-json.xml">functionaltests/suites/default/expected/post_GetRecordById-json.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/expected/post_Harvest-response-handler.xml">functionaltests/suites/default/expected/post_Harvest-response-handler.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/expected/post_GetCapabilities-sections.xml">functionaltests/suites/default/expected/post_GetCapabilities-sections.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/expected/post_GetRecords-all.xml">functionaltests/suites/default/expected/post_GetRecords-all.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/expected/post_GetRecords-elementname.xml">functionaltests/suites/default/expected/post_GetRecords-elementname.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/expected/post_GetRecords-filter-or-nested-and.xml">functionaltests/suites/default/expected/post_GetRecords-filter-or-nested-and.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/expected/get_GetCapabilities.xml">functionaltests/suites/default/expected/get_GetCapabilities.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/expected/post_GetCapabilities-updatesequence.xml">functionaltests/suites/default/expected/post_GetCapabilities-updatesequence.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/expected/post_GetRecords-distributedsearch.xml">functionaltests/suites/default/expected/post_GetRecords-distributedsearch.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/expected/get_GetRecords-filter.xml">functionaltests/suites/default/expected/get_GetRecords-filter.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/expected/post_GetRecords-filter-function.xml">functionaltests/suites/default/expected/post_GetRecords-filter-function.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/expected/post_GetRecords-filter-anytext.xml">functionaltests/suites/default/expected/post_GetRecords-filter-anytext.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/expected/post_Exception-GetRecords-elementname.xml">functionaltests/suites/default/expected/post_Exception-GetRecords-elementname.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/expected/get_Exception-GetRepositoryItem-notfound.xml">functionaltests/suites/default/expected/get_Exception-GetRepositoryItem-notfound.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/expected/post_Transaction-delete.xml">functionaltests/suites/default/expected/post_Transaction-delete.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/expected/get_Exception-GetRepositoryItem-service-invalid2.xml">functionaltests/suites/default/expected/get_Exception-GetRepositoryItem-service-invalid2.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/expected/post_Exception-GetRecords-badsrsname.xml">functionaltests/suites/default/expected/post_Exception-GetRecords-badsrsname.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/expected/get_GetRecords-filter-cql-title-or-abstract.xml">functionaltests/suites/default/expected/get_GetRecords-filter-cql-title-or-abstract.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/expected/get_GetCapabilities-invalid-request.xml">functionaltests/suites/default/expected/get_GetCapabilities-invalid-request.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/expected/get_GetRecords-sortby-invalid-order.xml">functionaltests/suites/default/expected/get_GetRecords-sortby-invalid-order.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/expected/get_GetRecords-all.xml">functionaltests/suites/default/expected/get_GetRecords-all.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/post/Transaction-delete.xml">functionaltests/suites/default/post/Transaction-delete.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/post/GetCapabilities-sections.xml">functionaltests/suites/default/post/GetCapabilities-sections.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/post/GetRecords-filter-or-nested-and.xml">functionaltests/suites/default/post/GetRecords-filter-or-nested-and.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/post/GetRecords-filter-anytext-and-not.xml">functionaltests/suites/default/post/GetRecords-filter-anytext-and-not.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/post/Harvest-response-handler.xml">functionaltests/suites/default/post/Harvest-response-handler.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/post/GetDomain-property.xml">functionaltests/suites/default/post/GetDomain-property.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/post/GetRecords-all-resulttype-validate.xml">functionaltests/suites/default/post/GetRecords-all-resulttype-validate.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/post/GetRecords-cql-title.xml">functionaltests/suites/default/post/GetRecords-cql-title.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/post/Exception-GetRecords-invalid-xml.xml">functionaltests/suites/default/post/Exception-GetRecords-invalid-xml.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/post/GetRecords-filter-not-bbox.xml">functionaltests/suites/default/post/GetRecords-filter-not-bbox.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/post/GetRecords-maxrecords.xml">functionaltests/suites/default/post/GetRecords-maxrecords.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/post/GetRecords-all-resulttype-hits.xml">functionaltests/suites/default/post/GetRecords-all-resulttype-hits.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/post/GetRecords-filter-between.xml">functionaltests/suites/default/post/GetRecords-filter-between.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/post/GetRecords-filter-function.xml">functionaltests/suites/default/post/GetRecords-filter-function.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/post/GetCapabilities-updatesequence.xml">functionaltests/suites/default/post/GetCapabilities-updatesequence.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/post/DescribeRecord.xml">functionaltests/suites/default/post/DescribeRecord.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/post/GetRecords-filter-anytext-equal.xml">functionaltests/suites/default/post/GetRecords-filter-anytext-equal.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/post/DescribeRecord-json.xml">functionaltests/suites/default/post/DescribeRecord-json.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/post/GetDomain-parameter.xml">functionaltests/suites/default/post/GetDomain-parameter.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/post/GetRecords-filter-or-bbox-freetext.xml">functionaltests/suites/default/post/GetRecords-filter-or-bbox-freetext.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/post/GetRecords-filter-and-nested-or.xml">functionaltests/suites/default/post/GetRecords-filter-and-nested-or.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/post/Harvest-default.xml">functionaltests/suites/default/post/Harvest-default.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/post/GetCapabilities.xml">functionaltests/suites/default/post/GetCapabilities.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/post/GetRecords-elementname.xml">functionaltests/suites/default/post/GetRecords-elementname.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/post/GetCapabilities-SOAP.xml">functionaltests/suites/default/post/GetCapabilities-SOAP.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/post/Transaction-update-recordproperty.xml">functionaltests/suites/default/post/Transaction-update-recordproperty.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/post/GetRecords-all.xml">functionaltests/suites/default/post/GetRecords-all.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/post/Exception-GetRecords-badsrsname.xml">functionaltests/suites/default/post/Exception-GetRecords-badsrsname.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/post/GetRecords-filter-bbox.xml">functionaltests/suites/default/post/GetRecords-filter-bbox.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/post/GetRecords-filter-or-title-abstract.xml">functionaltests/suites/default/post/GetRecords-filter-or-title-abstract.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/post/GetRecords-filter-and-nested-or2.xml">functionaltests/suites/default/post/GetRecords-filter-and-nested-or2.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/post/GetRecords-all-json.xml">functionaltests/suites/default/post/GetRecords-all-json.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/post/GetRecordById-json.xml">functionaltests/suites/default/post/GetRecordById-json.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/post/GetRecords-distributedsearch.xml">functionaltests/suites/default/post/GetRecords-distributedsearch.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/post/Transaction-update-full.xml">functionaltests/suites/default/post/Transaction-update-full.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/post/GetRecordById.xml">functionaltests/suites/default/post/GetRecordById.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/post/GetRecords-requestid.xml">functionaltests/suites/default/post/GetRecords-requestid.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/post/GetRecords-filter-anytext.xml">functionaltests/suites/default/post/GetRecords-filter-anytext.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/post/GetRecords-filter-bbox-sortby.xml">functionaltests/suites/default/post/GetRecords-filter-bbox-sortby.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/post/GetRecords-end.xml">functionaltests/suites/default/post/GetRecords-end.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/post/GetRecords-filter-and-bbox-freetext.xml">functionaltests/suites/default/post/GetRecords-filter-and-bbox-freetext.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/post/Exception-GetRecords-elementname.xml">functionaltests/suites/default/post/Exception-GetRecords-elementname.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/post/GetRecords-filter-function-bad.xml">functionaltests/suites/default/post/GetRecords-filter-function-bad.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/post/GetRecords-all-sortby-bbox.xml">functionaltests/suites/default/post/GetRecords-all-sortby-bbox.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/post/Transaction-insert.xml">functionaltests/suites/default/post/Transaction-insert.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/post/GetRecords-filter-bbox-reproject.xml">functionaltests/suites/default/post/GetRecords-filter-bbox-reproject.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/post/GetRecords-bbox-filter-crs84.xml">functionaltests/suites/default/post/GetRecords-bbox-filter-crs84.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/default/post/GetRecords-cql-title-and-abstract.xml">functionaltests/suites/default/post/GetRecords-cql-title-and-abstract.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/utf-8/expected/post_GetCapabilities.xml">functionaltests/suites/utf-8/expected/post_GetCapabilities.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/utf-8/post/GetCapabilities.xml">functionaltests/suites/utf-8/post/GetCapabilities.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/sru/expected/get_search_cql.xml">functionaltests/suites/sru/expected/get_search_cql.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/sru/expected/get_search.xml">functionaltests/suites/sru/expected/get_search.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/sru/expected/get_search_startrecord_maxrecords.xml">functionaltests/suites/sru/expected/get_search_startrecord_maxrecords.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/sru/expected/get_explain.xml">functionaltests/suites/sru/expected/get_explain.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/sru/expected/get_search_maxrecords.xml">functionaltests/suites/sru/expected/get_search_maxrecords.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/ebrim/expected/post_GetRecords-filter-bbox.xml">functionaltests/suites/ebrim/expected/post_GetRecords-filter-bbox.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/ebrim/expected/post_DescribeRecord.xml">functionaltests/suites/ebrim/expected/post_DescribeRecord.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/ebrim/expected/post_GetCapabilities.xml">functionaltests/suites/ebrim/expected/post_GetCapabilities.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/ebrim/expected/post_GetRecords-filter-bbox-full.xml">functionaltests/suites/ebrim/expected/post_GetRecords-filter-bbox-full.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/ebrim/post/DescribeRecord.xml">functionaltests/suites/ebrim/post/DescribeRecord.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/ebrim/post/GetCapabilities.xml">functionaltests/suites/ebrim/post/GetCapabilities.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/ebrim/post/GetRecords-filter-bbox.xml">functionaltests/suites/ebrim/post/GetRecords-filter-bbox.xml</option>
+                            <option value="tests/functionaltests/suites/suites/default.cfg,functionaltests/suites/ebrim/post/GetRecords-filter-bbox-full.xml">functionaltests/suites/ebrim/post/GetRecords-filter-bbox-full.xml</option>
 
                         </select>
                         <input type="button" class="send" value="Send"/>
@@ -301,174 +657,174 @@
         <h3 class="header">HTTP GET</h3>
             <ul>
 
-<li><a href="../csw.py?config=tests/suites/apiso-inspire/default.cfg&service=CSW&version=2.0.2&request=GetCapabilities">GetCapabilities</a></li>
-<li><a href="../csw.py?config=tests/suites/apiso-inspire/default.cfg&service=CSW&version=2.0.2&request=GetCapabilities&lang=gre">GetCapabilities-lang</a></li>
-<li><a href="../csw.py?config=tests/suites/atom/default.cfg&mode=opensearch&service=CSW&version=2.0.2&request=GetRecords&typenames=csw:Record&resulttype=results&elementsetname=brief">opensearch</a></li>
-<li><a href="../csw.py?config=tests/suites/atom/default.cfg&mode=opensearch&service=CSW&version=2.0.2&request=GetCapabilities">opensearch-description</a></li>
-<li><a href="../csw.py?config=tests/suites/atom/default.cfg&mode=opensearch&service=CSW&version=2.0.2&request=GetRecords&elementsetname=full&resulttype=results&typenames=csw:Record&q=greece">opensearch-ogc-q</a></li>
-<li><a href="../csw.py?config=tests/suites/atom/default.cfg&mode=opensearch&service=CSW&version=2.0.2&request=GetRecords&elementsetname=full&resulttype=results&typenames=csw:Record&bbox=-180,-90,180,90">opensearch-ogc-bbox</a></li>
-<li><a href="../csw.py?config=tests/suites/atom/default.cfg&mode=opensearch&service=CSW&version=2.0.2&request=GetRecords&elementsetname=full&resulttype=results&typenames=csw:Record&time=2001/2004">opensearch-ogc-time</a></li>
-<li><a href="../csw.py?config=tests/suites/atom/default.cfg&mode=opensearch&service=CSW&version=2.0.2&request=GetRecords&elementsetname=full&resulttype=results&typenames=csw:Record&time=2004/">opensearch-ogc-timestart</a></li>
-<li><a href="../csw.py?config=tests/suites/atom/default.cfg&mode=opensearch&service=CSW&version=2.0.2&request=GetRecords&elementsetname=full&resulttype=results&typenames=csw:Record&time=/2004">opensearch-ogc-timeend</a></li>
-<li><a href="../csw.py?config=tests/suites/atom/default.cfg&mode=opensearch&service=CSW&version=2.0.2&request=GetRecords&elementsetname=full&resulttype=results&typenames=csw:Record&time=2001/2007&q=vitae">opensearch-ogc-q-and-time</a></li>
-<li><a href="../csw.py?config=tests/suites/atom/default.cfg&mode=opensearch&service=CSW&version=2.0.2&request=GetRecords&elementsetname=full&resulttype=results&typenames=csw:Record&time=2001/2007&bbox=-180,-90,180,90">opensearch-ogc-bbox-and-time</a></li>
-<li><a href="../csw.py?config=tests/suites/atom/default.cfg&mode=opensearch&service=CSW&version=2.0.2&request=GetRecords&elementsetname=full&resulttype=results&typenames=csw:Record&q=vegetation&bbox=-180,-90,180,90">opensearch-ogc-q-and-bbox</a></li>
-<li><a href="../csw.py?config=tests/suites/atom/default.cfg&mode=opensearch&service=CSW&version=2.0.2&request=GetRecords&elementsetname=full&resulttype=results&typenames=csw:Record&q=vegetation&startposition=1">opensearch-ogc-count-and-page1</a></li>
-<li><a href="../csw.py?config=tests/suites/atom/default.cfg&mode=opensearch&service=CSW&version=2.0.2&request=GetRecords&elementsetname=full&resulttype=results&typenames=csw:Record&q=vegetation&startposition=1&maxrecords=1">opensearch-ogc-count-and-page2</a></li>
-<li><a href="../csw.py?config=tests/suites/cite/default.cfg&service=CSW&version=2.0.2&request=GetCapabilities">27e17158-c57a-4493-92ac-dba8934cf462</a></li>
-<li><a href="../csw.py?config=tests/suites/cite/default.cfg&Service=CSW&Version=2.0.2&Request=GetRecordById&ElementSetName=brief&ID=urn%3Auuid%3A19887a8a-f6b0-4a63-ae56-7fba0e17801f">27f69b66-5f05-4311-a89c-73ca55c2686b</a></li>
-<li><a href="../csw.py?config=tests/suites/cite/default.cfg&service=CSW&request=GetCapabilities&acceptversions=2.0.2&date=2006-10-20">2ab7d1fa-885b-459f-80e4-b6282eab4f8c</a></li>
-<li><a href="../csw.py?config=tests/suites/cite/default.cfg&service=CSW&version=2.0.2&request=GetRecordById&id=urn%3Auuid%3A9a669547-b69b-469f-a11f-2d875366bbdc">37aa90e2-6ff0-420c-af15-8b9463099a73</a></li>
-<li><a href="../csw.py?config=tests/suites/cite/default.cfg&service=CSW&request=GetCapabilities&acceptformats=message/example">3a8a3c47-455f-4f49-9078-03119f3e70b3</a></li>
-<li><a href="../csw.py?config=tests/suites/cite/default.cfg&service=CSW&version=2.0.2&request=GetRecordById">4515831f-834a-4699-95f6-ab0c2cbfcfd0</a></li>
-<li><a href="../csw.py?config=tests/suites/cite/default.cfg&service=CSW&request=GetCapabilities&sections=">477b23a3-baa9-47c8-9541-5fe27735ed49</a></li>
-<li><a href="../csw.py?config=tests/suites/cite/default.cfg&sErViCe=CSW&REQUEST=GetCapabilities&version=2.0.2">48f26761-3a9d-48db-bee1-da089f5fb857</a></li>
-<li><a href="../csw.py?config=tests/suites/cite/default.cfg&Service=CSW&Version=2.0.2&Request=GetRecordById&OutputFormat=application/bogus_xml&id=urn:uuid:a06af396-3105-442d-8b40-22b57a90d2f2">4e38092f-1586-44b8-988e-0acfa5855916</a></li>
-<li><a href="../csw.py?config=tests/suites/cite/default.cfg&service=CSW&request=GetCapabilities&sections=OperationsMetadata">55c38f00-2553-42c1-99ab-33edbb561ad7</a></li>
-<li><a href="../csw.py?config=tests/suites/cite/default.cfg&service=FOO&request=GetCapabilities">5ab5db18-c87a-4fbf-a8d8-b7289b09ac81</a></li>
-<li><a href="../csw.py?config=tests/suites/cite/default.cfg&service=CSW&version=2.0.2&request=GetRecordById&id=urn:uuid:ce8627a0-685c-11db-bd13-0800200c9a66">6a4f57ca-a1bd-4802-89c2-44860dbdb0f0</a></li>
-<li><a href="../csw.py?config=tests/suites/cite/default.cfg&Service=CSW&Version=2.0.2&Request=GetRecordById&OutputSchema=http://www.w3.org/2005/Atom&Id=urn:uuid:19887a8a-f6b0-4a63-ae56-7fba0e17801f">6c375703-9c00-4aef-bec7-d2e964f849eb</a></li>
-<li><a href="../csw.py?config=tests/suites/cite/default.cfg&service=CSW&request=GetCapabilities">80f31def-4185-48b9-983a-960566918eae</a></li>
-<li><a href="../csw.py?config=tests/suites/cite/default.cfg&SERVICE=CSW&REQUEST=GetCapabilities&ACCEPTVERSIONS=2006.10.29">8e2232ed-05d9-44ae-8b04-0911cbe6a507</a></li>
-<li><a href="../csw.py?config=tests/suites/cite/default.cfg&service=CSW&request=GetCapabilities">9697f0aa-3b6a-4125-83a5-61e8826127c4</a></li>
-<li><a href="../csw.py?config=tests/suites/cite/default.cfg&Service=CSW&Version=2.0.2&Request=GetRecordById&ElementSetName=full&ID=urn%3Auuid%3Ae9330592-0932-474b-be34-c3a3bb67c7db">9bfd17fa-15dc-4a10-8fa7-b3cff7013dd7</a></li>
-<li><a href="../csw.py?config=tests/suites/cite/default.cfg&service=CSW&version=2.0.2&request=GetRecordById&id=urn:uuid:ce8627a0-685c-11db-bd13-0800200c9a66">b81c3595-06d6-4693-82ea-1ff8650755ac</a></li>
-<li><a href="../csw.py?config=tests/suites/cite/default.cfg&SERVICE=CSW&REQUEST=GetCapabilities&ACCEPTVERSIONS=2.0.2">ba5fc729-3b71-47a0-b7d0-42ec565cd185</a></li>
-<li><a href="../csw.py?config=tests/suites/cite/default.cfg&request=GetCapabilities">c4ea754f-c158-4d8d-8253-dc8f86021b52</a></li>
-<li><a href="../csw.py?config=tests/suites/cite/default.cfg&service=CSW&version=2.0.2&request=GetCapabilities">f4692ec5-9547-4a05-88ab-e6154af2640a</a></li>
-<li><a href="../csw.py?config=tests/suites/cite/default.cfg&service=CSW&version=2.0.2&request=GetRecordById&id=urn:uuid:94bc9c83-97f6-4b40-9eb8-a8e8787a5c63">f997f25e-c865-4d53-a362-0ed1846337f2</a></li>
-<li><a href="../csw.py?config=tests/suites/csw30/default.cfg">GetCapabilities-base-url</a></li>
-<li><a href="../csw.py?config=tests/suites/csw30/default.cfg&service=CSW&request=GetCapabilities">GetCapabilities-no-version</a></li>
-<li><a href="../csw.py?config=tests/suites/csw30/default.cfg&service=CSW&version=3.0.0&request=GetCapabilities">GetCapabilities</a></li>
-<li><a href="../csw.py?config=tests/suites/csw30/default.cfg&service=CSW&version=3.0.0&request=GetCapabilities-foo">Exception-invalid-request</a></li>
-<li><a href="../csw.py?config=tests/suites/csw30/default.cfg&service=CSW&version=3.0.0&request=GetDomain">Exception-GetDomain</a></li>
-<li><a href="../csw.py?config=tests/suites/csw30/default.cfg&service=CSW&version=3.0.0&request=GetDomain&parametername=GetRecords.ElementSetName">GetDomain-parameter</a></li>
-<li><a href="../csw.py?config=tests/suites/csw30/default.cfg&service=CSW&version=3.0.0&request=GetDomain&valuereference=dc:title">GetDomain-value-reference</a></li>
-<li><a href="../csw.py?config=tests/suites/csw30/default.cfg&service=CSW&version=3.0.0&request=GetDomain&valuereference=dc:title2">Exception-GetDomain-value-reference</a></li>
-<li><a href="../csw.py?config=tests/suites/csw30/default.cfg&service=CSW&version=3.0.0&request=GetRecordById&id=urn:uuid:829babb0-b2f1-49e1-8cd5-7b489fe71a1e">Exception-GetRecordById-dc.xml</a></li>
-<li><a href="../csw.py?config=tests/suites/csw30/default.cfg&service=CSW&version=3.0.0&request=GetRecordById&id=does_not_exist2">Exception-GetRecordById-404</a></li>
-<li><a href="../csw.py?config=tests/suites/csw30/default.cfg&mode=opensearch&service=CSW&version=3.0.0&request=GetCapabilities">OpenSearch-description</a></li>
-<li><a href="../csw.py?config=tests/suites/csw30/default.cfg&service=CSW&version=3.0.0&request=GetRepositoryItem&id=urn:uuid:19887a8a-f6b0-4a63-ae56-7fba0e17801f">GetRepositoryItem</a></li>
-<li><a href="../csw.py?config=tests/suites/csw30/default.cfg&service=CSW&version=3.0.0&request=GetRepositoryItem&id=NOTFOUND">Exception-GetRepositoryItem-notfound</a></li>
-<li><a href="../csw.py?config=tests/suites/csw30/default.cfg&mode=opensearch&service=CSW&version=3.0.0&request=GetCapabilities">002258f0-627f-457f-b2ad-025777c77ac8</a></li>
-<li><a href="../csw.py?config=tests/suites/csw30/default.cfg&mode=opensearch&service=CSW&version=3.0.0&request=GetRecords&elementsetname=full&typenames=csw:Record&resulttype=results&q=Fusc%C3%A9%20Land&bbox=&time=/&outputformat=application/atom%2Bxml&startposition=1&maxrecords=&recordids=">045c600d-973d-41eb-9f60-eba1b717b720</a></li>
-<li><a href="../csw.py?config=tests/suites/csw30/default.cfg&elementSetName=summary&outputFormat=application/atom%2Bxml&request=GetRecords&service=CSW&typeNames=Record&version=3.0.0">0bbcf862-5211-4351-9988-63f8bec49c98</a></li>
-<li><a href="../csw.py?config=tests/suites/csw30/default.cfg">0bdf8457-971e-4ed1-be4a-5feca4dcd8fa</a></li>
-<li><a href="../csw.py?config=tests/suites/csw30/default.cfg&elementName=tns:title&request=GetRecords&service=CSW&typeNames=Record&namespace=xmlns(tns%3Dhttp://purl.org/dc/elements/1.1/)&version=3.0.0">0d8bbdec-0846-42ca-8dc8-b7f4cba41d67</a></li>
-<li><a href="../csw.py?config=tests/suites/csw30/default.cfg&mode=opensearch&service=CSW&version=3.0.0&request=GetRecords&elementsetname=full&typenames=csw:Record&resulttype=results&q=lpppclq&bbox=&time=/&outputformat=application/atom%2Bxml&startposition=1&maxrecords=&recordids=">0e1dca37-477a-4060-99fe-7799b52d656c</a></li>
-<li><a href="../csw.py?config=tests/suites/csw30/default.cfg&elementSetName=full&maxRecords=20&request=GetRecords&service=CSW&typeNames=Record&version=3.0.0">13c87956-51a4-4780-a8e9-6e0b5c0bb473</a></li>
-<li><a href="../csw.py?config=tests/suites/csw30/default.cfg&acceptFormats=model/x3d%2Bxml&acceptVersions=3.0.0&request=GetCapabilities&service=CSW">151d982f-ebd3-4cb2-b507-a667713a1e92</a></li>
-<li><a href="../csw.py?config=tests/suites/csw30/default.cfg&acceptVersions=3.0.0&request=GetCapabilities">1869e495-1a61-4713-8285-76d1336ee1a6</a></li>
-<li><a href="../csw.py?config=tests/suites/csw30/default.cfg&request=GetRecordById&service=CSW&version=3.0.0">1bcb42a9-538c-4f0a-9d4c-d6f10b720aa6</a></li>
-<li><a href="../csw.py?config=tests/suites/csw30/default.cfg">22f44168-2ccf-4801-ad96-204212566d56</a></li>
-<li><a href="../csw.py?config=tests/suites/csw30/default.cfg&acceptVersions=3.0.0&sections=All&request=GetCapabilities&service=CSW">2499a9c9-8d33-449c-bc92-d494adfcc84d</a></li>
-<li><a href="../csw.py?config=tests/suites/csw30/default.cfg&acceptFormats=application/xml&acceptVersions=3.0.0&request=GetCapabilities&service=CSW">27f4f39c-d92a-4e3c-b961-c6aa8c24e513</a></li>
-<li><a href="../csw.py?config=tests/suites/csw30/default.cfg&id=urn:uuid:a06af396-3105-442d-8b40-22b57a90d2f2&request=GetRecordById&service=CSW&version=3.0.0">28e569df-8596-4128-8d9a-29ad03138915</a></li>
-<li><a href="../csw.py?config=tests/suites/csw30/default.cfg">2b06a5c8-0df2-4af1-8d2e-a425de11c845</a></li>
-<li><a href="../csw.py?config=tests/suites/csw30/default.cfg&maxRecords=2&elementSetName=summary&outputFormat=application/atom%2Bxml&request=GetRecords&service=CSW&typeNames=csw3:Record&startPosition=3&namespace=xmlns(csw3%3Dhttp://www.opengis.net/cat/csw/3.0)&version=3.0.0">2ba1418a-444d-4cce-9cfe-4c94efcf8b55</a></li>
-<li><a href="../csw.py?config=tests/suites/csw30/default.cfg&service=CSW&version=3.0.0&request=GetRecords&elementsetname=full&typenames=csw:Record&resulttype=results&q=ipsum&bbox=&time=/&outputformat=application/xml&outputschema=http://www.opengis.net/cat/csw/3.0&startposition=1&maxrecords=&recordids=">397fe17a-d5b4-4f96-8cc4-4ce467ed4d0a</a></li>
-<li><a href="../csw.py?config=tests/suites/csw30/default.cfg&elementSetName=brief&request=GetRecords&service=CSW&typeNames=tns:Record&namespace=xmlns(tns%3Dhttp://www.opengis.net/cat/csw/3.0)&version=3.0.0">3dcd1b15-73d2-4b7d-a3e3-ff15bf14aae4</a></li>
-<li><a href="../csw.py?config=tests/suites/csw30/default.cfg&elementSetName=summary&recordIds=urn:uuid:19887a8a-f6b0-4a63-ae56-7fba0e17801f">405e1ff1-5c75-4846-a28b-cfaff2a6921a</a></li>
-<li><a href="../csw.py?config=tests/suites/csw30/default.cfg">43cd6471-6ac7-45bd-8ff9-148cb2de9a52</a></li>
-<li><a href="../csw.py?config=tests/suites/csw30/default.cfg&acceptVersions=3.0.0&sections=ServiceIdentification&request=GetCapabilities&service=CSW">4566d2ec-1283-4a02-baed-a74fc5b47e37</a></li>
-<li><a href="../csw.py?config=tests/suites/csw30/default.cfg&acceptVersions=3.0.0&sections=Filter_Capabilities&request=GetCapabilities&service=CSW">461bd4c5-6623-490d-9036-d91a2201e87b</a></li>
-<li><a href="../csw.py?config=tests/suites/csw30/default.cfg&service=CSW&version=3.0.0&request=GetRecords&elementsetname=full&typenames=csw:Record&resulttype=results&q=&bbox=514432">5496894a-3877-4f62-a20b-5d7126f94925</a></li>
-<li><a href="../csw.py?config=tests/suites/csw30/default.cfg&service=CSW&version=3.0.0&request=GetRecords&elementsetname=full&typenames=csw:Record&resulttype=results&q=&bbox=-6.17">5a015f6a-bf14-4977-b1e3-6577eb0223c8</a></li>
-<li><a href="../csw.py?config=tests/suites/csw30/default.cfg&id=urn:uuid:88247b56-4cbc-4df9-9860-db3f8042e357&outputFormat=model/vnd.collada%2Bxml&request=GetRecordById&service=CSW&version=3.0.0">5c3a2390-1fb9-43f0-b96c-f48c7a69c990</a></li>
-<li><a href="../csw.py?config=tests/suites/csw30/default.cfg&acceptVersions=3.0.0&sections=OperationsMetadata&request=GetCapabilities&service=CSW">5e9e67dc-18d6-4645-8111-c6263c88a61f</a></li>
-<li><a href="../csw.py?config=tests/suites/csw30/default.cfg&elementSetName=full&q=amet&request=GetRecords&service=CSW&typeNames=Record&version=3.0.0">604d9379-741c-42e5-b4cf-92e56c87fa64</a></li>
-<li><a href="../csw.py?config=tests/suites/csw30/default.cfg&request=GetRecords&service=CSW&typeNames=UnknownType&version=3.0.0">60e6af95-d5fc-465a-82e2-fd2e6d85e4af</a></li>
-<li><a href="../csw.py?config=tests/suites/csw30/default.cfg&mode=opensearch&service=CSW&version=3.0.0&request=GetRecords&elementsetname=full&typenames=csw:Record&resulttype=results&q=&bbox=&time=/&outputformat=application/atom%2Bxml&startposition=1&maxrecords=&recordids=uid-bc5017e6-5cc8-4b03-aee7-d88f88caba0a">62ad94c2-b558-4265-a427-23d6677975d6</a></li>
-<li><a href="../csw.py?config=tests/suites/csw30/default.cfg&elementSetName=undefined-view&request=GetRecords&service=CSW&typeNames=Record&version=3.0.0">6a5e247b-0961-4b8a-a0d6-35a491d9cfe7</a></li>
-<li><a href="../csw.py?config=tests/suites/csw30/default.cfg">6a9d0558-9d87-495b-b999-b49a3ef1cf99</a></li>
-<li><a href="../csw.py?config=tests/suites/csw30/default.cfg&service=CSW&version=3.0.0&request=GetRecords&elementsetname=full&typenames=csw:Record&resulttype=results&q=Fusc%C3%A9%20Land&bbox=&time=/&outputformat=application/xml&outputschema=http://www.opengis.net/cat/csw/3.0&startposition=1&maxrecords=&recordids=">6bd790c9-6019-4652-9c91-330a894d6700</a></li>
-<li><a href="../csw.py?config=tests/suites/csw30/default.cfg&acceptVersions=3.0.0&request=GetCapabilities&service=CSW">6e9cba43-5e27-415d-adbd-a92851c2c173</a></li>
-<li><a href="../csw.py?config=tests/suites/csw30/default.cfg&id=urn:uuid:66ae76b7-54ba-489b-a582-0f0633d96493&request=GetRecordById&service=CSW&version=3.0.0">7630d230-e142-4a09-accf-f091000b90cd</a></li>
-<li><a href="../csw.py?config=tests/suites/csw30/default.cfg&acceptFormats=text/xml&acceptVersions=3.0.0&request=GetCapabilities&service=CSW">7e82446a-b5dc-43fe-9a73-4cc1f2f2f0bf</a></li>
-<li><a href="../csw.py?config=tests/suites/csw30/default.cfg">8025978e-1a35-4d70-80c2-e8329e0c7864</a></li>
-<li><a href="../csw.py?config=tests/suites/csw30/default.cfg&elementSetName=brief&bbox=44.79">8184ae4f-536d-4978-8b28-ad703be96967</a></li>
-<li><a href="../csw.py?config=tests/suites/csw30/default.cfg&maxRecords=15&elementSetName=summary&q=Mauris&bbox=-6.17">88f63a89-664f-4315-b4f8-04a0b33803a7</a></li>
-<li><a href="../csw.py?config=tests/suites/csw30/default.cfg&id=urn:example:1461546298217&request=GetRecordById&service=CSW&version=3.0.0">8987f8f0-4d93-4481-968c-a2ccbd6b8be2</a></li>
-<li><a href="../csw.py?config=tests/suites/csw30/default.cfg&mode=opensearch&service=CSW&version=3.0.0&request=GetRecords&elementsetname=full&typenames=csw:Record&resulttype=results&q=&bbox=-180">8e5fa0f6-3f29-4d1f-abe2-d9866f3def98</a></li>
-<li><a href="../csw.py?config=tests/suites/csw30/default.cfg&acceptVersions=9999.12.31&request=GetCapabilities&service=CSW">9000ec29-5649-474e-b2d6-55c00f8a52c0</a></li>
-<li><a href="../csw.py?config=tests/suites/csw30/default.cfg&elementSetName=summary&bbox=-6.17">91914d35-7bbf-45e6-9b37-5ef484869a4e</a></li>
-<li><a href="../csw.py?config=tests/suites/csw30/default.cfg&elementSetName=full&q=atkovxqmf&request=GetRecords&service=CSW&typeNames=Record&version=3.0.0">92d4844d-57d5-4cf3-8f47-ba50e369dc04</a></li>
-<li><a href="../csw.py?config=tests/suites/csw30/default.cfg&elementSetName=brief&outputSchema=urn:uuid:6a29d2a8-9651-47a6-9b14-f05d2b5644f0&request=GetRecords&service=CSW&typeNames=Record&version=3.0.0">9c0e2a4b-b4e6-41c0-b630-c8c99fc89ff3</a></li>
-<li><a href="../csw.py?config=tests/suites/csw30/default.cfg&id=urn:uuid:1ef30a8b-876d-4828-9246-c37ab4510bbd&outputSchema=http://www.example.org/ns/alpha&request=GetRecordById&service=CSW&version=3.0.0">9d7ffac8-9798-428d-8e27-3cd12497ee6b</a></li>
-<li><a href="../csw.py?config=tests/suites/csw30/default.cfg&id=urn:uuid:829babb0-b2f1-49e1-8cd5-7b489fe71a1e&outputFormat=application/atom%2Bxml&request=GetRecordById&service=CSW&version=3.0.0">a2f18643-e24e-4fa5-b780-6de4a2dbc814</a></li>
-<li><a href="../csw.py?config=tests/suites/csw30/default.cfg&mode=opensearch&service=CSW&version=3.0.0&request=GetRecords&elementsetname=full&typenames=csw:Record&resulttype=results&q=&bbox=514432">abc90c8c-5868-4405-a73e-64c849be3b2a</a></li>
-<li><a href="../csw.py?config=tests/suites/csw30/default.cfg&maxRecords=2&elementSetName=summary&request=GetRecords&service=CSW&typeNames=csw3:Record&startPosition=3&namespace=xmlns(csw3%3Dhttp://www.opengis.net/cat/csw/3.0)&version=3.0.0">ad0c0571-09ed-436a-9a4f-a5de744c88fe</a></li>
-<li><a href="../csw.py?config=tests/suites/csw30/default.cfg&service=CSW&version=3.0.0&request=GetRecords&elementsetname=full&typenames=csw:Record&resulttype=results&q=&bbox=-180">af502903-f4ee-47ee-b76e-af878d238bcc</a></li>
-<li><a href="../csw.py?config=tests/suites/csw30/default.cfg&mode=opensearch&service=CSW&version=3.0.0&request=GetRecords&elementsetname=full&typenames=csw:Record&resulttype=results&q=&bbox=-6.17">b2aafc3f-4f35-47bc-affd-08590972deae</a></li>
-<li><a href="../csw.py?config=tests/suites/csw30/default.cfg&mode=opensearch&service=CSW&version=3.0.0&request=GetRecords&elementsetname=full&typenames=csw:Record&resulttype=results&q=&bbox=&time=/&outputformat=application/atom%2Bxml&startposition=3&maxrecords=4&recordids=">b6069623-f7d8-4021-8582-98f0aea0f763</a></li>
-<li><a href="../csw.py?config=tests/suites/csw30/default.cfg&elementSetName=brief&bbox=472944">b9a07a54-75a8-45bd-b341-2823600211e3</a></li>
-<li><a href="../csw.py?config=tests/suites/csw30/default.cfg&acceptVersions=3.0.0&request=getCapabilities&service=CSW">baa4a7d0-0c01-42b6-adc3-0d03e9949fa3</a></li>
-<li><a href="../csw.py?config=tests/suites/csw30/default.cfg&elementSetName=summary&q=Fusc%C3%A9%20Land&request=GetRecords&service=CSW&typeNames=Record&version=3.0.0">bfbe6409-f64a-4c89-acb3-50f260a5c743</a></li>
-<li><a href="../csw.py?config=tests/suites/csw30/default.cfg&service=CSW&version=3.0.0&request=GetRecords&elementsetname=full&typenames=csw:Record&resulttype=results&q=&bbox=&time=/&outputformat=application/xml&outputschema=http://www.opengis.net/cat/csw/3.0&startposition=3&maxrecords=4&recordids=">bfe20134-d1da-42ef-9c0f-8e1307bbf92b</a></li>
-<li><a href="../csw.py?config=tests/suites/csw30/default.cfg&SERVICE=CSW&Request=GetCapabilities&acceptversions=3.0.0">c03d173a-3f42-4956-89c8-1fe02c3a0873</a></li>
-<li><a href="../csw.py?config=tests/suites/csw30/default.cfg&elementName=undefined&request=GetRecords&service=CSW&typeNames=Record&version=3.0.0">cb43d8c3-e14c-4a9f-9231-4384b7dd21f3</a></li>
-<li><a href="../csw.py?config=tests/suites/csw30/default.cfg&acceptVersions=3.0.0&sections=ServiceProvider&request=GetCapabilities&service=CSW">d03c6fd3-e821-4a26-b62f-d20a474e25af</a></li>
-<li><a href="../csw.py?config=tests/suites/csw30/default.cfg&service=CSW&version=3.0.0&request=GetRecords&elementsetname=full&typenames=csw:Record&resulttype=results&q=&bbox=&time=/&outputformat=application/xml&outputschema=http://www.opengis.net/cat/csw/3.0&startposition=1&maxrecords=&recordids=uid-bc5017e6-5cc8-4b03-aee7-d88f88caba0a">d4ccbf96-a529-480e-a53d-5b88dc1dea7f</a></li>
-<li><a href="../csw.py?config=tests/suites/csw30/default.cfg&service=CSW&version=3.0.0&request=GetRecords&elementsetname=full&typenames=csw:Record&resulttype=results&q=lpppclq&bbox=&time=/&outputformat=application/xml&outputschema=http://www.opengis.net/cat/csw/3.0&startposition=1&maxrecords=&recordids=">d94c801a-1207-4897-b84a-53f3a192515b</a></li>
-<li><a href="../csw.py?config=tests/suites/csw30/default.cfg&id=urn:uuid:94bc9c83-97f6-4b40-9eb8-a8e8787a5c63&elementSetName=full&request=GetRecordById&service=CSW&version=3.0.0">da859e34-91fc-495a-8c09-285a40c0900b</a></li>
-<li><a href="../csw.py?config=tests/suites/csw30/default.cfg&mode=opensearch&service=CSW&version=3.0.0&request=GetRecords&elementsetname=full&typenames=csw:Record&resulttype=results&q=ipsum&bbox=&time=/&outputformat=application/atom%2Bxml&startposition=1&maxrecords=&recordids=">dc246fb8-5af5-4fda-82bb-c18b3ecd439c</a></li>
-<li><a href="../csw.py?config=tests/suites/csw30/default.cfg&mode=opensearch&service=CSW&version=3.0.0&request=GetRecords&elementsetname=full&typenames=csw:Record&resulttype=results&q=&bbox=&time=/&outputformat=application/atom%2Bxml&startposition=1&maxrecords=&recordids=urn%3Auuid%3A94bc9c83-97f6-4b40-9eb8-a8e8787a5c63">de016645-6d5c-4855-943c-2db07ae9f49a</a></li>
-<li><a href="../csw.py?config=tests/suites/csw30/default.cfg&elementSetName=summary&request=GetRecords&service=CSW&typeNames=Record&version=3.0.0">dff3ec6b-bb2d-4887-bd17-8fcf15def042</a></li>
-<li><a href="../csw.py?config=tests/suites/csw30/default.cfg&id=urn:uuid:1ef30a8b-876d-4828-9246-c37ab4510bbd&elementSetName=brief&request=GetRecordById&service=CSW&version=3.0.0">e38e6bfb-8ac4-4ae4-8b87-0aafbc8d3c6b</a></li>
-<li><a href="../csw.py?config=tests/suites/csw30/default.cfg">e67ca935-d65d-4d8c-8302-1405333dded0</a></li>
-<li><a href="../csw.py?config=tests/suites/csw30/default.cfg&elementName=ns1:subject&elementSetName=brief&request=GetRecords&service=CSW&typeNames=Record&namespace=xmlns(ns1%3Dhttp://purl.org/dc/elements/1.1/)&version=3.0.0">e7704509-3441-458f-8ef0-e333c6b6043f</a></li>
-<li><a href="../csw.py?config=tests/suites/csw30/default.cfg&elementSetName=summary&maxRecords=0&q=titles&request=GetRecords&service=CSW&typeNames=Record&version=3.0.0">f1223a49-6d08-44ff-97fe-4c32cbbfad82</a></li>
-<li><a href="../csw.py?config=tests/suites/csw30/default.cfg&elementSetName=full&outputFormat=text/example&request=GetRecords&service=CSW&typeNames=Record&version=3.0.0">f89dd4e1-3a81-4433-afd2-a3fa1bdb1e18</a></li>
-<li><a href="../csw.py?config=tests/suites/default/default.cfg&service=CSW&version=2.0.2&request=GetCapabilities">GetCapabilities</a></li>
-<li><a href="../csw.py?config=tests/suites/default/default.cfg&service=CSW&version=2.0.2&request=GetCapabilitiese">GetCapabilities-invalid-request</a></li>
-<li><a href="../csw.py?config=tests/suites/default/default.cfg&service=CSW&version=2.0.2&request=GetRecords&typenames=csw:Record&elementsetname=full">GetRecords-all</a></li>
-<li><a href="../csw.py?config=tests/suites/default/default.cfg&service=CSW&version=2.0.2&request=GetRecords&typenames=csw:Record&elementsetname=full&resulttype=results&sortby=dc:title:A">GetRecords-sortby-asc</a></li>
-<li><a href="../csw.py?config=tests/suites/default/default.cfg&service=CSW&version=2.0.2&request=GetRecords&typenames=csw:Record&elementsetname=full&resulttype=results&sortby=dc:title:D">GetRecords-sortby-desc</a></li>
-<li><a href="../csw.py?config=tests/suites/default/default.cfg&service=CSW&version=2.0.2&request=GetRecords&typenames=csw:Record&elementsetname=full&resulttype=results&sortby=dc:titlei:A">GetRecords-sortby-invalid-propertyname</a></li>
-<li><a href="../csw.py?config=tests/suites/default/default.cfg&service=CSW&version=2.0.2&request=GetRecords&typenames=csw:Record&elementsetname=full&resulttype=results&sortby=dc:title:FOO">GetRecords-sortby-invalid-order</a></li>
-<li><a href="../csw.py?config=tests/suites/default/default.cfg&service=CSW&version=2.0.2&request=GetRecords&typenames=csw:Record&elementsetname=full&resulttype=results&constraintlanguage=FILTER&constraint=%3Cogc%3AFilter%20xmlns%3Aogc%3D%22http%3A%2F%2Fwww.opengis.net%2Fogc%22%3E%3Cogc%3APropertyIsEqualTo%3E%3Cogc%3APropertyName%3Edc%3Atitle%3C%2Fogc%3APropertyName%3E%3Cogc%3ALiteral%3ELorem%20ipsum%3C%2Fogc%3ALiteral%3E%3C%2Fogc%3APropertyIsEqualTo%3E%3C% [...]
-<li><a href="../csw.py?config=tests/suites/default/default.cfg&service=CSW&version=2.0.2&request=GetRecords&typenames=csw:Record&elementsetname=full&resulttype=results&constraintlanguage=CQL_TEXT&constraint=dc%3Atitle%20like%20%27%25lor%25%27">GetRecords-filter-cql-title</a></li>
-<li><a href="../csw.py?config=tests/suites/default/default.cfg&service=CSW&version=2.0.2&request=GetRecords&typenames=csw:Record&elementsetname=full&resulttype=results&constraintlanguage=CQL_TEXT&constraint=dc%3Atitle%20like%20%27%25Lorem%20ipsum%25%27">GetRecords-filter-cql-title-with-spaces</a></li>
-<li><a href="../csw.py?config=tests/suites/default/default.cfg&service=CSW&version=2.0.2&request=GetRecords&typenames=csw:Record&elementsetname=full&resulttype=results&constraintlanguage=CQL_TEXT&constraint=dc%3Atitle%20like%20%27%25lor%25%27%20or%20dct%3Aabstract%20like%20%27%25pharetra%25%27">GetRecords-filter-cql-title-or-abstract</a></li>
-<li><a href="../csw.py?config=tests/suites/default/default.cfg&service=CSW&version=2.0.2&request=GetRecords&typenames=csw:Record&elementsetname=full&resulttype=results&constraintlanguage=CQL_TEXT&constraint=dc%3Atitle%20like%20%27%25dolor%20sit%25%27%20or%20dct%3Aabstract%20like%20%27%25pharetra%25%27">GetRecords-filter-cql-title-with-spaces-or-abstract</a></li>
-<li><a href="../csw.py?config=tests/suites/default/default.cfg&service=CSW&version=2.0.2&request=GetRecords&typenames=csw:Record&elementsetname=full&resulttype=results&constraintlanguage=CQL_TEXT&constraint=dc%3Atitle%20like%20%27%25lor%25%27%20or%20dct%3Aabstract%20like%20%27%25pharetra%20in%25%27">GetRecords-filter-cql-title-or-abstract-with-spaces</a></li>
-<li><a href="../csw.py?config=tests/suites/default/default.cfg&service=CSW&version=2.0.2&request=GetRecords&typenames=csw:Record&elementsetname=full&resulttype=results&constraintlanguage=CQL_TEXT&constraint=dc%3Atitle%20like%20%27%25dolor%20sit%25%27%20or%20dct%3Aabstract%20like%20%27%25pharetra%20in%25%27">GetRecords-filter-cql-title-with-spaces-or-abstract-with-spaces</a></li>
-<li><a href="../csw.py?config=tests/suites/default/default.cfg&service=CSW&version=2.0.2&request=GetRecords&typenames=csw:Record&elementsetname=full&maxrecords=">GetRecords-empty-maxrecords</a></li>
-<li><a href="../csw.py?config=tests/suites/default/default.cfg&service=CSW&version=2.0.2&request=GetRepositoryItem&id=urn:uuid:94bc9c83-97f6-4b40-9eb8-a8e8787a5c63">GetRepositoryItem</a></li>
-<li><a href="../csw.py?config=tests/suites/default/default.cfg&service=CSW&version=2.0.2&request=GetRepositoryItem&id=NOTFOUND">Exception-GetRepositoryItem-notfound</a></li>
-<li><a href="../csw.py?config=tests/suites/default/default.cfg&service=CSW%00&version=2.0.2&request=GetRepositoryItem&id=123">Exception-GetRepositoryItem-service-invalid1</a></li>
-<li><a href="../csw.py?config=tests/suites/default/default.cfg&service=CSW%00'&version=2.0.2&request=GetRepositoryItem&id=123">Exception-GetRepositoryItem-service-invalid2</a></li>
-<li><a href="../csw.py?config=tests/suites/default/default.cfg&service=CSW&version=2.0.2'&request=GetRepositoryItem&id=123">Exception-GetRepositoryItem-version-invalid</a></li>
-<li><a href="../csw.py?config=tests/suites/manager/default.cfg&service=CSW&version=2.0.2&request=Harvest">Exception-Harvest-missing-resourcetype</a></li>
-<li><a href="../csw.py?config=tests/suites/manager/default.cfg&service=CSW&version=2.0.2&request=Harvest&resourcetype=http://www.opengis.net/wms">Exception-Harvest-missing-source</a></li>
-<li><a href="../csw.py?config=tests/suites/manager/default.cfg&service=CSW&version=2.0.2&request=Harvest&resourcetype=http://www.opengis.net/wms1234&source=http://demo.pycsw.org/cite/csw">Exception-Harvest-invalid-resourcetype</a></li>
-<li><a href="../csw.py?config=tests/suites/manager/default.cfg&service=CSW&version=2.0.2&request=Harvest&resourcetype=urn:geoss:waf&source=http://demo.pycsw.org">Exception-Harvest-waf-no-records-found</a></li>
-<li><a href="../csw.py?config=tests/suites/manager/default.cfg&service=CSW&version=2.0.2&request=Harvest&resourcetype=urn:geoss:waf&source=badvalue">Exception-Harvest-waf-bad-value</a></li>
-<li><a href="../csw.py?config=tests/suites/oaipmh/default.cfg&mode=oaipmh">empty</a></li>
-<li><a href="../csw.py?config=tests/suites/oaipmh/default.cfg&mode=oaipmh&">empty_with_amp</a></li>
-<li><a href="../csw.py?config=tests/suites/oaipmh/default.cfg&mode=oaipmh&verb=foo">bad_verb</a></li>
-<li><a href="../csw.py?config=tests/suites/oaipmh/default.cfg&mode=oaipmh&verb=foo&foo=bar">illegal_verb</a></li>
-<li><a href="../csw.py?config=tests/suites/oaipmh/default.cfg&mode=oaipmh&verb=Identify">Identify</a></li>
-<li><a href="../csw.py?config=tests/suites/oaipmh/default.cfg&mode=oaipmh&verb=ListSets">ListSets</a></li>
-<li><a href="../csw.py?config=tests/suites/oaipmh/default.cfg&mode=oaipmh&verb=ListMetadataFormats">ListMetadataFormats</a></li>
-<li><a href="../csw.py?config=tests/suites/oaipmh/default.cfg&mode=oaipmh&verb=GetRecord&identifier=urn:uuid:19887a8a-f6b0-4a63-ae56-7fba0e17801f&metadataPrefix=csw-record">GetRecord_dc</a></li>
-<li><a href="../csw.py?config=tests/suites/oaipmh/default.cfg&mode=oaipmh&verb=GetRecord&identifier=urn:uuid:19887a8a-f6b0-4a63-ae56-7fba0e17801f&metadataPrefix=csw-recordd">GetRecord_bad_metadata_prefix</a></li>
-<li><a href="../csw.py?config=tests/suites/oaipmh/default.cfg&mode=oaipmh&verb=GetRecord&identifier=urn:uuid:19887a8a-f6b0-4a63-ae56-7fba0e17801f&metadataPrefix=oai_dc">GetRecord_oai_dc</a></li>
-<li><a href="../csw.py?config=tests/suites/oaipmh/default.cfg&mode=oaipmh&verb=GetRecord&identifier=urn:uuid:19887a8a-f6b0-4a63-ae56-7fba0e17801f&metadataPrefix=iso19139">GetRecord_iso</a></li>
-<li><a href="../csw.py?config=tests/suites/oaipmh/default.cfg&mode=oaipmh&verb=ListIdentifiers">ListIdentifiers_missing_metadata_prefix</a></li>
-<li><a href="../csw.py?config=tests/suites/oaipmh/default.cfg&mode=oaipmh&verb=ListIdentifiers&metadataPrefix=csw-record">ListIdentifiers_dc</a></li>
-<li><a href="../csw.py?config=tests/suites/oaipmh/default.cfg&mode=oaipmh&verb=ListIdentifiers&metadataPrefix=iso19139">ListIdentifiers_iso</a></li>
-<li><a href="../csw.py?config=tests/suites/oaipmh/default.cfg&mode=oaipmh&verb=ListIdentifiers&metadataPrefix=oai_dc">ListIdentifiers_oai_dc</a></li>
-<li><a href="../csw.py?config=tests/suites/oaipmh/default.cfg&mode=oaipmh&verb=ListIdentifiers&metadataPrefix=foo">ListIdentifiers_bad_metadata_prefix</a></li>
-<li><a href="../csw.py?config=tests/suites/oaipmh/default.cfg&mode=oaipmh&verb=ListRecords&metadataPrefix=csw-record">ListRecords_dc</a></li>
-<li><a href="../csw.py?config=tests/suites/oaipmh/default.cfg&mode=oaipmh&verb=ListRecords&metadataPrefix=csw-recording">ListRecords_dc_bad_metadata_prefix</a></li>
-<li><a href="../csw.py?config=tests/suites/oaipmh/default.cfg&mode=oaipmh&verb=ListRecords&metadataPrefix=oai_dc">ListRecords_oai_dc</a></li>
-<li><a href="../csw.py?config=tests/suites/oaipmh/default.cfg&mode=oaipmh&verb=ListRecords&metadataPrefix=iso19139">ListRecords_iso19139</a></li>
-<li><a href="../csw.py?config=tests/suites/sru/default.cfg&mode=sru">explain</a></li>
-<li><a href="../csw.py?config=tests/suites/sru/default.cfg&mode=sru&version=1.1&operation=searchRetrieve&query=lor">search</a></li>
-<li><a href="../csw.py?config=tests/suites/sru/default.cfg&mode=sru&operation=searchRetrieve&query=lor&maximumRecords=2">search_maxrecords</a></li>
-<li><a href="../csw.py?config=tests/suites/sru/default.cfg&mode=sru&operation=searchRetrieve&query=lor&maximumRecords=2&startRecord=1">search_startrecord_maxrecords</a></li>
-<li><a href="../csw.py?config=tests/suites/sru/default.cfg&mode=sru&operation=searchRetrieve&query=dc:title%20like%20'%lor%'&maximumRecords=5">search_cql</a></li>
+<li><a href='../csw.py?PYCSW_SERVER?config=tests/suites/manager/default.cfg&service=CSW&version=2.0.2&request=Harvest'>Exception-Harvest-missing-resourcetype</a></li>
+<li><a href='../csw.py?PYCSW_SERVER?config=tests/suites/manager/default.cfg&service=CSW&version=2.0.2&request=Harvest&resourcetype=http://www.opengis.net/wms'>Exception-Harvest-missing-source</a></li>
+<li><a href='../csw.py?PYCSW_SERVER?config=tests/suites/manager/default.cfg&service=CSW&version=2.0.2&request=Harvest&resourcetype=http://www.opengis.net/wms1234&source=http://demo.pycsw.org/cite/csw'>Exception-Harvest-invalid-resourcetype</a></li>
+<li><a href='../csw.py?PYCSW_SERVER?config=tests/suites/manager/default.cfg&service=CSW&version=2.0.2&request=Harvest&resourcetype=urn:geoss:waf&source=http://demo.pycsw.org'>Exception-Harvest-waf-no-records-found</a></li>
+<li><a href='../csw.py?PYCSW_SERVER?config=tests/suites/manager/default.cfg&service=CSW&version=2.0.2&request=Harvest&resourcetype=urn:geoss:waf&source=badvalue'>Exception-Harvest-waf-bad-value</a></li>
+<li><a href='../csw.py?mode=oaipmh'>empty</a></li>
+<li><a href='../csw.py?mode=oaipmh&'>empty_with_amp</a></li>
+<li><a href='../csw.py?mode=oaipmh&verb=foo'>bad_verb</a></li>
+<li><a href='../csw.py?mode=oaipmh&verb=foo&foo=bar'>illegal_verb</a></li>
+<li><a href='../csw.py?mode=oaipmh&verb=Identify'>Identify</a></li>
+<li><a href='../csw.py?mode=oaipmh&verb=ListSets'>ListSets</a></li>
+<li><a href='../csw.py?mode=oaipmh&verb=ListMetadataFormats'>ListMetadataFormats</a></li>
+<li><a href='../csw.py?mode=oaipmh&verb=GetRecord&identifier=urn:uuid:19887a8a-f6b0-4a63-ae56-7fba0e17801f&metadataPrefix=csw-record'>GetRecord_dc</a></li>
+<li><a href='../csw.py?mode=oaipmh&verb=GetRecord&identifier=urn:uuid:19887a8a-f6b0-4a63-ae56-7fba0e17801f&metadataPrefix=csw-recordd'>GetRecord_bad_metadata_prefix</a></li>
+<li><a href='../csw.py?mode=oaipmh&verb=GetRecord&identifier=urn:uuid:19887a8a-f6b0-4a63-ae56-7fba0e17801f&metadataPrefix=oai_dc'>GetRecord_oai_dc</a></li>
+<li><a href='../csw.py?mode=oaipmh&verb=GetRecord&identifier=urn:uuid:19887a8a-f6b0-4a63-ae56-7fba0e17801f&metadataPrefix=iso19139'>GetRecord_iso</a></li>
+<li><a href='../csw.py?mode=oaipmh&verb=ListIdentifiers'>ListIdentifiers_missing_metadata_prefix</a></li>
+<li><a href='../csw.py?mode=oaipmh&verb=ListIdentifiers&metadataPrefix=csw-record'>ListIdentifiers_dc</a></li>
+<li><a href='../csw.py?mode=oaipmh&verb=ListIdentifiers&metadataPrefix=iso19139'>ListIdentifiers_iso</a></li>
+<li><a href='../csw.py?mode=oaipmh&verb=ListIdentifiers&metadataPrefix=oai_dc'>ListIdentifiers_oai_dc</a></li>
+<li><a href='../csw.py?mode=oaipmh&verb=ListIdentifiers&metadataPrefix=foo'>ListIdentifiers_bad_metadata_prefix</a></li>
+<li><a href='../csw.py?mode=oaipmh&verb=ListRecords&metadataPrefix=csw-record'>ListRecords_dc</a></li>
+<li><a href='../csw.py?mode=oaipmh&verb=ListRecords&metadataPrefix=csw-recording'>ListRecords_dc_bad_metadata_prefix</a></li>
+<li><a href='../csw.py?mode=oaipmh&verb=ListRecords&metadataPrefix=oai_dc'>ListRecords_oai_dc</a></li>
+<li><a href='../csw.py?mode=oaipmh&verb=ListRecords&metadataPrefix=iso19139'>ListRecords_iso19139</a></li>
+<li><a href='../csw.py?PYCSW_SERVER?config=tests/suites/csw30/default.cfg'>GetCapabilities-base-url</a></li>
+<li><a href='../csw.py?service=CSW&request=GetCapabilities'>GetCapabilities-no-version</a></li>
+<li><a href='../csw.py?service=CSW&version=3.0.0&request=GetCapabilities'>GetCapabilities</a></li>
+<li><a href='../csw.py?service=CSW&version=3.0.0&request=GetCapabilities-foo'>Exception-invalid-request</a></li>
+<li><a href='../csw.py?service=CSW&version=3.0.0&request=GetDomain'>Exception-GetDomain</a></li>
+<li><a href='../csw.py?service=CSW&version=3.0.0&request=GetDomain&parametername=GetRecords.ElementSetName'>GetDomain-parameter</a></li>
+<li><a href='../csw.py?service=CSW&version=3.0.0&request=GetDomain&valuereference=dc:title'>GetDomain-value-reference</a></li>
+<li><a href='../csw.py?service=CSW&version=3.0.0&request=GetDomain&valuereference=dc:title2'>Exception-GetDomain-value-reference</a></li>
+<li><a href='../csw.py?service=CSW&version=3.0.0&request=GetRecordById&id=urn:uuid:829babb0-b2f1-49e1-8cd5-7b489fe71a1e'>Exception-GetRecordById-dc.xml</a></li>
+<li><a href='../csw.py?service=CSW&version=3.0.0&request=GetRecordById&id=does_not_exist2'>Exception-GetRecordById-404</a></li>
+<li><a href='../csw.py?mode=opensearch&service=CSW&version=3.0.0&request=GetCapabilities'>OpenSearch-description</a></li>
+<li><a href='../csw.py?service=CSW&version=3.0.0&request=GetRepositoryItem&id=urn:uuid:19887a8a-f6b0-4a63-ae56-7fba0e17801f'>GetRepositoryItem</a></li>
+<li><a href='../csw.py?service=CSW&version=3.0.0&request=GetRepositoryItem&id=NOTFOUND'>Exception-GetRepositoryItem-notfound</a></li>
+<li><a href='../csw.py?mode=opensearch&service=CSW&version=3.0.0&request=GetCapabilities'>002258f0-627f-457f-b2ad-025777c77ac8</a></li>
+<li><a href='../csw.py?mode=opensearch&service=CSW&version=3.0.0&request=GetRecords&elementsetname=full&typenames=csw:Record&resulttype=results&q=Fusc%C3%A9%20Land&bbox=&time=/&outputformat=application/atom%2Bxml&startposition=1&maxrecords=&recordids='>045c600d-973d-41eb-9f60-eba1b717b720</a></li>
+<li><a href='../csw.py?elementSetName=summary&outputFormat=application/atom%2Bxml&request=GetRecords&service=CSW&typeNames=Record&version=3.0.0'>0bbcf862-5211-4351-9988-63f8bec49c98</a></li>
+<li><a href='../csw.py?PYCSW_SERVER?config=tests/suites/csw30/default.cfg'>0bdf8457-971e-4ed1-be4a-5feca4dcd8fa</a></li>
+<li><a href='../csw.py?elementName=tns:title&request=GetRecords&service=CSW&typeNames=Record&namespace=xmlns(tns%3Dhttp://purl.org/dc/elements/1.1/)&version=3.0.0'>0d8bbdec-0846-42ca-8dc8-b7f4cba41d67</a></li>
+<li><a href='../csw.py?mode=opensearch&service=CSW&version=3.0.0&request=GetRecords&elementsetname=full&typenames=csw:Record&resulttype=results&q=lpppclq&bbox=&time=/&outputformat=application/atom%2Bxml&startposition=1&maxrecords=&recordids='>0e1dca37-477a-4060-99fe-7799b52d656c</a></li>
+<li><a href='../csw.py?elementSetName=full&maxRecords=20&request=GetRecords&service=CSW&typeNames=Record&version=3.0.0'>13c87956-51a4-4780-a8e9-6e0b5c0bb473</a></li>
+<li><a href='../csw.py?acceptFormats=model/x3d%2Bxml&acceptVersions=3.0.0&request=GetCapabilities&service=CSW'>151d982f-ebd3-4cb2-b507-a667713a1e92</a></li>
+<li><a href='../csw.py?acceptVersions=3.0.0&request=GetCapabilities'>1869e495-1a61-4713-8285-76d1336ee1a6</a></li>
+<li><a href='../csw.py?request=GetRecordById&service=CSW&version=3.0.0'>1bcb42a9-538c-4f0a-9d4c-d6f10b720aa6</a></li>
+<li><a href='../csw.py?PYCSW_SERVER?config=tests/suites/csw30/default.cfg'>22f44168-2ccf-4801-ad96-204212566d56</a></li>
+<li><a href='../csw.py?acceptVersions=3.0.0&sections=All&request=GetCapabilities&service=CSW'>2499a9c9-8d33-449c-bc92-d494adfcc84d</a></li>
+<li><a href='../csw.py?acceptFormats=application/xml&acceptVersions=3.0.0&request=GetCapabilities&service=CSW'>27f4f39c-d92a-4e3c-b961-c6aa8c24e513</a></li>
+<li><a href='../csw.py?id=urn:uuid:a06af396-3105-442d-8b40-22b57a90d2f2&request=GetRecordById&service=CSW&version=3.0.0'>28e569df-8596-4128-8d9a-29ad03138915</a></li>
+<li><a href='../csw.py?PYCSW_SERVER?config=tests/suites/csw30/default.cfg'>2b06a5c8-0df2-4af1-8d2e-a425de11c845</a></li>
+<li><a href='../csw.py?maxRecords=2&elementSetName=summary&outputFormat=application/atom%2Bxml&request=GetRecords&service=CSW&typeNames=csw3:Record&startPosition=3&namespace=xmlns(csw3%3Dhttp://www.opengis.net/cat/csw/3.0)&version=3.0.0'>2ba1418a-444d-4cce-9cfe-4c94efcf8b55</a></li>
+<li><a href='../csw.py?service=CSW&version=3.0.0&request=GetRecords&elementsetname=full&typenames=csw:Record&resulttype=results&q=ipsum&bbox=&time=/&outputformat=application/xml&outputschema=http://www.opengis.net/cat/csw/3.0&startposition=1&maxrecords=&recordids='>397fe17a-d5b4-4f96-8cc4-4ce467ed4d0a</a></li>
+<li><a href='../csw.py?elementSetName=brief&request=GetRecords&service=CSW&typeNames=tns:Record&namespace=xmlns(tns%3Dhttp://www.opengis.net/cat/csw/3.0)&version=3.0.0'>3dcd1b15-73d2-4b7d-a3e3-ff15bf14aae4</a></li>
+<li><a href='../csw.py?elementSetName=summary&recordIds=urn:uuid:19887a8a-f6b0-4a63-ae56-7fba0e17801f,urn:uuid:e9330592-0932-474b-be34-c3a3bb67c7db&request=GetRecords&service=CSW&typeNames=Record&version=3.0.0'>405e1ff1-5c75-4846-a28b-cfaff2a6921a</a></li>
+<li><a href='../csw.py?PYCSW_SERVER?config=tests/suites/csw30/default.cfg'>43cd6471-6ac7-45bd-8ff9-148cb2de9a52</a></li>
+<li><a href='../csw.py?acceptVersions=3.0.0&sections=ServiceIdentification&request=GetCapabilities&service=CSW'>4566d2ec-1283-4a02-baed-a74fc5b47e37</a></li>
+<li><a href='../csw.py?acceptVersions=3.0.0&sections=Filter_Capabilities&request=GetCapabilities&service=CSW'>461bd4c5-6623-490d-9036-d91a2201e87b</a></li>
+<li><a href='../csw.py?service=CSW&version=3.0.0&request=GetRecords&elementsetname=full&typenames=csw:Record&resulttype=results&q=&bbox=514432,5429689,529130,5451619&time=/&outputformat=application/xml&outputschema=http://www.opengis.net/cat/csw/3.0&startposition=1&maxrecords=&recordids='>5496894a-3877-4f62-a20b-5d7126f94925</a></li>
+<li><a href='../csw.py?service=CSW&version=3.0.0&request=GetRecords&elementsetname=full&typenames=csw:Record&resulttype=results&q=&bbox=-6.17,44.79,17.92,68.41&time=/&outputformat=application/xml&outputschema=http://www.opengis.net/cat/csw/3.0&startposition=1&maxrecords=&recordids='>5a015f6a-bf14-4977-b1e3-6577eb0223c8</a></li>
+<li><a href='../csw.py?id=urn:uuid:88247b56-4cbc-4df9-9860-db3f8042e357&outputFormat=model/vnd.collada%2Bxml&request=GetRecordById&service=CSW&version=3.0.0'>5c3a2390-1fb9-43f0-b96c-f48c7a69c990</a></li>
+<li><a href='../csw.py?acceptVersions=3.0.0&sections=OperationsMetadata&request=GetCapabilities&service=CSW'>5e9e67dc-18d6-4645-8111-c6263c88a61f</a></li>
+<li><a href='../csw.py?elementSetName=full&q=amet&request=GetRecords&service=CSW&typeNames=Record&version=3.0.0'>604d9379-741c-42e5-b4cf-92e56c87fa64</a></li>
+<li><a href='../csw.py?request=GetRecords&service=CSW&typeNames=UnknownType&version=3.0.0'>60e6af95-d5fc-465a-82e2-fd2e6d85e4af</a></li>
+<li><a href='../csw.py?mode=opensearch&service=CSW&version=3.0.0&request=GetRecords&elementsetname=full&typenames=csw:Record&resulttype=results&q=&bbox=&time=/&outputformat=application/atom%2Bxml&startposition=1&maxrecords=&recordids=uid-bc5017e6-5cc8-4b03-aee7-d88f88caba0a'>62ad94c2-b558-4265-a427-23d6677975d6</a></li>
+<li><a href='../csw.py?elementSetName=undefined-view&request=GetRecords&service=CSW&typeNames=Record&version=3.0.0'>6a5e247b-0961-4b8a-a0d6-35a491d9cfe7</a></li>
+<li><a href='../csw.py?PYCSW_SERVER?config=tests/suites/csw30/default.cfg'>6a9d0558-9d87-495b-b999-b49a3ef1cf99</a></li>
+<li><a href='../csw.py?service=CSW&version=3.0.0&request=GetRecords&elementsetname=full&typenames=csw:Record&resulttype=results&q=Fusc%C3%A9%20Land&bbox=&time=/&outputformat=application/xml&outputschema=http://www.opengis.net/cat/csw/3.0&startposition=1&maxrecords=&recordids='>6bd790c9-6019-4652-9c91-330a894d6700</a></li>
+<li><a href='../csw.py?acceptVersions=3.0.0&request=GetCapabilities&service=CSW'>6e9cba43-5e27-415d-adbd-a92851c2c173</a></li>
+<li><a href='../csw.py?id=urn:uuid:66ae76b7-54ba-489b-a582-0f0633d96493&request=GetRecordById&service=CSW&version=3.0.0'>7630d230-e142-4a09-accf-f091000b90cd</a></li>
+<li><a href='../csw.py?acceptFormats=text/xml&acceptVersions=3.0.0&request=GetCapabilities&service=CSW'>7e82446a-b5dc-43fe-9a73-4cc1f2f2f0bf</a></li>
+<li><a href='../csw.py?PYCSW_SERVER?config=tests/suites/csw30/default.cfg'>8025978e-1a35-4d70-80c2-e8329e0c7864</a></li>
+<li><a href='../csw.py?elementSetName=brief&bbox=44.79,-6.17,68.41,17.92,urn:ogc:def:crs:EPSG::4326&request=GetRecords&service=CSW&typeNames=Record&version=3.0.0'>8184ae4f-536d-4978-8b28-ad703be96967</a></li>
+<li><a href='../csw.py?maxRecords=15&elementSetName=summary&q=Mauris&bbox=-6.17,44.79,17.92,68.41&request=GetRecords&service=CSW&typeNames=Record&version=3.0.0'>88f63a89-664f-4315-b4f8-04a0b33803a7</a></li>
+<li><a href='../csw.py?id=urn:example:1461546298217&request=GetRecordById&service=CSW&version=3.0.0'>8987f8f0-4d93-4481-968c-a2ccbd6b8be2</a></li>
+<li><a href='../csw.py?mode=opensearch&service=CSW&version=3.0.0&request=GetRecords&elementsetname=full&typenames=csw:Record&resulttype=results&q=&bbox=-180,-90,180,90&time=/&outputformat=application/atom%2Bxml&startposition=1&maxrecords=&recordids='>8e5fa0f6-3f29-4d1f-abe2-d9866f3def98</a></li>
+<li><a href='../csw.py?acceptVersions=9999.12.31&request=GetCapabilities&service=CSW'>9000ec29-5649-474e-b2d6-55c00f8a52c0</a></li>
+<li><a href='../csw.py?elementSetName=summary&bbox=-6.17,44.79,17.92,68.41&request=GetRecords&service=CSW&typeNames=Record&version=3.0.0'>91914d35-7bbf-45e6-9b37-5ef484869a4e</a></li>
+<li><a href='../csw.py?elementSetName=full&q=atkovxqmf&request=GetRecords&service=CSW&typeNames=Record&version=3.0.0'>92d4844d-57d5-4cf3-8f47-ba50e369dc04</a></li>
+<li><a href='../csw.py?elementSetName=brief&outputSchema=urn:uuid:6a29d2a8-9651-47a6-9b14-f05d2b5644f0&request=GetRecords&service=CSW&typeNames=Record&version=3.0.0'>9c0e2a4b-b4e6-41c0-b630-c8c99fc89ff3</a></li>
+<li><a href='../csw.py?id=urn:uuid:1ef30a8b-876d-4828-9246-c37ab4510bbd&outputSchema=http://www.example.org/ns/alpha&request=GetRecordById&service=CSW&version=3.0.0'>9d7ffac8-9798-428d-8e27-3cd12497ee6b</a></li>
+<li><a href='../csw.py?id=urn:uuid:829babb0-b2f1-49e1-8cd5-7b489fe71a1e&outputFormat=application/atom%2Bxml&request=GetRecordById&service=CSW&version=3.0.0'>a2f18643-e24e-4fa5-b780-6de4a2dbc814</a></li>
+<li><a href='../csw.py?mode=opensearch&service=CSW&version=3.0.0&request=GetRecords&elementsetname=full&typenames=csw:Record&resulttype=results&q=&bbox=514432,5429689,529130,5451619&time=/&outputformat=application/atom%2Bxml&startposition=1&maxrecords=&recordids='>abc90c8c-5868-4405-a73e-64c849be3b2a</a></li>
+<li><a href='../csw.py?maxRecords=2&elementSetName=summary&request=GetRecords&service=CSW&typeNames=csw3:Record&startPosition=3&namespace=xmlns(csw3%3Dhttp://www.opengis.net/cat/csw/3.0)&version=3.0.0'>ad0c0571-09ed-436a-9a4f-a5de744c88fe</a></li>
+<li><a href='../csw.py?service=CSW&version=3.0.0&request=GetRecords&elementsetname=full&typenames=csw:Record&resulttype=results&q=&bbox=-180,-90,180,90&time=/&outputformat=application/xml&outputschema=http://www.opengis.net/cat/csw/3.0&startposition=1&maxrecords=&recordids='>af502903-f4ee-47ee-b76e-af878d238bcc</a></li>
+<li><a href='../csw.py?mode=opensearch&service=CSW&version=3.0.0&request=GetRecords&elementsetname=full&typenames=csw:Record&resulttype=results&q=&bbox=-6.17,44.79,17.92,68.41&time=/&outputformat=application/atom%2Bxml&startposition=1&maxrecords=&recordids='>b2aafc3f-4f35-47bc-affd-08590972deae</a></li>
+<li><a href='../csw.py?mode=opensearch&service=CSW&version=3.0.0&request=GetRecords&elementsetname=full&typenames=csw:Record&resulttype=results&q=&bbox=&time=/&outputformat=application/atom%2Bxml&startposition=3&maxrecords=4&recordids='>b6069623-f7d8-4021-8582-98f0aea0f763</a></li>
+<li><a href='../csw.py?elementSetName=brief&bbox=472944,5363287,492722,5455253,urn:ogc:def:crs:EPSG::0000&request=GetRecords&service=CSW&typeNames=Record&version=3.0.0'>b9a07a54-75a8-45bd-b341-2823600211e3</a></li>
+<li><a href='../csw.py?acceptVersions=3.0.0&request=getCapabilities&service=CSW'>baa4a7d0-0c01-42b6-adc3-0d03e9949fa3</a></li>
+<li><a href='../csw.py?elementSetName=summary&q=Fusc%C3%A9%20Land&request=GetRecords&service=CSW&typeNames=Record&version=3.0.0'>bfbe6409-f64a-4c89-acb3-50f260a5c743</a></li>
+<li><a href='../csw.py?service=CSW&version=3.0.0&request=GetRecords&elementsetname=full&typenames=csw:Record&resulttype=results&q=&bbox=&time=/&outputformat=application/xml&outputschema=http://www.opengis.net/cat/csw/3.0&startposition=3&maxrecords=4&recordids='>bfe20134-d1da-42ef-9c0f-8e1307bbf92b</a></li>
+<li><a href='../csw.py?SERVICE=CSW&Request=GetCapabilities&acceptversions=3.0.0'>c03d173a-3f42-4956-89c8-1fe02c3a0873</a></li>
+<li><a href='../csw.py?elementName=undefined&request=GetRecords&service=CSW&typeNames=Record&version=3.0.0'>cb43d8c3-e14c-4a9f-9231-4384b7dd21f3</a></li>
+<li><a href='../csw.py?acceptVersions=3.0.0&sections=ServiceProvider&request=GetCapabilities&service=CSW'>d03c6fd3-e821-4a26-b62f-d20a474e25af</a></li>
+<li><a href='../csw.py?service=CSW&version=3.0.0&request=GetRecords&elementsetname=full&typenames=csw:Record&resulttype=results&q=&bbox=&time=/&outputformat=application/xml&outputschema=http://www.opengis.net/cat/csw/3.0&startposition=1&maxrecords=&recordids=uid-bc5017e6-5cc8-4b03-aee7-d88f88caba0a'>d4ccbf96-a529-480e-a53d-5b88dc1dea7f</a></li>
+<li><a href='../csw.py?service=CSW&version=3.0.0&request=GetRecords&elementsetname=full&typenames=csw:Record&resulttype=results&q=lpppclq&bbox=&time=/&outputformat=application/xml&outputschema=http://www.opengis.net/cat/csw/3.0&startposition=1&maxrecords=&recordids='>d94c801a-1207-4897-b84a-53f3a192515b</a></li>
+<li><a href='../csw.py?id=urn:uuid:94bc9c83-97f6-4b40-9eb8-a8e8787a5c63&elementSetName=full&request=GetRecordById&service=CSW&version=3.0.0'>da859e34-91fc-495a-8c09-285a40c0900b</a></li>
+<li><a href='../csw.py?mode=opensearch&service=CSW&version=3.0.0&request=GetRecords&elementsetname=full&typenames=csw:Record&resulttype=results&q=ipsum&bbox=&time=/&outputformat=application/atom%2Bxml&startposition=1&maxrecords=&recordids='>dc246fb8-5af5-4fda-82bb-c18b3ecd439c</a></li>
+<li><a href='../csw.py?mode=opensearch&service=CSW&version=3.0.0&request=GetRecords&elementsetname=full&typenames=csw:Record&resulttype=results&q=&bbox=&time=/&outputformat=application/atom%2Bxml&startposition=1&maxrecords=&recordids=urn%3Auuid%3A94bc9c83-97f6-4b40-9eb8-a8e8787a5c63'>de016645-6d5c-4855-943c-2db07ae9f49a</a></li>
+<li><a href='../csw.py?elementSetName=summary&request=GetRecords&service=CSW&typeNames=Record&version=3.0.0'>dff3ec6b-bb2d-4887-bd17-8fcf15def042</a></li>
+<li><a href='../csw.py?id=urn:uuid:1ef30a8b-876d-4828-9246-c37ab4510bbd&elementSetName=brief&request=GetRecordById&service=CSW&version=3.0.0'>e38e6bfb-8ac4-4ae4-8b87-0aafbc8d3c6b</a></li>
+<li><a href='../csw.py?PYCSW_SERVER?config=tests/suites/csw30/default.cfg'>e67ca935-d65d-4d8c-8302-1405333dded0</a></li>
+<li><a href='../csw.py?elementName=ns1:subject&elementSetName=brief&request=GetRecords&service=CSW&typeNames=Record&namespace=xmlns(ns1%3Dhttp://purl.org/dc/elements/1.1/)&version=3.0.0'>e7704509-3441-458f-8ef0-e333c6b6043f</a></li>
+<li><a href='../csw.py?elementSetName=summary&maxRecords=0&q=titles&request=GetRecords&service=CSW&typeNames=Record&version=3.0.0'>f1223a49-6d08-44ff-97fe-4c32cbbfad82</a></li>
+<li><a href='../csw.py?elementSetName=full&outputFormat=text/example&request=GetRecords&service=CSW&typeNames=Record&version=3.0.0'>f89dd4e1-3a81-4433-afd2-a3fa1bdb1e18</a></li>
+<li><a href='../csw.py?service=CSW&version=2.0.2&request=GetCapabilities'>GetCapabilities</a></li>
+<li><a href='../csw.py?service=CSW&version=2.0.2&request=GetCapabilities&lang=gre'>GetCapabilities-lang</a></li>
+<li><a href='../csw.py?mode=opensearch&service=CSW&version=2.0.2&request=GetRecords&typenames=csw:Record&resulttype=results&elementsetname=brief'>opensearch</a></li>
+<li><a href='../csw.py?mode=opensearch&service=CSW&version=2.0.2&request=GetCapabilities'>opensearch-description</a></li>
+<li><a href='../csw.py?mode=opensearch&service=CSW&version=2.0.2&request=GetRecords&elementsetname=full&resulttype=results&typenames=csw:Record&q=greece'>opensearch-ogc-q</a></li>
+<li><a href='../csw.py?mode=opensearch&service=CSW&version=2.0.2&request=GetRecords&elementsetname=full&resulttype=results&typenames=csw:Record&bbox=-180,-90,180,90'>opensearch-ogc-bbox</a></li>
+<li><a href='../csw.py?mode=opensearch&service=CSW&version=2.0.2&request=GetRecords&elementsetname=full&resulttype=results&typenames=csw:Record&time=2001/2004'>opensearch-ogc-time</a></li>
+<li><a href='../csw.py?mode=opensearch&service=CSW&version=2.0.2&request=GetRecords&elementsetname=full&resulttype=results&typenames=csw:Record&time=2004/'>opensearch-ogc-timestart</a></li>
+<li><a href='../csw.py?mode=opensearch&service=CSW&version=2.0.2&request=GetRecords&elementsetname=full&resulttype=results&typenames=csw:Record&time=/2004'>opensearch-ogc-timeend</a></li>
+<li><a href='../csw.py?mode=opensearch&service=CSW&version=2.0.2&request=GetRecords&elementsetname=full&resulttype=results&typenames=csw:Record&time=2001/2007&q=vitae'>opensearch-ogc-q-and-time</a></li>
+<li><a href='../csw.py?mode=opensearch&service=CSW&version=2.0.2&request=GetRecords&elementsetname=full&resulttype=results&typenames=csw:Record&time=2001/2007&bbox=-180,-90,180,90'>opensearch-ogc-bbox-and-time</a></li>
+<li><a href='../csw.py?mode=opensearch&service=CSW&version=2.0.2&request=GetRecords&elementsetname=full&resulttype=results&typenames=csw:Record&q=vegetation&bbox=-180,-90,180,90'>opensearch-ogc-q-and-bbox</a></li>
+<li><a href='../csw.py?mode=opensearch&service=CSW&version=2.0.2&request=GetRecords&elementsetname=full&resulttype=results&typenames=csw:Record&q=vegetation&startposition=1'>opensearch-ogc-count-and-page1</a></li>
+<li><a href='../csw.py?mode=opensearch&service=CSW&version=2.0.2&request=GetRecords&elementsetname=full&resulttype=results&typenames=csw:Record&q=vegetation&startposition=1&maxrecords=1'>opensearch-ogc-count-and-page2</a></li>
+<li><a href='../csw.py?service=CSW&version=2.0.2&request=GetCapabilities'>27e17158-c57a-4493-92ac-dba8934cf462</a></li>
+<li><a href='../csw.py?Service=CSW&Version=2.0.2&Request=GetRecordById&ElementSetName=brief&ID=urn%3Auuid%3A19887a8a-f6b0-4a63-ae56-7fba0e17801f'>27f69b66-5f05-4311-a89c-73ca55c2686b</a></li>
+<li><a href='../csw.py?service=CSW&request=GetCapabilities&acceptversions=2.0.2&date=2006-10-20'>2ab7d1fa-885b-459f-80e4-b6282eab4f8c</a></li>
+<li><a href='../csw.py?service=CSW&version=2.0.2&request=GetRecordById&id=urn%3Auuid%3A9a669547-b69b-469f-a11f-2d875366bbdc'>37aa90e2-6ff0-420c-af15-8b9463099a73</a></li>
+<li><a href='../csw.py?service=CSW&request=GetCapabilities&acceptformats=message/example'>3a8a3c47-455f-4f49-9078-03119f3e70b3</a></li>
+<li><a href='../csw.py?service=CSW&version=2.0.2&request=GetRecordById'>4515831f-834a-4699-95f6-ab0c2cbfcfd0</a></li>
+<li><a href='../csw.py?service=CSW&request=GetCapabilities&sections='>477b23a3-baa9-47c8-9541-5fe27735ed49</a></li>
+<li><a href='../csw.py?sErViCe=CSW&REQUEST=GetCapabilities&version=2.0.2'>48f26761-3a9d-48db-bee1-da089f5fb857</a></li>
+<li><a href='../csw.py?Service=CSW&Version=2.0.2&Request=GetRecordById&OutputFormat=application/bogus_xml&id=urn:uuid:a06af396-3105-442d-8b40-22b57a90d2f2,urn:uuid:19887a8a-f6b0-4a63-ae56-7fba0e17801f,urn:uuid:ab42a8c4-95e8-4630-bf79-33e59241605a'>4e38092f-1586-44b8-988e-0acfa5855916</a></li>
+<li><a href='../csw.py?service=CSW&request=GetCapabilities&sections=OperationsMetadata,ServiceIdentification'>55c38f00-2553-42c1-99ab-33edbb561ad7</a></li>
+<li><a href='../csw.py?service=FOO&request=GetCapabilities'>5ab5db18-c87a-4fbf-a8d8-b7289b09ac81</a></li>
+<li><a href='../csw.py?service=CSW&version=2.0.2&request=GetRecordById&id=urn:uuid:ce8627a0-685c-11db-bd13-0800200c9a66,urn:uuid:6a3de50b-fa66-4b58-a0e6-ca146fdd18d4'>6a4f57ca-a1bd-4802-89c2-44860dbdb0f0</a></li>
+<li><a href='../csw.py?Service=CSW&Version=2.0.2&Request=GetRecordById&OutputSchema=http://www.w3.org/2005/Atom&Id=urn:uuid:19887a8a-f6b0-4a63-ae56-7fba0e17801f'>6c375703-9c00-4aef-bec7-d2e964f849eb</a></li>
+<li><a href='../csw.py?service=CSW&request=GetCapabilities'>80f31def-4185-48b9-983a-960566918eae</a></li>
+<li><a href='../csw.py?SERVICE=CSW&REQUEST=GetCapabilities&ACCEPTVERSIONS=2006.10.29'>8e2232ed-05d9-44ae-8b04-0911cbe6a507</a></li>
+<li><a href='../csw.py?service=CSW&request=GetCapabilities'>9697f0aa-3b6a-4125-83a5-61e8826127c4</a></li>
+<li><a href='../csw.py?Service=CSW&Version=2.0.2&Request=GetRecordById&ElementSetName=full&ID=urn%3Auuid%3Ae9330592-0932-474b-be34-c3a3bb67c7db'>9bfd17fa-15dc-4a10-8fa7-b3cff7013dd7</a></li>
+<li><a href='../csw.py?service=CSW&version=2.0.2&request=GetRecordById&id=urn:uuid:ce8627a0-685c-11db-bd13-0800200c9a66'>b81c3595-06d6-4693-82ea-1ff8650755ac</a></li>
+<li><a href='../csw.py?SERVICE=CSW&REQUEST=GetCapabilities&ACCEPTVERSIONS=2.0.2,2.0.0'>ba5fc729-3b71-47a0-b7d0-42ec565cd185</a></li>
+<li><a href='../csw.py?request=GetCapabilities'>c4ea754f-c158-4d8d-8253-dc8f86021b52</a></li>
+<li><a href='../csw.py?service=CSW&version=2.0.2&request=GetCapabilities'>f4692ec5-9547-4a05-88ab-e6154af2640a</a></li>
+<li><a href='../csw.py?service=CSW&version=2.0.2&request=GetRecordById&id=urn:uuid:94bc9c83-97f6-4b40-9eb8-a8e8787a5c63'>f997f25e-c865-4d53-a362-0ed1846337f2</a></li>
+<li><a href='../csw.py?service=CSW&version=2.0.2&request=GetCapabilities'>GetCapabilities</a></li>
+<li><a href='../csw.py?service=CSW&version=2.0.2&request=GetCapabilitiese'>GetCapabilities-invalid-request</a></li>
+<li><a href='../csw.py?service=CSW&version=2.0.2&request=GetRecords&typenames=csw:Record&elementsetname=full'>GetRecords-all</a></li>
+<li><a href='../csw.py?service=CSW&version=2.0.2&request=GetRecords&typenames=csw:Record&elementsetname=full&resulttype=results&sortby=dc:title:A'>GetRecords-sortby-asc</a></li>
+<li><a href='../csw.py?service=CSW&version=2.0.2&request=GetRecords&typenames=csw:Record&elementsetname=full&resulttype=results&sortby=dc:title:D'>GetRecords-sortby-desc</a></li>
+<li><a href='../csw.py?service=CSW&version=2.0.2&request=GetRecords&typenames=csw:Record&elementsetname=full&resulttype=results&sortby=dc:titlei:A'>GetRecords-sortby-invalid-propertyname</a></li>
+<li><a href='../csw.py?service=CSW&version=2.0.2&request=GetRecords&typenames=csw:Record&elementsetname=full&resulttype=results&sortby=dc:title:FOO'>GetRecords-sortby-invalid-order</a></li>
+<li><a href='../csw.py?service=CSW&version=2.0.2&request=GetRecords&typenames=csw:Record&elementsetname=full&resulttype=results&constraintlanguage=FILTER&constraint=%3Cogc%3AFilter%20xmlns%3Aogc%3D%22http%3A%2F%2Fwww.opengis.net%2Fogc%22%3E%3Cogc%3APropertyIsEqualTo%3E%3Cogc%3APropertyName%3Edc%3Atitle%3C%2Fogc%3APropertyName%3E%3Cogc%3ALiteral%3ELorem%20ipsum%3C%2Fogc%3ALiteral%3E%3C%2Fogc%3APropertyIsEqualTo%3E%3C%2Fogc%3AFilter%3E'>GetRecords-filter</a></li>
+<li><a href='../csw.py?service=CSW&version=2.0.2&request=GetRecords&typenames=csw:Record&elementsetname=full&resulttype=results&constraintlanguage=CQL_TEXT&constraint=dc%3Atitle%20like%20%27%25lor%25%27'>GetRecords-filter-cql-title</a></li>
+<li><a href='../csw.py?service=CSW&version=2.0.2&request=GetRecords&typenames=csw:Record&elementsetname=full&resulttype=results&constraintlanguage=CQL_TEXT&constraint=dc%3Atitle%20like%20%27%25Lorem%20ipsum%25%27'>GetRecords-filter-cql-title-with-spaces</a></li>
+<li><a href='../csw.py?service=CSW&version=2.0.2&request=GetRecords&typenames=csw:Record&elementsetname=full&resulttype=results&constraintlanguage=CQL_TEXT&constraint=dc%3Atitle%20like%20%27%25lor%25%27%20or%20dct%3Aabstract%20like%20%27%25pharetra%25%27'>GetRecords-filter-cql-title-or-abstract</a></li>
+<li><a href='../csw.py?service=CSW&version=2.0.2&request=GetRecords&typenames=csw:Record&elementsetname=full&resulttype=results&constraintlanguage=CQL_TEXT&constraint=dc%3Atitle%20like%20%27%25dolor%20sit%25%27%20or%20dct%3Aabstract%20like%20%27%25pharetra%25%27'>GetRecords-filter-cql-title-with-spaces-or-abstract</a></li>
+<li><a href='../csw.py?service=CSW&version=2.0.2&request=GetRecords&typenames=csw:Record&elementsetname=full&resulttype=results&constraintlanguage=CQL_TEXT&constraint=dc%3Atitle%20like%20%27%25lor%25%27%20or%20dct%3Aabstract%20like%20%27%25pharetra%20in%25%27'>GetRecords-filter-cql-title-or-abstract-with-spaces</a></li>
+<li><a href='../csw.py?service=CSW&version=2.0.2&request=GetRecords&typenames=csw:Record&elementsetname=full&resulttype=results&constraintlanguage=CQL_TEXT&constraint=dc%3Atitle%20like%20%27%25dolor%20sit%25%27%20or%20dct%3Aabstract%20like%20%27%25pharetra%20in%25%27'>GetRecords-filter-cql-title-with-spaces-or-abstract-with-spaces</a></li>
+<li><a href='../csw.py?service=CSW&version=2.0.2&request=GetRecords&typenames=csw:Record&elementsetname=full&maxrecords='>GetRecords-empty-maxrecords</a></li>
+<li><a href='../csw.py?service=CSW&version=2.0.2&request=GetRepositoryItem&id=urn:uuid:94bc9c83-97f6-4b40-9eb8-a8e8787a5c63'>GetRepositoryItem</a></li>
+<li><a href='../csw.py?service=CSW&version=2.0.2&request=GetRepositoryItem&id=NOTFOUND'>Exception-GetRepositoryItem-notfound</a></li>
+<li><a href='../csw.py?service=CSW%00&version=2.0.2&request=GetRepositoryItem&id=123'>Exception-GetRepositoryItem-service-invalid1</a></li>
+<li><a href="../csw.py?service=CSW%00'&version=2.0.2&request=GetRepositoryItem&id=123">Exception-GetRepositoryItem-service-invalid2</a></li>
+<li><a href="../csw.py?service=CSW&version=2.0.2'&request=GetRepositoryItem&id=123">Exception-GetRepositoryItem-version-invalid</a></li>
+<li><a href='../csw.py?mode=sru'>explain</a></li>
+<li><a href='../csw.py?mode=sru&version=1.1&operation=searchRetrieve&query=lor'>search</a></li>
+<li><a href='../csw.py?mode=sru&operation=searchRetrieve&query=lor&maximumRecords=2'>search_maxrecords</a></li>
+<li><a href='../csw.py?mode=sru&operation=searchRetrieve&query=lor&maximumRecords=2&startRecord=1'>search_startrecord_maxrecords</a></li>
+<li><a href="../csw.py?mode=sru&operation=searchRetrieve&query=dc:title%20like%20'%lor%'&maximumRecords=5">search_cql</a></li>
 
             </ul>
         <hr/>
diff --git a/tests/run_tests.py b/tests/run_tests.py
deleted file mode 100644
index 5ab6912..0000000
--- a/tests/run_tests.py
+++ /dev/null
@@ -1,577 +0,0 @@
-#!/usr/bin/python
-# =================================================================
-#
-# Authors: Tom Kralidis <tomkralidis at gmail.com>
-#          Ricardo Garcia Silva <ricardo.garcia.silva at gmail.com>
-#
-# Copyright (c) 2016 Tom Kralidis
-# Copyright (c) 2016 Ricardo Garcia Silva
-#
-# Permission is hereby granted, free of charge, to any person
-# obtaining a copy of this software and associated documentation
-# files (the "Software"), to deal in the Software without
-# restriction, including without limitation the rights to use,
-# copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the
-# Software is furnished to do so, subject to the following
-# conditions:
-#
-# The above copyright notice and this permission notice shall be
-# included in all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
-# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
-# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-# OTHER DEALINGS IN THE SOFTWARE.
-#
-# =================================================================
-
-# simple testing framework inspired by MapServer msautotest
-
-import codecs
-import csv
-import filecmp
-import getopt
-import glob
-from io import BytesIO
-import json
-import os
-import re
-import sys
-import time
-
-from lxml import etree
-from lxml import objectify
-
-from pycsw.core.util import get_elapsed_time, http_request
-
-ENCODING = 'utf-8'
-
-def plural(num):
-    """Determine plurality given an integer"""
-    if num != 1:
-        return 's'
-    else:
-        return ''
-
-
-def test_xml_result(result, expected, encoding=ENCODING):
-    """Compare the XML test results with an expected value.
-
-    This function compares the test result with the expected values by
-    performing XML canonicalization (c14n)[1]_.
-
-    Parameters
-    ----------
-    result: bytes
-        The result of running the test.
-    expected: bytes
-        The expected outcome.
-
-    Returns
-    -------
-    bool
-        Whether the result matches the expectations or not.
-
-    Raises
-    ------
-    etree.XMLSyntaxError
-        If any of the input parameters is not a valid XMl.
-    etree.C14NError
-        If any of the input parameters cannot be canonicalized. This may
-        happen if there are relative namespace URIs in any of the XML
-        documents, as they are explicitly not allowed when doing XML c14n
-
-    References
-    ----------
-    .. [1] http://www.w3.org/TR/xml-c14n
-
-    """
-
-    try:
-        result_element = etree.fromstring(result)
-        expected_element = etree.fromstring(expected)
-        result_buffer = BytesIO()
-        result_tree = result_element.getroottree()
-        objectify.deannotate(result_tree, cleanup_namespaces=True)
-        result_tree.write_c14n(result_buffer)
-        expected_buffer = BytesIO()
-        expected_tree = expected_element.getroottree()
-        objectify.deannotate(expected_tree, cleanup_namespaces=True)
-        expected_tree.write_c14n(expected_buffer)
-        matches = result_buffer.getvalue() == expected_buffer.getvalue()
-        if not matches:
-            print("result:")
-            print(result_buffer.getvalue())
-            print("+++++++++++++++++++++++")
-            print("expected:")
-            print(expected_buffer.getvalue())
-
-    except etree.XMLSyntaxError:
-        matches = None
-    return matches
-
-
-def test_json_result(result, expected, encoding=ENCODING):
-    """Compare the JSON test results with an expected value.
-
-    Parameters
-    ----------
-    result: bytes
-        The result of running the test.
-    expected: bytes
-        The expected outcome.
-
-    Returns
-    -------
-    bool
-        Whether the result matches the expectations or not.
-
-    """
-
-    try:
-        result_dict = json.loads(result.decode(encoding))
-        expected_dict = json.loads(expected.decode(encoding))
-    except ValueError:
-        matches = None
-    else:
-        matches = result_dict == expected_dict
-    return matches
-
-
-def get_validity(expected_path, result, output_file_name, force_id_mask=False):
-    """Test whether the test result matches the expected outcome.
-
-    This function deals with both XML and JSON results. It first tries to
-    parse the result and the expected outcome as XML and evaluates them using
-    XML canonicalization (c14n). If the result cannot be parsed as XML, it then
-    tries to load it as JSON and does a sorted comparison.
-
-    Parameters
-    ----------
-    expected_path: bytes
-        The path to the file that has the expected test outcome
-    result: bytes
-        The actual result that was generated by running the test code
-    output_file_name: str
-        Name of the file that will be written to disk with the contents of
-        the result
-    force_id_mask: bool, optional
-        Whether to apply result normalization to id fields
-
-    Returns
-    -------
-    int
-        One of three possible values:
-
-        * If the input `expected_path` could not be found, the results will
-          be used to generate a new expected file. In this case the return
-          value will be 0;
-        * If the result matches the expected outcome, the return value is 1;
-        * If the result does not match the expected outcome the return value is
-          -1.
-
-    """
-
-    normalized_result = normalize(result, force_id_mask=force_id_mask)
-    if not os.path.exists(expected_path):  # create expected file
-        with open(expected_path, 'wb') as f:
-            f.write(normalized_result)
-        status = 0
-    else:  # compare result with expected
-        with open(expected_path, 'rb') as expected_fh:
-            expected = expected_fh.read()
-            matches_expected = test_xml_result(normalized_result, expected)
-            if matches_expected is None:
-                # the file is either not XML (perhaps JSON?) or malformed
-                matches_expected = test_json_result(
-                    normalized_result, expected, encoding=ENCODING)
-        if matches_expected:  # pass
-            status = 1
-        else:  # failed
-            status = -1
-            if not os.path.exists('results'):
-                os.mkdir('results')
-            with open('results%s%s' % (os.sep, output_file_name), 'wb') as f:
-                f.write(normalized_result)
-    return status
-
-
-def pedantic_get_validity(sexpected, sresult, soutfile, force_id_mask=False):
-    """Decipher whether the output passes, fails, or initializes"""
-    if not os.path.exists(sexpected):  # create expected file
-        with open(sexpected, 'wb') as f:
-            f.write(normalize(sresult, force_id_mask))
-        sstatus = 0
-    else:  # compare result with expected
-        if not os.path.exists('results'):
-            os.mkdir('results')
-        with open('results%s%s' % (os.sep, soutfile), 'wb') as f:
-            f.write(normalize(sresult, force_id_mask))
-        if filecmp.cmp(sexpected, 'results%s%s' % (os.sep, soutfile)):  # pass
-            os.remove('results%s%s' % (os.sep, soutfile))
-            sstatus = 1
-        else:  # fail
-            import difflib
-            with open(sexpected, 'rb') as a:
-                with open('results%s%s' % (os.sep, soutfile), 'rb') as b:
-                    a2 = a.readlines()
-                    b2 = b.readlines()
-                    diff = difflib.unified_diff(a2, b2)
-            print('\n'.join(list(diff)))
-            if len(a2) != len(b2):
-                print('LINE COUNT: expected: %d, result: %d' % (len(a2), len(b2)))
-            sstatus = -1
-    return sstatus
-
-
-def normalize(sresult, force_id_mask=False):
-    """Replace time, updateSequence and version specific values with generic
-    values"""
-
-    # XML responses
-    version = re.search(b'<!-- (.*) -->', sresult)
-    updatesequence = re.search(b'updateSequence="(\S+)"', sresult)
-    timestamp = re.search(b'timestamp="(.*)"', sresult)
-    timestamp2 = re.search(b'timeStamp="(.*)"', sresult)
-    timestamp3 = re.search(b'<oai:responseDate>(.*)</oai:responseDate>', sresult)
-    timestamp4 = re.search(b'<oai:earliestDatestamp>(.*)</oai:earliestDatestamp>', sresult)
-    zrhost = re.search(b'<zr:host>(.*)</zr:host>', sresult)
-    zrport = re.search(b'<zr:port>(.*)</zr:port>', sresult)
-    elapsed_time = re.search(b'elapsedTime="(.*)"', sresult)
-    expires = re.search(b'expires="(.*?)"', sresult)
-    atom_updated = re.findall(b'<atom:updated>(.*)</atom:updated>', sresult)
-
-    if version:
-        sresult = sresult.replace(version.group(0), b'<!-- PYCSW_VERSION -->')
-    if updatesequence:
-        sresult = sresult.replace(updatesequence.group(0),
-                                  b'updateSequence="PYCSW_UPDATESEQUENCE"')
-    if timestamp:
-        sresult = sresult.replace(timestamp.group(0),
-                                  b'timestamp="PYCSW_TIMESTAMP"')
-    if timestamp2:
-        sresult = sresult.replace(timestamp2.group(0),
-                                  b'timeStamp="PYCSW_TIMESTAMP"')
-    if timestamp3:
-        sresult = sresult.replace(timestamp3.group(0),
-                                  b'<oai:responseDate>PYCSW_TIMESTAMP</oai:responseDate>')
-    if timestamp4:
-        sresult = sresult.replace(timestamp4.group(0),
-                                  b'<oai:earliestDatestamp>PYCSW_TIMESTAMP</oai:earliestDatestamp>')
-    if zrport:
-        sresult = sresult.replace(zrport.group(0),
-                                  b'<zr:port>PYCSW_PORT</zr:port>')
-    if zrhost:
-        sresult = sresult.replace(zrhost.group(0),
-                                  b'<zr:host>PYCSW_HOST</zr:host>')
-    if elapsed_time:
-        sresult = sresult.replace(elapsed_time.group(0),
-                                  b'elapsedTime="PYCSW_ELAPSED_TIME"')
-    if expires:
-        sresult = sresult.replace(expires.group(0),
-                                  b'expires="PYCSW_EXPIRES"')
-    for au in atom_updated:
-        sresult = sresult.replace(au, b'PYCSW_TIMESTAMP')
-
-    # for csw:HarvestResponse documents, mask identifiers
-    # which are dynamically generated for OWS endpoints
-    if sresult.find(b'HarvestResponse') != -1:
-        identifier = re.findall(b'<dc:identifier>(\S+)</dc:identifier>',
-                                sresult)
-        for i in identifier:
-            sresult = sresult.replace(i, b'PYCSW_IDENTIFIER')
-
-    # JSON responses
-    timestamp = re.search(b'"@timestamp": "(.*?)"', sresult)
-
-    if timestamp:
-        sresult = sresult.replace(timestamp.group(0),
-                                  b'"@timestamp": "PYCSW_TIMESTAMP"')
-
-    # harvesting-based GetRecords/GetRecordById responses
-    if force_id_mask:
-        dcid = re.findall(b'<dc:identifier>(urn:uuid.*)</dc:identifier>', sresult)
-        isoid = re.findall(b'id="(urn:uuid.*)"', sresult)
-        isoid2 = re.findall(b'<gco:CharacterString>(urn:uuid.*)</gco', sresult)
-
-        for d in dcid:
-            sresult = sresult.replace(d, b'PYCSW_IDENTIFIER')
-        for i in isoid:
-            sresult = sresult.replace(i, b'PYCSW_IDENTIFIER')
-        for i2 in isoid2:
-            sresult = sresult.replace(i2, b'PYCSW_IDENTIFIER')
-
-    return sresult
-
-def usage():
-    """Provide usage instructions"""
-    return '''
-NAME
-    run_tests.py - pycsw unit test testrunner
-
-SYNOPSIS
-    run_tests.py -u <url> [-l logfile] [-s suite1[,suite2]]
-
-    Available options:
-
-    -u    URL to test
-
-    -l    log results to file
-
-    -s    testsuites to run (comma-seperated list)
-
-    -p    run tests in pedantic mode (byte level diff check) (default: c14n mode)
-
-    -d    database (SQLite3 [default], PostgreSQL, MySQL)
-
-    -r    run tests which harvest remote resources (default off)
-
-    -t    time (milliseconds) in which requests should complete
-
-EXAMPLES
-
-    1.) default test example
-
-        run_tests.py -u http://localhost:8000/
-
-    2.) log results to logfile
-
-        run_tests.py -u http://localhost:8000/ -l /path/to/results.log
-
-    3.) run only specified testsuites
-
-        run_tests.py -u http://localhost:8000/ -s default,apiso
-
-    4.) run tests including remote harvest tests
-
-        run_tests.py -u http://localhost:8000/ -s default,apiso -r
-
-    5.) default test example with 1000ms time benchmark
-
-        run_tests.py -u http://localhost:8000/ -t 1000
-
-
-'''
-
-# main
-
-if len(sys.argv) < 2:
-    print(usage())
-    sys.exit(1)
-
-URL = sys.argv[1]
-
-URL = None
-LOGFILE = None
-TESTSUITES = []
-
-PASSED = 0
-FAILED = 0
-WARNING = 0
-INITED = 0
-
-LOGWRITER = None
-DATABASE = 'SQLite3'
-REMOTE = False
-PEDANTIC = False
-TIME = None
-
-try:
-    OPTS, ARGS = getopt.getopt(sys.argv[1:], 'u:l:s:d:t:rhp')
-except getopt.GetoptError as err:
-    print('\nERROR: %s' % err)
-    print(usage())
-    sys.exit(2)
-
-for o, a in OPTS:
-    if o == '-u':
-        URL = a
-    if o == '-l':
-        LOGFILE = a
-    if o == '-d':
-        DATABASE = a
-    if o == '-t':
-        TIME = int(a)
-    if o == '-r':
-        REMOTE = True
-    if o == '-p':
-        PEDANTIC = True
-    if o == '-s':
-        TESTSUITES = a.split(',')
-    if o == '-h':  # dump help and exit
-        print(usage())
-        sys.exit(3)
-
-print('\nRunning tests against %s' % URL)
-
-if LOGFILE is not None:  # write detailed output to CSV
-    LOGWRITER = csv.writer(open(LOGFILE, 'wb'))
-    LOGWRITER.writerow(['url', 'configuration', 'testname', 'result'])
-
-if TIME is not None:  # perform benchmarking
-    print('Benchmark: %dms' % TIME)
-
-if TESTSUITES:
-    if 'harvesting' in TESTSUITES:
-        REMOTE = True
-    TESTSUITES_LIST = ['suites%s%s' % (os.sep, x) for x in TESTSUITES]
-else:
-    TESTSUITES_LIST = glob.glob('suites%s*' % os.sep)
-
-for testsuite in TESTSUITES_LIST:
-    if not os.path.exists(testsuite):
-        raise RuntimeError('Testsuite %s not found' % testsuite)
-
-    if testsuite == 'suites%sharvesting' % os.sep and not REMOTE:
-        continue
-
-    force_id_mask = False
-    if testsuite in ['suites%smanager' % os.sep, 'suites%sharvesting' % os.sep]:
-        force_id_mask = True
-
-    # get configuration
-    for cfg in glob.glob('%s%s*.cfg' % (testsuite, os.sep)):
-        print('\nTesting configuration %s' % cfg)
-
-        for root, dirs, files in os.walk(testsuite):
-            if files:
-                for sfile in sorted(files):
-                    if os.path.splitext(sfile)[1] not in ['.xml', '.txt']:
-                        break
-
-                    if os.path.basename(root) == "exports":
-                        continue
-
-                    if sfile == 'requests.txt':  # GET requests
-                        filename = '%s%s%s' % (root, os.sep, sfile)
-                        with open(filename) as f:
-                            gets = csv.reader(f)
-                            for row in gets:
-                                testfile = '%s%s%s' % (root, os.sep, sfile)
-                                request = ','.join(row[1:]).replace('PYCSW_SERVER',
-                                                                    URL)
-                                outfile = '%s%s' % (root.replace(os.sep, '_'),
-                                                    '_%s.xml' % row[0])
-                                expected = 'expected%s%s' % (os.sep, outfile)
-                                print('\n test %s:%s' % (testfile, row[0]))
-
-                                try:
-                                    begin = time.time()
-                                    result = http_request('GET', request)
-                                    end = time.time()
-                                    elapsed = get_elapsed_time(begin, end)
-                                    print('  completed in %dms' % elapsed)
-                                except Exception as err:
-                                    result = err.read()
-                                if PEDANTIC:
-                                    status = pedantic_get_validity(
-                                        expected, result, outfile,
-                                        force_id_mask
-                                    )
-                                else:
-                                    try:
-                                        status = get_validity(expected, result,
-                                                              outfile,
-                                                              force_id_mask)
-                                    except etree.C14NError:
-                                        print("Could not canonicalize {0}. "
-                                              "Using pedantic "
-                                              "mode".format(row[0]))
-                                        status = pedantic_get_validity(
-                                            expected, result, outfile,
-                                            force_id_mask
-                                        )
-
-                                if status == 1:
-                                    print('  passed')
-                                    PASSED += 1
-                                elif status == 0:
-                                    print('  initialized')
-                                    INITED += 1
-                                elif status == -1 and DATABASE == 'PostgreSQL':
-                                    print('  warning: possible collation issue')
-                                    WARNING += 1
-                                else:
-                                    print('  FAILED')
-                                    FAILED += 1
-
-                                if TIME and get_elapsed_time(begin, end) > TIME:
-                                    print('  FAILED BENCHMARK')
-
-                                if LOGWRITER is not None:
-                                    LOGWRITER.writerow([URL, cfg,
-                                                        testfile, status])
-
-                    else:  # POST requests
-                        testfile = '%s%s%s' % (root, os.sep, sfile)
-                        if '%sdata' % os.sep in testfile:  # sample data
-                            break
-                        outfile = '%s%s' % (os.sep,
-                                            testfile.replace(os.sep, '_'))
-                        expected = 'expected%s%s' % (os.sep, outfile)
-                        print('\n test %s' % testfile)
-
-                        # read test
-                        with open(testfile, 'rb') as fh:
-                            request = fh.read()
-
-                        configkvp = 'config=tests%s%s' % (os.sep, cfg)
-                        url2 = '%s?%s' % (URL, configkvp)
-
-                        # invoke request
-                        try:
-                            begin = time.time()
-                            result = http_request('POST', url2, request)
-                            end = time.time()
-                            elapsed = get_elapsed_time(begin, end)
-                            print('  completed in %dms' % elapsed)
-                        except Exception as err:
-                            result = err.read()
-                        if PEDANTIC:
-                            status = pedantic_get_validity(
-                                expected, result, outfile, force_id_mask)
-                        else:
-                            try:
-                                status = get_validity(expected, result, outfile,
-                                                      force_id_mask)
-                            except etree.C14NError:
-                                print("Could not canonicalize {0}. Using "
-                                      "pedantic mode".format(sfile))
-                                status = pedantic_get_validity(
-                                    expected, result, outfile, force_id_mask)
-
-                        if status == 1:
-                            print('  passed')
-                            PASSED += 1
-                        elif status == 0:
-                            print('  initialized')
-                            INITED += 1
-                        elif status == -1 and DATABASE == 'PostgreSQL':
-                            print('  warning: possible sorting collation issue')
-                            WARNING += 1
-                        else:
-                            print('  FAILED')
-                            FAILED += 1
-
-                        if TIME and get_elapsed_time(begin, end) > TIME:
-                            print('  FAILED BENCHMARK')
-
-                        if LOGWRITER is not None:
-                            LOGWRITER.writerow([URL, cfg, testfile, status])
-
-if LOGWRITER is not None:
-    LOGWRITER.close()
-
-print('\nResults (%d/%d - %.2f%%)' %
-      (PASSED, PASSED + FAILED, float(PASSED) / float(PASSED + FAILED) * 100))
-print('   %d test%s passed' % (PASSED, plural(PASSED)))
-print('   %d test%s warnings' % (WARNING, plural(WARNING)))
-print('   %d test%s failed' % (FAILED, plural(FAILED)))
-print('   %d test%s initialized' % (INITED, plural(INITED)))
-
-sys.exit(FAILED)
diff --git a/tests/suites/apiso-inspire/get/requests.txt b/tests/suites/apiso-inspire/get/requests.txt
deleted file mode 100644
index 862e409..0000000
--- a/tests/suites/apiso-inspire/get/requests.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-GetCapabilities,PYCSW_SERVER?config=tests/suites/apiso-inspire/default.cfg&service=CSW&version=2.0.2&request=GetCapabilities
-GetCapabilities-lang,PYCSW_SERVER?config=tests/suites/apiso-inspire/default.cfg&service=CSW&version=2.0.2&request=GetCapabilities&lang=gre
diff --git a/tests/suites/atom/get/requests.txt b/tests/suites/atom/get/requests.txt
deleted file mode 100644
index ba73cf8..0000000
--- a/tests/suites/atom/get/requests.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-opensearch,PYCSW_SERVER?config=tests/suites/atom/default.cfg&mode=opensearch&service=CSW&version=2.0.2&request=GetRecords&typenames=csw:Record&resulttype=results&elementsetname=brief
-opensearch-description,PYCSW_SERVER?config=tests/suites/atom/default.cfg&mode=opensearch&service=CSW&version=2.0.2&request=GetCapabilities
-opensearch-ogc-q,PYCSW_SERVER?config=tests/suites/atom/default.cfg&mode=opensearch&service=CSW&version=2.0.2&request=GetRecords&elementsetname=full&resulttype=results&typenames=csw:Record&q=greece
-opensearch-ogc-bbox,"PYCSW_SERVER?config=tests/suites/atom/default.cfg&mode=opensearch&service=CSW&version=2.0.2&request=GetRecords&elementsetname=full&resulttype=results&typenames=csw:Record&bbox=-180,-90,180,90"
-opensearch-ogc-time,PYCSW_SERVER?config=tests/suites/atom/default.cfg&mode=opensearch&service=CSW&version=2.0.2&request=GetRecords&elementsetname=full&resulttype=results&typenames=csw:Record&time=2001/2004
-opensearch-ogc-timestart,PYCSW_SERVER?config=tests/suites/atom/default.cfg&mode=opensearch&service=CSW&version=2.0.2&request=GetRecords&elementsetname=full&resulttype=results&typenames=csw:Record&time=2004/
-opensearch-ogc-timeend,PYCSW_SERVER?config=tests/suites/atom/default.cfg&mode=opensearch&service=CSW&version=2.0.2&request=GetRecords&elementsetname=full&resulttype=results&typenames=csw:Record&time=/2004
-opensearch-ogc-q-and-time,PYCSW_SERVER?config=tests/suites/atom/default.cfg&mode=opensearch&service=CSW&version=2.0.2&request=GetRecords&elementsetname=full&resulttype=results&typenames=csw:Record&time=2001/2007&q=vitae
-opensearch-ogc-bbox-and-time,"PYCSW_SERVER?config=tests/suites/atom/default.cfg&mode=opensearch&service=CSW&version=2.0.2&request=GetRecords&elementsetname=full&resulttype=results&typenames=csw:Record&time=2001/2007&bbox=-180,-90,180,90"
-opensearch-ogc-q-and-bbox,"PYCSW_SERVER?config=tests/suites/atom/default.cfg&mode=opensearch&service=CSW&version=2.0.2&request=GetRecords&elementsetname=full&resulttype=results&typenames=csw:Record&q=vegetation&bbox=-180,-90,180,90"
-opensearch-ogc-count-and-page1,"PYCSW_SERVER?config=tests/suites/atom/default.cfg&mode=opensearch&service=CSW&version=2.0.2&request=GetRecords&elementsetname=full&resulttype=results&typenames=csw:Record&q=vegetation&startposition=1"
-opensearch-ogc-count-and-page2,"PYCSW_SERVER?config=tests/suites/atom/default.cfg&mode=opensearch&service=CSW&version=2.0.2&request=GetRecords&elementsetname=full&resulttype=results&typenames=csw:Record&q=vegetation&startposition=1&maxrecords=1"
diff --git a/tests/suites/cite/get/requests.txt b/tests/suites/cite/get/requests.txt
deleted file mode 100644
index 9eb5bc2..0000000
--- a/tests/suites/cite/get/requests.txt
+++ /dev/null
@@ -1,22 +0,0 @@
-27e17158-c57a-4493-92ac-dba8934cf462,PYCSW_SERVER?config=tests/suites/cite/default.cfg&service=CSW&version=2.0.2&request=GetCapabilities
-27f69b66-5f05-4311-a89c-73ca55c2686b,PYCSW_SERVER?config=tests/suites/cite/default.cfg&Service=CSW&Version=2.0.2&Request=GetRecordById&ElementSetName=brief&ID=urn%3Auuid%3A19887a8a-f6b0-4a63-ae56-7fba0e17801f
-2ab7d1fa-885b-459f-80e4-b6282eab4f8c,PYCSW_SERVER?config=tests/suites/cite/default.cfg&service=CSW&request=GetCapabilities&acceptversions=2.0.2&date=2006-10-20
-37aa90e2-6ff0-420c-af15-8b9463099a73,PYCSW_SERVER?config=tests/suites/cite/default.cfg&service=CSW&version=2.0.2&request=GetRecordById&id=urn%3Auuid%3A9a669547-b69b-469f-a11f-2d875366bbdc
-3a8a3c47-455f-4f49-9078-03119f3e70b3,PYCSW_SERVER?config=tests/suites/cite/default.cfg&service=CSW&request=GetCapabilities&acceptformats=message/example
-4515831f-834a-4699-95f6-ab0c2cbfcfd0,PYCSW_SERVER?config=tests/suites/cite/default.cfg&service=CSW&version=2.0.2&request=GetRecordById
-477b23a3-baa9-47c8-9541-5fe27735ed49,PYCSW_SERVER?config=tests/suites/cite/default.cfg&service=CSW&request=GetCapabilities&sections=
-48f26761-3a9d-48db-bee1-da089f5fb857,PYCSW_SERVER?config=tests/suites/cite/default.cfg&sErViCe=CSW&REQUEST=GetCapabilities&version=2.0.2
-4e38092f-1586-44b8-988e-0acfa5855916,PYCSW_SERVER?config=tests/suites/cite/default.cfg&Service=CSW&Version=2.0.2&Request=GetRecordById&OutputFormat=application/bogus_xml&id=urn:uuid:a06af396-3105-442d-8b40-22b57a90d2f2,urn:uuid:19887a8a-f6b0-4a63-ae56-7fba0e17801f,urn:uuid:ab42a8c4-95e8-4630-bf79-33e59241605a
-55c38f00-2553-42c1-99ab-33edbb561ad7,PYCSW_SERVER?config=tests/suites/cite/default.cfg&service=CSW&request=GetCapabilities&sections=OperationsMetadata,ServiceIdentification
-5ab5db18-c87a-4fbf-a8d8-b7289b09ac81,PYCSW_SERVER?config=tests/suites/cite/default.cfg&service=FOO&request=GetCapabilities
-6a4f57ca-a1bd-4802-89c2-44860dbdb0f0,PYCSW_SERVER?config=tests/suites/cite/default.cfg&service=CSW&version=2.0.2&request=GetRecordById&id=urn:uuid:ce8627a0-685c-11db-bd13-0800200c9a66,urn:uuid:6a3de50b-fa66-4b58-a0e6-ca146fdd18d4
-6c375703-9c00-4aef-bec7-d2e964f849eb,PYCSW_SERVER?config=tests/suites/cite/default.cfg&Service=CSW&Version=2.0.2&Request=GetRecordById&OutputSchema=http://www.w3.org/2005/Atom&Id=urn:uuid:19887a8a-f6b0-4a63-ae56-7fba0e17801f
-80f31def-4185-48b9-983a-960566918eae,PYCSW_SERVER?config=tests/suites/cite/default.cfg&service=CSW&request=GetCapabilities
-8e2232ed-05d9-44ae-8b04-0911cbe6a507,PYCSW_SERVER?config=tests/suites/cite/default.cfg&SERVICE=CSW&REQUEST=GetCapabilities&ACCEPTVERSIONS=2006.10.29
-9697f0aa-3b6a-4125-83a5-61e8826127c4,PYCSW_SERVER?config=tests/suites/cite/default.cfg&service=CSW&request=GetCapabilities
-9bfd17fa-15dc-4a10-8fa7-b3cff7013dd7,PYCSW_SERVER?config=tests/suites/cite/default.cfg&Service=CSW&Version=2.0.2&Request=GetRecordById&ElementSetName=full&ID=urn%3Auuid%3Ae9330592-0932-474b-be34-c3a3bb67c7db
-b81c3595-06d6-4693-82ea-1ff8650755ac,PYCSW_SERVER?config=tests/suites/cite/default.cfg&service=CSW&version=2.0.2&request=GetRecordById&id=urn:uuid:ce8627a0-685c-11db-bd13-0800200c9a66
-ba5fc729-3b71-47a0-b7d0-42ec565cd185,PYCSW_SERVER?config=tests/suites/cite/default.cfg&SERVICE=CSW&REQUEST=GetCapabilities&ACCEPTVERSIONS=2.0.2,2.0.0
-c4ea754f-c158-4d8d-8253-dc8f86021b52,PYCSW_SERVER?config=tests/suites/cite/default.cfg&request=GetCapabilities
-f4692ec5-9547-4a05-88ab-e6154af2640a,PYCSW_SERVER?config=tests/suites/cite/default.cfg&service=CSW&version=2.0.2&request=GetCapabilities
-f997f25e-c865-4d53-a362-0ed1846337f2,PYCSW_SERVER?config=tests/suites/cite/default.cfg&service=CSW&version=2.0.2&request=GetRecordById&id=urn:uuid:94bc9c83-97f6-4b40-9eb8-a8e8787a5c63
diff --git a/tests/suites/csw30/get/requests.txt b/tests/suites/csw30/get/requests.txt
deleted file mode 100644
index d93dd98..0000000
--- a/tests/suites/csw30/get/requests.txt
+++ /dev/null
@@ -1,82 +0,0 @@
-GetCapabilities-base-url,PYCSW_SERVER?config=tests/suites/csw30/default.cfg
-GetCapabilities-no-version,PYCSW_SERVER?config=tests/suites/csw30/default.cfg&service=CSW&request=GetCapabilities
-GetCapabilities,PYCSW_SERVER?config=tests/suites/csw30/default.cfg&service=CSW&version=3.0.0&request=GetCapabilities
-Exception-invalid-request,PYCSW_SERVER?config=tests/suites/csw30/default.cfg&service=CSW&version=3.0.0&request=GetCapabilities-foo
-Exception-GetDomain,PYCSW_SERVER?config=tests/suites/csw30/default.cfg&service=CSW&version=3.0.0&request=GetDomain
-GetDomain-parameter,PYCSW_SERVER?config=tests/suites/csw30/default.cfg&service=CSW&version=3.0.0&request=GetDomain&parametername=GetRecords.ElementSetName
-GetDomain-value-reference,PYCSW_SERVER?config=tests/suites/csw30/default.cfg&service=CSW&version=3.0.0&request=GetDomain&valuereference=dc:title
-Exception-GetDomain-value-reference,PYCSW_SERVER?config=tests/suites/csw30/default.cfg&service=CSW&version=3.0.0&request=GetDomain&valuereference=dc:title2
-Exception-GetRecordById-dc.xml,PYCSW_SERVER?config=tests/suites/csw30/default.cfg&service=CSW&version=3.0.0&request=GetRecordById&id=urn:uuid:829babb0-b2f1-49e1-8cd5-7b489fe71a1e
-Exception-GetRecordById-404,PYCSW_SERVER?config=tests/suites/csw30/default.cfg&service=CSW&version=3.0.0&request=GetRecordById&id=does_not_exist2
-OpenSearch-description,PYCSW_SERVER?config=tests/suites/csw30/default.cfg&mode=opensearch&service=CSW&version=3.0.0&request=GetCapabilities
-GetRepositoryItem,PYCSW_SERVER?config=tests/suites/csw30/default.cfg&service=CSW&version=3.0.0&request=GetRepositoryItem&id=urn:uuid:19887a8a-f6b0-4a63-ae56-7fba0e17801f
-Exception-GetRepositoryItem-notfound,PYCSW_SERVER?config=tests/suites/csw30/default.cfg&service=CSW&version=3.0.0&request=GetRepositoryItem&id=NOTFOUND
-002258f0-627f-457f-b2ad-025777c77ac8,PYCSW_SERVER?config=tests/suites/csw30/default.cfg&mode=opensearch&service=CSW&version=3.0.0&request=GetCapabilities
-045c600d-973d-41eb-9f60-eba1b717b720,PYCSW_SERVER?config=tests/suites/csw30/default.cfg&mode=opensearch&service=CSW&version=3.0.0&request=GetRecords&elementsetname=full&typenames=csw:Record&resulttype=results&q=Fusc%C3%A9%20Land&bbox=&time=/&outputformat=application/atom%2Bxml&startposition=1&maxrecords=&recordids=
-0bbcf862-5211-4351-9988-63f8bec49c98,PYCSW_SERVER?config=tests/suites/csw30/default.cfg&elementSetName=summary&outputFormat=application/atom%2Bxml&request=GetRecords&service=CSW&typeNames=Record&version=3.0.0
-0bdf8457-971e-4ed1-be4a-5feca4dcd8fa,PYCSW_SERVER?config=tests/suites/csw30/default.cfg
-0d8bbdec-0846-42ca-8dc8-b7f4cba41d67,PYCSW_SERVER?config=tests/suites/csw30/default.cfg&elementName=tns:title&request=GetRecords&service=CSW&typeNames=Record&namespace=xmlns(tns%3Dhttp://purl.org/dc/elements/1.1/)&version=3.0.0
-0e1dca37-477a-4060-99fe-7799b52d656c,PYCSW_SERVER?config=tests/suites/csw30/default.cfg&mode=opensearch&service=CSW&version=3.0.0&request=GetRecords&elementsetname=full&typenames=csw:Record&resulttype=results&q=lpppclq&bbox=&time=/&outputformat=application/atom%2Bxml&startposition=1&maxrecords=&recordids=
-13c87956-51a4-4780-a8e9-6e0b5c0bb473,PYCSW_SERVER?config=tests/suites/csw30/default.cfg&elementSetName=full&maxRecords=20&request=GetRecords&service=CSW&typeNames=Record&version=3.0.0
-151d982f-ebd3-4cb2-b507-a667713a1e92,PYCSW_SERVER?config=tests/suites/csw30/default.cfg&acceptFormats=model/x3d%2Bxml&acceptVersions=3.0.0&request=GetCapabilities&service=CSW
-1869e495-1a61-4713-8285-76d1336ee1a6,PYCSW_SERVER?config=tests/suites/csw30/default.cfg&acceptVersions=3.0.0&request=GetCapabilities
-1bcb42a9-538c-4f0a-9d4c-d6f10b720aa6,PYCSW_SERVER?config=tests/suites/csw30/default.cfg&request=GetRecordById&service=CSW&version=3.0.0
-22f44168-2ccf-4801-ad96-204212566d56,PYCSW_SERVER?config=tests/suites/csw30/default.cfg
-2499a9c9-8d33-449c-bc92-d494adfcc84d,PYCSW_SERVER?config=tests/suites/csw30/default.cfg&acceptVersions=3.0.0&sections=All&request=GetCapabilities&service=CSW
-27f4f39c-d92a-4e3c-b961-c6aa8c24e513,PYCSW_SERVER?config=tests/suites/csw30/default.cfg&acceptFormats=application/xml&acceptVersions=3.0.0&request=GetCapabilities&service=CSW
-28e569df-8596-4128-8d9a-29ad03138915,PYCSW_SERVER?config=tests/suites/csw30/default.cfg&id=urn:uuid:a06af396-3105-442d-8b40-22b57a90d2f2&request=GetRecordById&service=CSW&version=3.0.0
-2b06a5c8-0df2-4af1-8d2e-a425de11c845,PYCSW_SERVER?config=tests/suites/csw30/default.cfg
-2ba1418a-444d-4cce-9cfe-4c94efcf8b55,PYCSW_SERVER?config=tests/suites/csw30/default.cfg&maxRecords=2&elementSetName=summary&outputFormat=application/atom%2Bxml&request=GetRecords&service=CSW&typeNames=csw3:Record&startPosition=3&namespace=xmlns(csw3%3Dhttp://www.opengis.net/cat/csw/3.0)&version=3.0.0
-397fe17a-d5b4-4f96-8cc4-4ce467ed4d0a,PYCSW_SERVER?config=tests/suites/csw30/default.cfg&service=CSW&version=3.0.0&request=GetRecords&elementsetname=full&typenames=csw:Record&resulttype=results&q=ipsum&bbox=&time=/&outputformat=application/xml&outputschema=http://www.opengis.net/cat/csw/3.0&startposition=1&maxrecords=&recordids=
-3dcd1b15-73d2-4b7d-a3e3-ff15bf14aae4,PYCSW_SERVER?config=tests/suites/csw30/default.cfg&elementSetName=brief&request=GetRecords&service=CSW&typeNames=tns:Record&namespace=xmlns(tns%3Dhttp://www.opengis.net/cat/csw/3.0)&version=3.0.0
-405e1ff1-5c75-4846-a28b-cfaff2a6921a,PYCSW_SERVER?config=tests/suites/csw30/default.cfg&elementSetName=summary&recordIds=urn:uuid:19887a8a-f6b0-4a63-ae56-7fba0e17801f,urn:uuid:e9330592-0932-474b-be34-c3a3bb67c7db&request=GetRecords&service=CSW&typeNames=Record&version=3.0.0
-43cd6471-6ac7-45bd-8ff9-148cb2de9a52,PYCSW_SERVER?config=tests/suites/csw30/default.cfg
-4566d2ec-1283-4a02-baed-a74fc5b47e37,PYCSW_SERVER?config=tests/suites/csw30/default.cfg&acceptVersions=3.0.0&sections=ServiceIdentification&request=GetCapabilities&service=CSW
-461bd4c5-6623-490d-9036-d91a2201e87b,PYCSW_SERVER?config=tests/suites/csw30/default.cfg&acceptVersions=3.0.0&sections=Filter_Capabilities&request=GetCapabilities&service=CSW
-5496894a-3877-4f62-a20b-5d7126f94925,PYCSW_SERVER?config=tests/suites/csw30/default.cfg&service=CSW&version=3.0.0&request=GetRecords&elementsetname=full&typenames=csw:Record&resulttype=results&q=&bbox=514432,5429689,529130,5451619&time=/&outputformat=application/xml&outputschema=http://www.opengis.net/cat/csw/3.0&startposition=1&maxrecords=&recordids=
-5a015f6a-bf14-4977-b1e3-6577eb0223c8,PYCSW_SERVER?config=tests/suites/csw30/default.cfg&service=CSW&version=3.0.0&request=GetRecords&elementsetname=full&typenames=csw:Record&resulttype=results&q=&bbox=-6.17,44.79,17.92,68.41&time=/&outputformat=application/xml&outputschema=http://www.opengis.net/cat/csw/3.0&startposition=1&maxrecords=&recordids=
-5c3a2390-1fb9-43f0-b96c-f48c7a69c990,PYCSW_SERVER?config=tests/suites/csw30/default.cfg&id=urn:uuid:88247b56-4cbc-4df9-9860-db3f8042e357&outputFormat=model/vnd.collada%2Bxml&request=GetRecordById&service=CSW&version=3.0.0
-5e9e67dc-18d6-4645-8111-c6263c88a61f,PYCSW_SERVER?config=tests/suites/csw30/default.cfg&acceptVersions=3.0.0&sections=OperationsMetadata&request=GetCapabilities&service=CSW
-604d9379-741c-42e5-b4cf-92e56c87fa64,PYCSW_SERVER?config=tests/suites/csw30/default.cfg&elementSetName=full&q=amet&request=GetRecords&service=CSW&typeNames=Record&version=3.0.0
-60e6af95-d5fc-465a-82e2-fd2e6d85e4af,PYCSW_SERVER?config=tests/suites/csw30/default.cfg&request=GetRecords&service=CSW&typeNames=UnknownType&version=3.0.0
-62ad94c2-b558-4265-a427-23d6677975d6,PYCSW_SERVER?config=tests/suites/csw30/default.cfg&mode=opensearch&service=CSW&version=3.0.0&request=GetRecords&elementsetname=full&typenames=csw:Record&resulttype=results&q=&bbox=&time=/&outputformat=application/atom%2Bxml&startposition=1&maxrecords=&recordids=uid-bc5017e6-5cc8-4b03-aee7-d88f88caba0a
-6a5e247b-0961-4b8a-a0d6-35a491d9cfe7,PYCSW_SERVER?config=tests/suites/csw30/default.cfg&elementSetName=undefined-view&request=GetRecords&service=CSW&typeNames=Record&version=3.0.0
-6a9d0558-9d87-495b-b999-b49a3ef1cf99,PYCSW_SERVER?config=tests/suites/csw30/default.cfg
-6bd790c9-6019-4652-9c91-330a894d6700,PYCSW_SERVER?config=tests/suites/csw30/default.cfg&service=CSW&version=3.0.0&request=GetRecords&elementsetname=full&typenames=csw:Record&resulttype=results&q=Fusc%C3%A9%20Land&bbox=&time=/&outputformat=application/xml&outputschema=http://www.opengis.net/cat/csw/3.0&startposition=1&maxrecords=&recordids=
-6e9cba43-5e27-415d-adbd-a92851c2c173,PYCSW_SERVER?config=tests/suites/csw30/default.cfg&acceptVersions=3.0.0&request=GetCapabilities&service=CSW
-7630d230-e142-4a09-accf-f091000b90cd,PYCSW_SERVER?config=tests/suites/csw30/default.cfg&id=urn:uuid:66ae76b7-54ba-489b-a582-0f0633d96493&request=GetRecordById&service=CSW&version=3.0.0
-7e82446a-b5dc-43fe-9a73-4cc1f2f2f0bf,PYCSW_SERVER?config=tests/suites/csw30/default.cfg&acceptFormats=text/xml&acceptVersions=3.0.0&request=GetCapabilities&service=CSW
-8025978e-1a35-4d70-80c2-e8329e0c7864,PYCSW_SERVER?config=tests/suites/csw30/default.cfg
-8184ae4f-536d-4978-8b28-ad703be96967,PYCSW_SERVER?config=tests/suites/csw30/default.cfg&elementSetName=brief&bbox=44.79,-6.17,68.41,17.92,urn:ogc:def:crs:EPSG::4326&request=GetRecords&service=CSW&typeNames=Record&version=3.0.0
-88f63a89-664f-4315-b4f8-04a0b33803a7,PYCSW_SERVER?config=tests/suites/csw30/default.cfg&maxRecords=15&elementSetName=summary&q=Mauris&bbox=-6.17,44.79,17.92,68.41&request=GetRecords&service=CSW&typeNames=Record&version=3.0.0
-8987f8f0-4d93-4481-968c-a2ccbd6b8be2,PYCSW_SERVER?config=tests/suites/csw30/default.cfg&id=urn:example:1461546298217&request=GetRecordById&service=CSW&version=3.0.0
-8e5fa0f6-3f29-4d1f-abe2-d9866f3def98,PYCSW_SERVER?config=tests/suites/csw30/default.cfg&mode=opensearch&service=CSW&version=3.0.0&request=GetRecords&elementsetname=full&typenames=csw:Record&resulttype=results&q=&bbox=-180,-90,180,90&time=/&outputformat=application/atom%2Bxml&startposition=1&maxrecords=&recordids=
-9000ec29-5649-474e-b2d6-55c00f8a52c0,PYCSW_SERVER?config=tests/suites/csw30/default.cfg&acceptVersions=9999.12.31&request=GetCapabilities&service=CSW
-91914d35-7bbf-45e6-9b37-5ef484869a4e,PYCSW_SERVER?config=tests/suites/csw30/default.cfg&elementSetName=summary&bbox=-6.17,44.79,17.92,68.41&request=GetRecords&service=CSW&typeNames=Record&version=3.0.0
-92d4844d-57d5-4cf3-8f47-ba50e369dc04,PYCSW_SERVER?config=tests/suites/csw30/default.cfg&elementSetName=full&q=atkovxqmf&request=GetRecords&service=CSW&typeNames=Record&version=3.0.0
-9c0e2a4b-b4e6-41c0-b630-c8c99fc89ff3,PYCSW_SERVER?config=tests/suites/csw30/default.cfg&elementSetName=brief&outputSchema=urn:uuid:6a29d2a8-9651-47a6-9b14-f05d2b5644f0&request=GetRecords&service=CSW&typeNames=Record&version=3.0.0
-9d7ffac8-9798-428d-8e27-3cd12497ee6b,PYCSW_SERVER?config=tests/suites/csw30/default.cfg&id=urn:uuid:1ef30a8b-876d-4828-9246-c37ab4510bbd&outputSchema=http://www.example.org/ns/alpha&request=GetRecordById&service=CSW&version=3.0.0
-a2f18643-e24e-4fa5-b780-6de4a2dbc814,PYCSW_SERVER?config=tests/suites/csw30/default.cfg&id=urn:uuid:829babb0-b2f1-49e1-8cd5-7b489fe71a1e&outputFormat=application/atom%2Bxml&request=GetRecordById&service=CSW&version=3.0.0
-abc90c8c-5868-4405-a73e-64c849be3b2a,PYCSW_SERVER?config=tests/suites/csw30/default.cfg&mode=opensearch&service=CSW&version=3.0.0&request=GetRecords&elementsetname=full&typenames=csw:Record&resulttype=results&q=&bbox=514432,5429689,529130,5451619&time=/&outputformat=application/atom%2Bxml&startposition=1&maxrecords=&recordids=
-ad0c0571-09ed-436a-9a4f-a5de744c88fe,PYCSW_SERVER?config=tests/suites/csw30/default.cfg&maxRecords=2&elementSetName=summary&request=GetRecords&service=CSW&typeNames=csw3:Record&startPosition=3&namespace=xmlns(csw3%3Dhttp://www.opengis.net/cat/csw/3.0)&version=3.0.0
-af502903-f4ee-47ee-b76e-af878d238bcc,PYCSW_SERVER?config=tests/suites/csw30/default.cfg&service=CSW&version=3.0.0&request=GetRecords&elementsetname=full&typenames=csw:Record&resulttype=results&q=&bbox=-180,-90,180,90&time=/&outputformat=application/xml&outputschema=http://www.opengis.net/cat/csw/3.0&startposition=1&maxrecords=&recordids=
-b2aafc3f-4f35-47bc-affd-08590972deae,PYCSW_SERVER?config=tests/suites/csw30/default.cfg&mode=opensearch&service=CSW&version=3.0.0&request=GetRecords&elementsetname=full&typenames=csw:Record&resulttype=results&q=&bbox=-6.17,44.79,17.92,68.41&time=/&outputformat=application/atom%2Bxml&startposition=1&maxrecords=&recordids=
-b6069623-f7d8-4021-8582-98f0aea0f763,PYCSW_SERVER?config=tests/suites/csw30/default.cfg&mode=opensearch&service=CSW&version=3.0.0&request=GetRecords&elementsetname=full&typenames=csw:Record&resulttype=results&q=&bbox=&time=/&outputformat=application/atom%2Bxml&startposition=3&maxrecords=4&recordids=
-b9a07a54-75a8-45bd-b341-2823600211e3,PYCSW_SERVER?config=tests/suites/csw30/default.cfg&elementSetName=brief&bbox=472944,5363287,492722,5455253,urn:ogc:def:crs:EPSG::0000&request=GetRecords&service=CSW&typeNames=Record&version=3.0.0
-baa4a7d0-0c01-42b6-adc3-0d03e9949fa3,PYCSW_SERVER?config=tests/suites/csw30/default.cfg&acceptVersions=3.0.0&request=getCapabilities&service=CSW
-bfbe6409-f64a-4c89-acb3-50f260a5c743,PYCSW_SERVER?config=tests/suites/csw30/default.cfg&elementSetName=summary&q=Fusc%C3%A9%20Land&request=GetRecords&service=CSW&typeNames=Record&version=3.0.0
-bfe20134-d1da-42ef-9c0f-8e1307bbf92b,PYCSW_SERVER?config=tests/suites/csw30/default.cfg&service=CSW&version=3.0.0&request=GetRecords&elementsetname=full&typenames=csw:Record&resulttype=results&q=&bbox=&time=/&outputformat=application/xml&outputschema=http://www.opengis.net/cat/csw/3.0&startposition=3&maxrecords=4&recordids=
-c03d173a-3f42-4956-89c8-1fe02c3a0873,PYCSW_SERVER?config=tests/suites/csw30/default.cfg&SERVICE=CSW&Request=GetCapabilities&acceptversions=3.0.0
-cb43d8c3-e14c-4a9f-9231-4384b7dd21f3,PYCSW_SERVER?config=tests/suites/csw30/default.cfg&elementName=undefined&request=GetRecords&service=CSW&typeNames=Record&version=3.0.0
-d03c6fd3-e821-4a26-b62f-d20a474e25af,PYCSW_SERVER?config=tests/suites/csw30/default.cfg&acceptVersions=3.0.0&sections=ServiceProvider&request=GetCapabilities&service=CSW
-d4ccbf96-a529-480e-a53d-5b88dc1dea7f,PYCSW_SERVER?config=tests/suites/csw30/default.cfg&service=CSW&version=3.0.0&request=GetRecords&elementsetname=full&typenames=csw:Record&resulttype=results&q=&bbox=&time=/&outputformat=application/xml&outputschema=http://www.opengis.net/cat/csw/3.0&startposition=1&maxrecords=&recordids=uid-bc5017e6-5cc8-4b03-aee7-d88f88caba0a
-d94c801a-1207-4897-b84a-53f3a192515b,PYCSW_SERVER?config=tests/suites/csw30/default.cfg&service=CSW&version=3.0.0&request=GetRecords&elementsetname=full&typenames=csw:Record&resulttype=results&q=lpppclq&bbox=&time=/&outputformat=application/xml&outputschema=http://www.opengis.net/cat/csw/3.0&startposition=1&maxrecords=&recordids=
-da859e34-91fc-495a-8c09-285a40c0900b,PYCSW_SERVER?config=tests/suites/csw30/default.cfg&id=urn:uuid:94bc9c83-97f6-4b40-9eb8-a8e8787a5c63&elementSetName=full&request=GetRecordById&service=CSW&version=3.0.0
-dc246fb8-5af5-4fda-82bb-c18b3ecd439c,PYCSW_SERVER?config=tests/suites/csw30/default.cfg&mode=opensearch&service=CSW&version=3.0.0&request=GetRecords&elementsetname=full&typenames=csw:Record&resulttype=results&q=ipsum&bbox=&time=/&outputformat=application/atom%2Bxml&startposition=1&maxrecords=&recordids=
-de016645-6d5c-4855-943c-2db07ae9f49a,PYCSW_SERVER?config=tests/suites/csw30/default.cfg&mode=opensearch&service=CSW&version=3.0.0&request=GetRecords&elementsetname=full&typenames=csw:Record&resulttype=results&q=&bbox=&time=/&outputformat=application/atom%2Bxml&startposition=1&maxrecords=&recordids=urn%3Auuid%3A94bc9c83-97f6-4b40-9eb8-a8e8787a5c63
-dff3ec6b-bb2d-4887-bd17-8fcf15def042,PYCSW_SERVER?config=tests/suites/csw30/default.cfg&elementSetName=summary&request=GetRecords&service=CSW&typeNames=Record&version=3.0.0
-e38e6bfb-8ac4-4ae4-8b87-0aafbc8d3c6b,PYCSW_SERVER?config=tests/suites/csw30/default.cfg&id=urn:uuid:1ef30a8b-876d-4828-9246-c37ab4510bbd&elementSetName=brief&request=GetRecordById&service=CSW&version=3.0.0
-e67ca935-d65d-4d8c-8302-1405333dded0,PYCSW_SERVER?config=tests/suites/csw30/default.cfg
-e7704509-3441-458f-8ef0-e333c6b6043f,PYCSW_SERVER?config=tests/suites/csw30/default.cfg&elementName=ns1:subject&elementSetName=brief&request=GetRecords&service=CSW&typeNames=Record&namespace=xmlns(ns1%3Dhttp://purl.org/dc/elements/1.1/)&version=3.0.0
-f1223a49-6d08-44ff-97fe-4c32cbbfad82,PYCSW_SERVER?config=tests/suites/csw30/default.cfg&elementSetName=summary&maxRecords=0&q=titles&request=GetRecords&service=CSW&typeNames=Record&version=3.0.0
-f89dd4e1-3a81-4433-afd2-a3fa1bdb1e18,PYCSW_SERVER?config=tests/suites/csw30/default.cfg&elementSetName=full&outputFormat=text/example&request=GetRecords&service=CSW&typeNames=Record&version=3.0.0
diff --git a/tests/suites/default/get/requests.txt b/tests/suites/default/get/requests.txt
deleted file mode 100644
index ee36867..0000000
--- a/tests/suites/default/get/requests.txt
+++ /dev/null
@@ -1,20 +0,0 @@
-GetCapabilities,PYCSW_SERVER?config=tests/suites/default/default.cfg&service=CSW&version=2.0.2&request=GetCapabilities
-GetCapabilities-invalid-request,PYCSW_SERVER?config=tests/suites/default/default.cfg&service=CSW&version=2.0.2&request=GetCapabilitiese
-GetRecords-all,PYCSW_SERVER?config=tests/suites/default/default.cfg&service=CSW&version=2.0.2&request=GetRecords&typenames=csw:Record&elementsetname=full
-GetRecords-sortby-asc,PYCSW_SERVER?config=tests/suites/default/default.cfg&service=CSW&version=2.0.2&request=GetRecords&typenames=csw:Record&elementsetname=full&resulttype=results&sortby=dc:title:A
-GetRecords-sortby-desc,PYCSW_SERVER?config=tests/suites/default/default.cfg&service=CSW&version=2.0.2&request=GetRecords&typenames=csw:Record&elementsetname=full&resulttype=results&sortby=dc:title:D
-GetRecords-sortby-invalid-propertyname,PYCSW_SERVER?config=tests/suites/default/default.cfg&service=CSW&version=2.0.2&request=GetRecords&typenames=csw:Record&elementsetname=full&resulttype=results&sortby=dc:titlei:A
-GetRecords-sortby-invalid-order,PYCSW_SERVER?config=tests/suites/default/default.cfg&service=CSW&version=2.0.2&request=GetRecords&typenames=csw:Record&elementsetname=full&resulttype=results&sortby=dc:title:FOO
-GetRecords-filter,PYCSW_SERVER?config=tests/suites/default/default.cfg&service=CSW&version=2.0.2&request=GetRecords&typenames=csw:Record&elementsetname=full&resulttype=results&constraintlanguage=FILTER&constraint=%3Cogc%3AFilter%20xmlns%3Aogc%3D%22http%3A%2F%2Fwww.opengis.net%2Fogc%22%3E%3Cogc%3APropertyIsEqualTo%3E%3Cogc%3APropertyName%3Edc%3Atitle%3C%2Fogc%3APropertyName%3E%3Cogc%3ALiteral%3ELorem%20ipsum%3C%2Fogc%3ALiteral%3E%3C%2Fogc%3APropertyIsEqualTo%3E%3C%2Fogc%3AFilter%3E
-GetRecords-filter-cql-title,PYCSW_SERVER?config=tests/suites/default/default.cfg&service=CSW&version=2.0.2&request=GetRecords&typenames=csw:Record&elementsetname=full&resulttype=results&constraintlanguage=CQL_TEXT&constraint=dc%3Atitle%20like%20%27%25lor%25%27
-GetRecords-filter-cql-title-with-spaces,PYCSW_SERVER?config=tests/suites/default/default.cfg&service=CSW&version=2.0.2&request=GetRecords&typenames=csw:Record&elementsetname=full&resulttype=results&constraintlanguage=CQL_TEXT&constraint=dc%3Atitle%20like%20%27%25Lorem%20ipsum%25%27
-GetRecords-filter-cql-title-or-abstract,PYCSW_SERVER?config=tests/suites/default/default.cfg&service=CSW&version=2.0.2&request=GetRecords&typenames=csw:Record&elementsetname=full&resulttype=results&constraintlanguage=CQL_TEXT&constraint=dc%3Atitle%20like%20%27%25lor%25%27%20or%20dct%3Aabstract%20like%20%27%25pharetra%25%27
-GetRecords-filter-cql-title-with-spaces-or-abstract,PYCSW_SERVER?config=tests/suites/default/default.cfg&service=CSW&version=2.0.2&request=GetRecords&typenames=csw:Record&elementsetname=full&resulttype=results&constraintlanguage=CQL_TEXT&constraint=dc%3Atitle%20like%20%27%25dolor%20sit%25%27%20or%20dct%3Aabstract%20like%20%27%25pharetra%25%27
-GetRecords-filter-cql-title-or-abstract-with-spaces,PYCSW_SERVER?config=tests/suites/default/default.cfg&service=CSW&version=2.0.2&request=GetRecords&typenames=csw:Record&elementsetname=full&resulttype=results&constraintlanguage=CQL_TEXT&constraint=dc%3Atitle%20like%20%27%25lor%25%27%20or%20dct%3Aabstract%20like%20%27%25pharetra%20in%25%27
-GetRecords-filter-cql-title-with-spaces-or-abstract-with-spaces,PYCSW_SERVER?config=tests/suites/default/default.cfg&service=CSW&version=2.0.2&request=GetRecords&typenames=csw:Record&elementsetname=full&resulttype=results&constraintlanguage=CQL_TEXT&constraint=dc%3Atitle%20like%20%27%25dolor%20sit%25%27%20or%20dct%3Aabstract%20like%20%27%25pharetra%20in%25%27
-GetRecords-empty-maxrecords,PYCSW_SERVER?config=tests/suites/default/default.cfg&service=CSW&version=2.0.2&request=GetRecords&typenames=csw:Record&elementsetname=full&maxrecords=
-GetRepositoryItem,PYCSW_SERVER?config=tests/suites/default/default.cfg&service=CSW&version=2.0.2&request=GetRepositoryItem&id=urn:uuid:94bc9c83-97f6-4b40-9eb8-a8e8787a5c63
-Exception-GetRepositoryItem-notfound,PYCSW_SERVER?config=tests/suites/default/default.cfg&service=CSW&version=2.0.2&request=GetRepositoryItem&id=NOTFOUND
-Exception-GetRepositoryItem-service-invalid1,PYCSW_SERVER?config=tests/suites/default/default.cfg&service=CSW%00&version=2.0.2&request=GetRepositoryItem&id=123
-Exception-GetRepositoryItem-service-invalid2,PYCSW_SERVER?config=tests/suites/default/default.cfg&service=CSW%00'&version=2.0.2&request=GetRepositoryItem&id=123
-Exception-GetRepositoryItem-version-invalid,PYCSW_SERVER?config=tests/suites/default/default.cfg&service=CSW&version=2.0.2'&request=GetRepositoryItem&id=123
diff --git a/tests/suites/harvesting/data/.gitkeep b/tests/suites/harvesting/data/.gitkeep
deleted file mode 100644
index e69de29..0000000
diff --git a/tests/suites/manager/data/.gitkeep b/tests/suites/manager/data/.gitkeep
deleted file mode 100644
index e69de29..0000000
diff --git a/tests/suites/oaipmh/get/requests.txt b/tests/suites/oaipmh/get/requests.txt
deleted file mode 100644
index e9f859c..0000000
--- a/tests/suites/oaipmh/get/requests.txt
+++ /dev/null
@@ -1,20 +0,0 @@
-empty,PYCSW_SERVER?config=tests/suites/oaipmh/default.cfg&mode=oaipmh
-empty_with_amp,PYCSW_SERVER?config=tests/suites/oaipmh/default.cfg&mode=oaipmh&
-bad_verb,PYCSW_SERVER?config=tests/suites/oaipmh/default.cfg&mode=oaipmh&verb=foo
-illegal_verb,PYCSW_SERVER?config=tests/suites/oaipmh/default.cfg&mode=oaipmh&verb=foo&foo=bar
-Identify,PYCSW_SERVER?config=tests/suites/oaipmh/default.cfg&mode=oaipmh&verb=Identify
-ListSets,PYCSW_SERVER?config=tests/suites/oaipmh/default.cfg&mode=oaipmh&verb=ListSets
-ListMetadataFormats,PYCSW_SERVER?config=tests/suites/oaipmh/default.cfg&mode=oaipmh&verb=ListMetadataFormats
-GetRecord_dc,PYCSW_SERVER?config=tests/suites/oaipmh/default.cfg&mode=oaipmh&verb=GetRecord&identifier=urn:uuid:19887a8a-f6b0-4a63-ae56-7fba0e17801f&metadataPrefix=csw-record
-GetRecord_bad_metadata_prefix,PYCSW_SERVER?config=tests/suites/oaipmh/default.cfg&mode=oaipmh&verb=GetRecord&identifier=urn:uuid:19887a8a-f6b0-4a63-ae56-7fba0e17801f&metadataPrefix=csw-recordd
-GetRecord_oai_dc,PYCSW_SERVER?config=tests/suites/oaipmh/default.cfg&mode=oaipmh&verb=GetRecord&identifier=urn:uuid:19887a8a-f6b0-4a63-ae56-7fba0e17801f&metadataPrefix=oai_dc
-GetRecord_iso,PYCSW_SERVER?config=tests/suites/oaipmh/default.cfg&mode=oaipmh&verb=GetRecord&identifier=urn:uuid:19887a8a-f6b0-4a63-ae56-7fba0e17801f&metadataPrefix=iso19139
-ListIdentifiers_missing_metadata_prefix,PYCSW_SERVER?config=tests/suites/oaipmh/default.cfg&mode=oaipmh&verb=ListIdentifiers
-ListIdentifiers_dc,PYCSW_SERVER?config=tests/suites/oaipmh/default.cfg&mode=oaipmh&verb=ListIdentifiers&metadataPrefix=csw-record
-ListIdentifiers_iso,PYCSW_SERVER?config=tests/suites/oaipmh/default.cfg&mode=oaipmh&verb=ListIdentifiers&metadataPrefix=iso19139
-ListIdentifiers_oai_dc,PYCSW_SERVER?config=tests/suites/oaipmh/default.cfg&mode=oaipmh&verb=ListIdentifiers&metadataPrefix=oai_dc
-ListIdentifiers_bad_metadata_prefix,PYCSW_SERVER?config=tests/suites/oaipmh/default.cfg&mode=oaipmh&verb=ListIdentifiers&metadataPrefix=foo
-ListRecords_dc,PYCSW_SERVER?config=tests/suites/oaipmh/default.cfg&mode=oaipmh&verb=ListRecords&metadataPrefix=csw-record
-ListRecords_dc_bad_metadata_prefix,PYCSW_SERVER?config=tests/suites/oaipmh/default.cfg&mode=oaipmh&verb=ListRecords&metadataPrefix=csw-recording
-ListRecords_oai_dc,PYCSW_SERVER?config=tests/suites/oaipmh/default.cfg&mode=oaipmh&verb=ListRecords&metadataPrefix=oai_dc
-ListRecords_iso19139,PYCSW_SERVER?config=tests/suites/oaipmh/default.cfg&mode=oaipmh&verb=ListRecords&metadataPrefix=iso19139
diff --git a/tests/suites/sru/get/requests.txt b/tests/suites/sru/get/requests.txt
deleted file mode 100644
index 24170ae..0000000
--- a/tests/suites/sru/get/requests.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-explain,PYCSW_SERVER?config=tests/suites/sru/default.cfg&mode=sru
-search,PYCSW_SERVER?config=tests/suites/sru/default.cfg&mode=sru&version=1.1&operation=searchRetrieve&query=lor
-search_maxrecords,PYCSW_SERVER?config=tests/suites/sru/default.cfg&mode=sru&operation=searchRetrieve&query=lor&maximumRecords=2
-search_startrecord_maxrecords,PYCSW_SERVER?config=tests/suites/sru/default.cfg&mode=sru&operation=searchRetrieve&query=lor&maximumRecords=2&startRecord=1
-search_cql,PYCSW_SERVER?config=tests/suites/sru/default.cfg&mode=sru&operation=searchRetrieve&query=dc:title%20like%20'%lor%'&maximumRecords=5
diff --git a/tests/unittests/test_fmt_json.py b/tests/unittests/test_fmt_json.py
new file mode 100644
index 0000000..723424e
--- /dev/null
+++ b/tests/unittests/test_fmt_json.py
@@ -0,0 +1,93 @@
+# -*- coding: utf-8 -*-
+# =================================================================
+#
+# Authors: Ricardo Garcia Silva <ricardo.garcia.silva at gmail.com>
+#
+# Copyright (c) 2017 Ricardo Garcia Silva
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation
+# files (the "Software"), to deal in the Software without
+# restriction, including without limitation the rights to use,
+# copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following
+# conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+#
+# =================================================================
+"""Unit tests for pycsw.core.formats.fmt_json"""
+
+import pytest
+
+from pycsw.core.formats import fmt_json
+
+pytestmark = pytest.mark.unit
+
+
+def test_xml2dict():
+    identifier = "ac522ef2-89a6-11db-91b1-7eea55d89593"
+    xml = """
+        <?xml version="1.0" encoding="UTF-8"?>
+        <GetRecordsResponse
+           xmlns="http://www.opengis.net/cat/csw/3.0"
+           xmlns:csw="http://www.opengis.net/cat/csw/3.0"
+           xmlns:ows="http://www.opengis.net/ows/2.0"
+           xmlns:xsi="http://www.w3.org/2001/xmlschema-instance"
+           xsi:schemalocation="http://www.opengis.net/cat/csw/3.0
+                               http://schemas.opengis.net/cat/csw/3.0/cswall.xsd">
+           <RequestId>http://www.altova.com</RequestId>
+           <SearchStatus timestamp="2009-12-17T09:30:47-05:00"/>
+           <SearchResults resultSetId="someId" elementSet="summary"
+              recordSchema="http://www.opengis.net/cat/csw/3.0"
+              numberOfRecordsMatched="1" numberOfRecordsReturned="1" nextRecord="1">
+              <csw:Record xmlns:dc="http://purl.org/dc/elements/1.1/"
+                 xmlns:dct="http://purl.org/dc/terms/"
+                 xmlns:ows="http://www.opengis.net/ows/2.0">
+                 <dc:creator>U.S. Geological Survey</dc:creator>
+                 <dc:contributor>State of Texas</dc:contributor>
+                 <dc:publisher>U.S. Geological Survey</dc:publisher>
+                 <dc:subject>Elevation, Hypsography, and Contours</dc:subject>
+                 <dc:subject>elevation</dc:subject>
+                 <dct:abstract>Elevation data.</dct:abstract>
+                 <dc:identifier>{identifier}</dc:identifier>
+                 <dc:relation>OfferedBy</dc:relation>
+                 <dc:source>dd1b2ce7-0722-4642-8cd4-6f885f132777</dc:source>
+                 <dc:rights>Copyright © 2004, State of Texas</dc:rights>
+                 <dc:type>Service</dc:type>
+                 <dc:title>National Elevation Mapping Service for Texas</dc:title>
+                 <dct:modified>2004-03-01</dct:modified>
+                 <dc:language>en</dc:language>
+                 <ows:BoundingBox>
+                    <ows:LowerCorner>-108.44 28.229</ows:LowerCorner>
+                    <ows:UpperCorner>-96.223 34.353</ows:UpperCorner>
+                 </ows:BoundingBox>
+                 <csw:TemporalExtent>
+                    <csw:begin>2001-12-01T09:30:47Z</csw:begin>
+                    <csw:end>2001-12-17T09:30:47Z</csw:end>
+                 </csw:TemporalExtent>
+              </csw:Record>
+           </SearchResults>
+        </GetRecordsResponse>
+    """.strip().format(identifier=identifier)
+    namespaces = {
+        "csw": "http://www.opengis.net/cat/csw/3.0",
+        "ows": "http://www.opengis.net/ows/2.0",
+        "xsi": "http://www.w3.org/2001/xmlschema-instance",
+        "dc": "http://purl.org/dc/elements/1.1/",
+        "dct":"http://purl.org/dc/terms/",
+    }
+    result = fmt_json.xml2dict(xml_string=xml, namespaces=namespaces)
+    assert result["csw:GetRecordsResponse"]["csw:SearchResults"][
+        "csw:Record"]["dc:identifier"] == identifier
diff --git a/pycsw/core/formats/fmt_json.py b/tests/unittests/test_metadata.py
similarity index 61%
copy from pycsw/core/formats/fmt_json.py
copy to tests/unittests/test_metadata.py
index ded6ac6..20a25a8 100644
--- a/pycsw/core/formats/fmt_json.py
+++ b/tests/unittests/test_metadata.py
@@ -1,9 +1,8 @@
-# -*- coding: utf-8 -*-
 # =================================================================
 #
-# Authors: Tom Kralidis <tomkralidis at gmail.com>
+# Authors: Ricardo Garcia Silva <ricardo.garcia.silva at gmail.com>
 #
-# Copyright (c) 2015 Tom Kralidis
+# Copyright (c) 2017 Ricardo Garcia Silva
 #
 # Permission is hereby granted, free of charge, to any person
 # obtaining a copy of this software and associated documentation
@@ -27,18 +26,30 @@
 # OTHER DEALINGS IN THE SOFTWARE.
 #
 # =================================================================
+"""Unit tests for pycsw.core.metadata"""
 
-import json
-from pycsw.core.util import xml2dict
+import pytest
 
+from pycsw.core import metadata
 
-def xml2json(xml_string, namespaces, pretty_print=False):
-    """Convert an xml string to JSON"""
+pytestmark = pytest.mark.unit
 
-    separators = (',', ': ')
 
-    if pretty_print:
-        return json.dumps(xml2dict(xml_string, namespaces),
-                          indent=4, separators=separators)
+ at pytest.mark.parametrize("bboxes, expected", [
+    (
+        [
+            "POLYGON ((0 0, 0 1, 1 1, 1 0, 0 0))",
+            "POLYGON ((2 2, 2 3, 3 3, 3 2, 2 2))",
+        ],
+        "POLYGON((0.00 0.00, 0.00 3.00, 3.00 3.00, 3.00 0.00, 0.00 0.00))"
+    ),
+])
+def test_bbox_from_polygons(bboxes, expected):
+    result = metadata.bbox_from_polygons(bboxes)
+    assert result == expected
 
-    return json.dumps(xml2dict(xml_string, namespaces), separators=separators)
+
+def test_bbox_from_polygons_invalid():
+    bboxes = "stuff"
+    with pytest.raises(RuntimeError):
+        metadata.bbox_from_polygons(bboxes)
diff --git a/pycsw/plugins/repository/geonode/__init__.py b/tests/unittests/test_ogc_csw_csw3.py
similarity index 73%
rename from pycsw/plugins/repository/geonode/__init__.py
rename to tests/unittests/test_ogc_csw_csw3.py
index 08a4c3d..a0cf6b0 100644
--- a/pycsw/plugins/repository/geonode/__init__.py
+++ b/tests/unittests/test_ogc_csw_csw3.py
@@ -1,9 +1,8 @@
-# -*- coding: utf-8 -*-
 # =================================================================
 #
-# Authors: Tom Kralidis <tomkralidis at gmail.com>
+# Authors: Ricardo Garcia Silva <ricardo.garcia.silva at gmail.com>
 #
-# Copyright (c) 2015 Tom Kralidis
+# Copyright (c) 2017 Ricardo Garcia Silva
 #
 # Permission is hereby granted, free of charge, to any person
 # obtaining a copy of this software and associated documentation
@@ -27,3 +26,19 @@
 # OTHER DEALINGS IN THE SOFTWARE.
 #
 # =================================================================
+"""Unit tests for pycsw.ogc.csw.csw3"""
+
+import pytest
+
+from pycsw.ogc.csw import csw3
+
+pytestmark = pytest.mark.unit
+
+
+ at pytest.mark.parametrize("begin, end, expected", [
+    (0, 1, 1000),
+    (3, 8, 5000),
+])
+def test_get_elapsed_time(begin, end, expected):
+    result = csw3.get_elapsed_time(begin, end)
+    assert result == expected
diff --git a/pycsw/core/formats/fmt_json.py b/tests/unittests/test_opensearch.py
similarity index 54%
copy from pycsw/core/formats/fmt_json.py
copy to tests/unittests/test_opensearch.py
index ded6ac6..bfa7f85 100644
--- a/pycsw/core/formats/fmt_json.py
+++ b/tests/unittests/test_opensearch.py
@@ -1,9 +1,8 @@
-# -*- coding: utf-8 -*-
 # =================================================================
 #
-# Authors: Tom Kralidis <tomkralidis at gmail.com>
+# Authors: Ricardo Garcia Silva <ricardo.garcia.silva at gmail.com>
 #
-# Copyright (c) 2015 Tom Kralidis
+# Copyright (c) 2017 Ricardo Garcia Silva
 #
 # Permission is hereby granted, free of charge, to any person
 # obtaining a copy of this software and associated documentation
@@ -27,18 +26,36 @@
 # OTHER DEALINGS IN THE SOFTWARE.
 #
 # =================================================================
+"""Unit tests for pycsw.opensearch"""
 
-import json
-from pycsw.core.util import xml2dict
+import pytest
 
+from pycsw import opensearch
 
-def xml2json(xml_string, namespaces, pretty_print=False):
-    """Convert an xml string to JSON"""
+pytestmark = pytest.mark.unit
 
-    separators = (',', ': ')
 
-    if pretty_print:
-        return json.dumps(xml2dict(xml_string, namespaces),
-                          indent=4, separators=separators)
-
-    return json.dumps(xml2dict(xml_string, namespaces), separators=separators)
+ at pytest.mark.parametrize("bbox, expected", [
+    ([10, 30, -10, -30], True),
+    ([10.0, 30.0, -10.0, -30.0], True),
+    (["10", "30", "-10", "-30"], True),
+    ([-180, 30, -10, -30], True),
+    ([180, 30, -10, -30], True),
+    ([0, -90, -10, -30], True),
+    ([0, 90, -10, -30], True),
+    ([10, 30, -180, -30], True),
+    ([10, 30, 180, -30], True),
+    ([10, 30, -10, -90], True),
+    ([10, 30, -10, 90], True),
+    ([-190, 30, -10, -30], False),
+    ([190, 30, -10, -30], False),
+    ([10, 100, -10, -30], False),
+    ([10, -100, -10, -30], False),
+    ([10, 30, -190, -30], False),
+    ([10, 30, 190, -30], False),
+    ([10, 30, -10, -190], False),
+    ([10, 30, -10, 190], False),
+])
+def test_validate_4326(bbox, expected):
+    result = opensearch.validate_4326(bbox)
+    assert result == expected
\ No newline at end of file
diff --git a/tests/unittests/test_repository.py b/tests/unittests/test_repository.py
new file mode 100644
index 0000000..6b00221
--- /dev/null
+++ b/tests/unittests/test_repository.py
@@ -0,0 +1,66 @@
+# =================================================================
+#
+# Authors: Ricardo Garcia Silva <ricardo.garcia.silva at gmail.com>
+#
+# Copyright (c) 2017 Ricardo Garcia Silva
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation
+# files (the "Software"), to deal in the Software without
+# restriction, including without limitation the rights to use,
+# copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following
+# conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+#
+# =================================================================
+"""Unit tests for pycsw.core.repository"""
+
+import pytest
+
+from pycsw.core import repository
+
+pytestmark = pytest.mark.unit
+
+
+ at pytest.mark.parametrize("data, input_, predicate, distance, expected", [
+    ("LINESTRING(0 0, 1 1)", "POINT(0.5 0.5)", "bbox", 0, "true"),
+    ("LINESTRING(0 0, 1 1)", "POINT(2 2)", "bbox", 0, "false"),
+    ("LINESTRING(0 0, 1 1)", "POINT(2 2)", "beyond", 1, "true"),
+    ("LINESTRING(0 0, 1 1)", "POINT(2 2)", "beyond", 2, "false"),
+    ("LINESTRING(0 0, 1 1)", "POINT(0.5 0.5)", "beyond", "false", "false"),
+    ("LINESTRING(0 0, 1 1)", "POINT(0.5 0.5)", "contains", 0, "true"),
+    ("LINESTRING(0 0, 1 1)", "POINT(2 2)", "contains", 0, "false"),
+    ("LINESTRING(0 0, 1 1)", "LINESTRING(1 0, 0 1)", "crosses", 0, "true"),
+    ("LINESTRING(0 0, 1 1)", "POINT(0.5 0.5)", "crosses", 0, "false"),
+    ("POINT(1 1)", "POINT(1 1)", "equals", 0, "true"),
+    ("LINESTRING(0 0, 1 1)", "POINT(0.5 0.5)", "equals", 0, "false"),
+    ("LINESTRING(0 0, 1 1)", "POINT(0 0)", "touches", 0, "true"),
+    ("LINESTRING(0 0, 1 1)", "POINT(0.5 0.5)", "touches", 0, "false"),
+    ("POINT(0.5 0.5)", "LINESTRING(0 0, 1 1)", "within", 0, "true"),
+    ("LINESTRING(0 0, 1 1)", "POINT(0.5 0.5)", "within", 0, "false"),
+    (None, "POINT(0.5 0.5)", "within", 0, "false"),
+    ("POINT(0.5 0.5)", None, "within", 0, "false"),
+    (None, None, "within", 0, "false"),
+    ("LINESTRING(0 0, 1 1)", "POINT(0.5 0.5)", "dwithin", "false", "false"),
+])
+def test_query_spatial(data, input_, predicate, distance, expected):
+    result = repository.query_spatial(
+        bbox_data_wkt=data,
+        bbox_input_wkt=input_,
+        predicate=predicate,
+        distance=distance
+    )
+    assert result == expected
diff --git a/tests/unittests/test_util.py b/tests/unittests/test_util.py
new file mode 100644
index 0000000..2c48011
--- /dev/null
+++ b/tests/unittests/test_util.py
@@ -0,0 +1,252 @@
+# =================================================================
+#
+# Authors: Ricardo Garcia Silva <ricardo.garcia.silva at gmail.com>
+#
+# Copyright (c) 2017 Ricardo Garcia Silva
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation
+# files (the "Software"), to deal in the Software without
+# restriction, including without limitation the rights to use,
+# copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following
+# conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+#
+# =================================================================
+"""Unit tests for pycsw.core.util"""
+
+import datetime as dt
+import os
+import time
+
+import mock
+import pytest
+from shapely.wkt import loads
+
+from pycsw.core import util
+
+pytestmark = pytest.mark.unit
+
+
+def test_get_today_and_now():
+    fake_now = "2017-01-01T00:00:00Z"
+    with mock.patch.object(util.time, "localtime") as mock_localtime:
+        mock_localtime.return_value = time.strptime(
+            fake_now,
+            "%Y-%m-%dT%H:%M:%SZ"
+        )
+        result = util.get_today_and_now()
+        assert result == fake_now
+
+
+ at pytest.mark.parametrize("value, expected", [
+    (dt.date(2017, 1, 23), "2017-01-23"),
+    (dt.datetime(2017, 1, 23), "2017-01-23"),
+    (dt.datetime(2017, 1, 23, 20, 32, 10), "2017-01-23T20:32:10Z"),
+    (dt.datetime(2017, 1, 23, 10), "2017-01-23T10:00:00Z"),
+    (dt.datetime(2017, 1, 23, 10, 20), "2017-01-23T10:20:00Z"),
+])
+def test_datetime2iso8601(value, expected):
+    result = util.datetime2iso8601(value)
+    assert result == expected
+
+
+ at pytest.mark.parametrize("version, expected", [
+    ("2", -1),
+    ("1.2", -1),
+    ("5.4.3.2", -1),
+    ("This is a regular string, not a version", -1),
+    ("3.4.1", 30401),
+])
+def test_get_version_integer(version, expected):
+    result = util.get_version_integer(version)
+    assert result == expected
+
+
+ at pytest.mark.parametrize("invalid_version", [
+    2,
+    2.2,
+    None,
+])
+def test_get_version_integer_invalid_version(invalid_version):
+    with pytest.raises(RuntimeError):
+        util.get_version_integer(invalid_version)
+
+ at pytest.mark.parametrize("xpath_expression, expected", [
+    ("ns1:first", "{something}first"),
+    ("ns1:first/ns2:second", "{something}first/{other}second"),
+    ("ns1:first/ns2:second[1]", "{something}first/{other}second[1]"),
+    ("ns1:first/*/ns3:third", "{something}first/*/{another}third"),
+    ("", ""),
+])
+def test_nspath_eval(xpath_expression, expected):
+    nsmap = {
+        "ns1": "something",
+        "ns2": "other",
+        "ns3": "another",
+    }
+    result = util.nspath_eval(xpath_expression, nsmap)
+    assert result == expected
+
+
+def test_nspath_eval_invalid_element():
+    with pytest.raises(RuntimeError):
+        util.nspath_eval(
+            xpath="ns1:tag1/ns2:ns3:tag2",
+            nsmap={
+                "ns1": "something",
+                "ns2": "other",
+                "ns3": "another",
+            }
+        )
+
+ at pytest.mark.parametrize("envelope, expected", [
+    ("ENVELOPE (-180,180,90,-90)", "-180,-90,180,90"),
+    (" ENVELOPE(-180,180,90,-90)", "-180,-90,180,90"),
+    (" ENVELOPE( -180, 180, 90, -90) ", "-180,-90,180,90"),
+])
+def test_wktenvelope2bbox(envelope, expected):
+    result = util.wktenvelope2bbox(envelope)
+    assert result == expected
+
+# TODO - Add more WKT cases for other geometry types
+ at pytest.mark.parametrize("wkt, bounds, expected", [
+    ("POINT (10 10)", True, (10.0, 10.0, 10.0, 10.0)),
+    ("SRID=4326;POINT (10 10)", True, (10.0, 10.0, 10.0, 10.0)),
+    ("POINT (10 10)", False, loads("POINT (10 10)")),
+    ("SRID=4326;POINT (10 10)", False, loads("POINT (10 10)")),
+])
+def test_wkt2geom(wkt, bounds, expected):
+    result = util.wkt2geom(wkt, bounds=bounds)
+    assert result == expected
+
+
+ at pytest.mark.parametrize("bbox, expected", [
+    (
+        "0.0, 10.0, 30.0, 15.0",
+        "POLYGON((0.00 10.00, 0.00 15.00, 30.00 15.00, "
+        "30.00 10.00, 0.00 10.00))"
+    ),
+    (
+        "-10.0, 10.0, 30.0, 15.0",
+        "POLYGON((-10.00 10.00, -10.00 15.00, 30.00 15.00, "
+        "30.00 10.00, -10.00 10.00))"
+    ),
+])
+def test_bbox2wktpolygon(bbox, expected):
+    result = util.bbox2wktpolygon(bbox)
+    assert result == expected
+
+
+def test_transform_mappings():
+    queryables = {
+        "q1": {"xpath": "p1", "dbcol": "col1"},
+        "q2": {"xpath": "p2", "dbcol": "col2"},
+    }
+    typename = {"q2": "q1"}
+    duplicate_queryables = queryables.copy()
+    duplicate_typename = typename.copy()
+    util.transform_mappings(duplicate_queryables, duplicate_typename)
+    assert duplicate_queryables["q1"]["xpath"] == queryables["q2"]["xpath"]
+    assert duplicate_queryables["q1"]["dbcol"] == queryables["q2"]["dbcol"]
+
+
+ at pytest.mark.parametrize("name, value, expected", [
+    ("name", "john", "john"),
+    ("date", dt.date(2017, 1, 1), "2017-01-01"),
+    ("datetime", dt.datetime(2017, 1, 1, 10, 5), "2017-01-01T10:05:00Z"),
+    ("some_callable", os.getcwd, os.getcwd()),
+])
+def test_getqattr_no_link(name, value, expected):
+    class Phony(object):
+        pass
+
+    instance = Phony()
+    setattr(instance, name, value)
+    result = util.getqattr(instance, name)
+    assert result == expected
+
+
+def test_getqattr_link():
+    some_object = mock.MagicMock()
+    some_object.some_link.return_value = [
+        ["one", "two"],
+        ["three", "four"],
+    ]
+    result = util.getqattr(some_object, "some_link")
+    assert result == "one,two^three,four"
+
+
+def test_getqattr_invalid():
+        result = util.getqattr(dt.date(2017, 1, 1), "name")
+        assert result is None
+
+
+def test_http_request_post():
+    # here we replace owslib.util.http_post with a mock object
+    # because we are not interested in testing owslib
+    method = "POST"
+    url = "some_phony_url"
+    request = "some_phony_request"
+    timeout = 40
+    with mock.patch("pycsw.core.util.http_post",
+                    autospec=True) as mock_http_post:
+        util.http_request(
+            method=method,
+            url=url,
+            request=request,
+            timeout=timeout
+        )
+        mock_http_post.assert_called_with(url, request, timeout=timeout)
+
+
+ at pytest.mark.parametrize("url, expected", [
+    ("http://host/wms", "http://host/wms?"),
+    ("http://host/wms?foo=bar&", "http://host/wms?foo=bar&"),
+    ("http://host/wms?foo=bar", "http://host/wms?foo=bar&"),
+    ("http://host/wms?", "http://host/wms?"),
+    ("http://host/wms?foo", "http://host/wms?foo&"),
+])
+def test_bind_url(url, expected):
+    result = util.bind_url(url)
+    assert result == expected
+
+
+ at pytest.mark.parametrize("ip, netmask, expected", [
+    ("192.168.100.14", "192.168.100.0/24", True),
+    ("192.168.100.14", "192.168.0.0/24", False),
+    ("192.168.100.14", "192.168.0.0/16", True),
+])
+def test_ip_in_network_cidr(ip, netmask, expected):
+    result = util.ip_in_network_cidr(ip, netmask)
+    assert result == expected
+
+
+ at pytest.mark.parametrize("ip, whitelist, expected", [
+    ("192.168.100.14", [], False),
+    ("192.168.100.14", ["192.168.100.15"], False),
+    ("192.168.100.14", ["192.168.100.15", "192.168.100.14"], True),
+    ("192.168.100.14", ["192.168.100.*"], True),
+    ("192.168.100.14", ["192.168.100.15", "192.168.100.*"], True),
+    ("192.168.100.14", ["192.168.100.0/24"], True),
+    ("192.168.100.14", ["192.168.100.15", "192.168.100.0/24"], True),
+    ("192.168.10.14", ["192.168.100.15", "192.168.0.0/16"], True),
+])
+def test_ipaddress_in_whitelist(ip, whitelist, expected):
+    result = util.ipaddress_in_whitelist(ip, whitelist)
+    assert result == expected
+
+
diff --git a/tests/unittests/test_wsgi.py b/tests/unittests/test_wsgi.py
new file mode 100644
index 0000000..66aecbf
--- /dev/null
+++ b/tests/unittests/test_wsgi.py
@@ -0,0 +1,153 @@
+# =================================================================
+#
+# Authors: Ricardo Garcia Silva <ricardo.garcia.silva at gmail.com>
+#
+# Copyright (c) 2017 Ricardo Garcia Silva
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation
+# files (the "Software"), to deal in the Software without
+# restriction, including without limitation the rights to use,
+# copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following
+# conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+#
+# =================================================================
+"""Unit tests for pycsw.wsgi"""
+
+from wsgiref.util import setup_testing_defaults
+
+import mock
+import pytest
+
+from pycsw import wsgi
+
+pytestmark = pytest.mark.unit
+
+ at pytest.mark.parametrize("process_env, wsgi_env, fake_dir, expected", [
+    ({}, None, "dummy", "dummy"),
+    ({"PYCSW_ROOT": "this"}, None, "dummy", "this"),
+    ({"PYCSW_ROOT": "this"}, {"PYCSW_ROOT": "that"}, "dummy", "this"),
+    ({}, {"PYCSW_ROOT": "that"}, "dummy", "that"),
+])
+def test_get_pycsw_root_path(process_env, wsgi_env, fake_dir, expected):
+    with mock.patch("pycsw.wsgi.os", autospec=True) as mock_os:
+        mock_os.path.dirname.return_value = fake_dir
+        result = wsgi.get_pycsw_root_path(
+            process_env,
+            request_environment=wsgi_env
+        )
+        assert result == expected
+
+
+ at pytest.mark.parametrize("process_env, wsgi_env, pycsw_root, expected", [
+    ({}, {}, "dummy", "dummy/default.cfg"),
+    ({"PYCSW_CONFIG": "default.cfg"}, {}, "dummy", "default.cfg"),
+    (
+        {"PYCSW_CONFIG": "/some/abs/path/default.cfg"},
+        {},
+        "dummy",
+        "/some/abs/path/default.cfg"
+    ),
+    (
+        {"PYCSW_CONFIG": "default.cfg"},
+        {"QUERY_STRING": ""},
+        "dummy",
+        "default.cfg"
+    ),
+    (
+        {"PYCSW_CONFIG": "default.cfg"},
+        {"QUERY_STRING": "config=other.cfg"},
+        "dummy",
+        "other.cfg"
+    ),
+    (
+        {"PYCSW_CONFIG": "default.cfg"},
+        {"QUERY_STRING": "config=/other/path/other.cfg"},
+        "dummy",
+        "/other/path/other.cfg"
+    ),
+])
+def test_get_configuration_path(process_env, wsgi_env, pycsw_root, expected):
+    result = wsgi.get_configuration_path(process_env, wsgi_env, pycsw_root)
+    assert result == expected
+
+
+ at pytest.mark.parametrize("compression_level", [
+    1, 2, 3, 4, 5, 6, 7, 8, 9,
+])
+def test_compress_response(compression_level):
+    fake_response = "dummy"
+    with mock.patch("pycsw.wsgi.gzip", autospec=True) as mock_gzip:
+        compressed_response, headers = wsgi.compress_response(
+            fake_response, compression_level)
+        creation_kwargs = mock_gzip.GzipFile.call_args[1]
+        assert creation_kwargs["compresslevel"] == compression_level
+        assert headers["Content-Encoding"] == "gzip"
+
+
+def test_application_no_gzip():
+    fake_config_path = "fake_config_path"
+    fake_status = "fake_status"
+    fake_response = "fake_response"
+    fake_content_type = "fake_content_type"
+    request_env = {}
+    setup_testing_defaults(request_env)
+    mock_start_response = mock.MagicMock()
+    with mock.patch("pycsw.wsgi.server", autospec=True) as mock_server, \
+            mock.patch.object(
+                wsgi, "get_configuration_path") as mock_get_config_path:
+        mock_get_config_path.return_value = fake_config_path
+        mock_csw_class = mock_server.Csw
+        mock_pycsw = mock_csw_class.return_value
+        mock_pycsw.dispatch_wsgi.return_value = (fake_status, fake_response)
+        mock_pycsw.contenttype = fake_content_type
+        result = wsgi.application(request_env, mock_start_response)
+        mock_csw_class.assert_called_with(fake_config_path, request_env)
+        start_response_args = mock_start_response.call_args[0]
+        assert fake_status in start_response_args
+        assert result == [fake_response]
+
+
+def test_application_gzip():
+    fake_config_path = "fake_config_path"
+    fake_status = "fake_status"
+    fake_response = "fake_response"
+    fake_content_type = "fake_content_type"
+    fake_compression_level = 5
+    fake_compressed_contents = "fake compressed contents"
+    fake_compression_headers = {"phony": "dummy"}
+    request_env = {"HTTP_ACCEPT_ENCODING": "gzip"}
+    setup_testing_defaults(request_env)
+    mock_start_response = mock.MagicMock()
+    with mock.patch("pycsw.wsgi.server", autospec=True) as mock_server, \
+            mock.patch.object(
+                wsgi, "get_configuration_path") as mock_get_config_path, \
+            mock.patch.object(wsgi, "compress_response") as mock_compress:
+
+        mock_compress.return_value = (fake_compressed_contents,
+                                      fake_compression_headers)
+        mock_get_config_path.return_value = fake_config_path
+        mock_csw_class = mock_server.Csw
+        mock_pycsw = mock_csw_class.return_value
+        mock_pycsw.config = mock.MagicMock()
+        mock_pycsw.config.get.return_value = fake_compression_level
+        mock_pycsw.dispatch_wsgi.return_value = (fake_status, fake_response)
+        mock_pycsw.contenttype = fake_content_type
+        wsgi.application(request_env, mock_start_response)
+        mock_pycsw.config.get.assert_called_with("server",
+                                                 "gzip_compresslevel")
+        mock_compress.assert_called_with(fake_response, fake_compression_level)
diff --git a/tox.ini b/tox.ini
new file mode 100644
index 0000000..fb835ff
--- /dev/null
+++ b/tox.ini
@@ -0,0 +1,18 @@
+# Tox (http://tox.testrun.org/) is a tool for running tests
+# in multiple virtualenvs. This configuration file will run the
+# test suite on all supported python versions. To use it, "pip install tox"
+# and then run "tox" from this directory.
+
+[tox]
+envlist = {py27,py34,py35}-sqlite
+skip_missing_interpreters = True
+
+
+[testenv]
+deps =
+    -rrequirements-dev.txt
+usedevelop = True
+commands =
+    coverage run --parallel-mode --module pytest {posargs}
+    coverage combine --append
+    coverage report

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-grass/pycsw.git



More information about the Pkg-grass-devel mailing list