2012-02-23T12:00:00
500
GAVO RegTAP Service
ivo://ivoa.net/std/RegTAP#1.1
Tables containing the information in the IVOA Registry. To query
these tables, use `our TAP service`_.
For more information and example queries, see the
`RegTAP specification`_.
.. _our TAP service: /__system__/tap/run/info
.. _RegTAP specification: http://www.ivoa.net/documents/RegTAP/
virtual-observatories
execDef.spawnPython("bin/harvestRegistries.py")
execDef.spawn(
"dachs --ui stingy imp --suppress-meta -c rr/q"
" import make_tap_table".split())
execDef.spawnPython("bin/harvestRofR.py")
Administrative table: publishing registries we harvest, together
with the dates of last full and incremental harvests.
Administrative table: the files ingested together with the
processing date. Due to incremental harvesting, multiple files
may/will exist for a single resource.
A mapping between the registries and the authorities they
claim to manage.
common fields for tables and params. The what stream parameter
is either column or parameter, depending on where this thing goes.
1
1
1
1
1
1
1
1
1
1
The resources (like services, data collections, organizations)
present in this registry.
1
Registry 1.1
ivo://ivoa.net/std/RegTAP#1.1
xpath:/
to_tsvector('english', res_title)
to_tsvector('english', res_description)
to_tsvector('english', creator_seq)
LOWER(short_name) gin_trgm_ops
ivoid gin_trgm_ops
LOWER(ivoid) gin_trgm_ops
1
1
1
1
1
1
1
1
1
1
1
1
1
1
A single numeric value representing the angle, given in decimal
degrees, by which a positional query against this resource should be
``blurred'' in order to get an appropriate match.
1
1
A statement of usage conditions (license, attribution,
embargo, etc).
1
A URI identifying a license the data is made available
under.
1
The allowed values for waveband include:
Radio, Millimeter, Infrared, Optical, UV, EUV, X-ray, Gamma-ray.
The terms are taken from the vocabulary
http://ivoa.net/rdf/voresource/content_level.
The terms are taken from the vocabulary
http://ivoa.net/rdf/voresource/content_type.
The terms are taken from the vocabulary
http://ivoa.net/rdf/voresource/relationship_type.
Replay this in any table that represents a direct child
of resource
1
Entities (persons or organizations) operating on
resources: creators, contacts, publishers, contributors.
LOWER(role_name) gin_trgm_ops
1
1
1
1
1
1
1
Topics, object types, or other descriptive keywords
about the resource.
xpath:/content/
LOWER(res_subject) gin_trgm_ops
to_tsvector('english', res_subject)
1
res_subject mapped to the UAT. This is based on a manual
mapping of keywords found in 2020, where subjects not mappable
were dropped. This is a non-standard, local extension. Don't
base your procedures on it, we will tear it down once there is
sufficient takeup of the UAT in the VO.
xpath:/capability/
Pieces of behaviour of a resource.
2
1
1
1
1
xpath:/tableset/schema/
Sets of tables related to resources.
1
1
1
1
1
xpath:/(tableset/schema/|)table/
(Relational) tables that are part of schemata or resources.
1
1
1
1
1
A name for the role this table plays. Recognized values
include "output", indicating this table is output from a query;
"base_table", indicating a table whose records represent the
main subjects of its schema; and "view", indicating that the
table represents a useful combination or subset of other tables.
Other values are allowed.
1
1
xpath:/(tableset/schema/|)/table/column/
Metadata on columns of a resource's tables.
to_tsvector('english', column_description)
ucd gin_trgm_ops
1
1
1
An experimental table containing advanced statistics for numeric
table columns. This is only available for very few tables at
this point.
Note that the values reported here may be estimates based on a
subeset of the table rows.
XPath-value pairs for members of
resource or capability and their derivations that are less used and/or
from VOResource extensions. The pairs refer to a resource if
cap_index is NULL, to the referenced capability otherwise.
1
1
Replay this in any table that represents a direct child
of capability
xpath:/capability/interface/
Information on access modes of a capability.
1
1
1
1
1
1
1
1
1
1
1
xpath:/content/relationship/
Relationships between resources (like mirroring, derivation,
serving a data collection).
1
1
1
xpath:/capability/interface/param/
Input parameters for services.
to_tsvector('english', param_description)
1
1
Validation levels for resources
and capabilities.
xpath:/(capability/|)validationLevel
1
1
1
The validation level is an integer encoding the following semantics:
0
The resource has a description that is stored in a registry. This level
does not imply a compliant description.
1
In addition to meeting the level 0 definition, the resource
description conforms syntactically to this standard and to
the encoding scheme used.
2
In addition to meeting the level 1 definition, the resource description
refers to an existing resource that has demonstrated to be functionally
compliant.
When the resource is a service, it is considered to exist and
functionally compliant if use of the service accessURL responds without
error when used as intended by the resource. If the service is a
standard one, it must also demonstrate the response is syntactically
compliant with the service standard in order to be considered
functionally compliant. If the resource is not a service, then the
ReferenceURL must be shown to return a document without error.
3
In addition to meeting the level 2 definition, the resource description
has been inspected by a human and judged to comply semantically to this
standard as well as meeting any additional minimum quality criteria
(e.g., providing values for important but non-required metadata) set by
the human inspector.
4
In addition to meeting the level 3 definition, the resource description
meets additional quality criteria set by the human inspector and is
therefore considered an excellent description of the resource.
Consequently, the resource is expected to be operate well as part of a
VO application or research study.
A date associated with an event in the life cycle of the resource. This
could be creation or update. The role column can be used to clarify.
xpath:/curation/
1
1
The terms for a date's role should be drawn from
http://ivoa.net/rdf/voresource/date_role.
Note that this date refers to the resource itself; dates
describing the resource record are given by the created and updated
columns in the resource table.
An alternate identifier associated with this record.
This can be a resiource identifier like a DOI (in URI form,
e.g., doi:10.1016/j.epsl.2011.11.037), or a person identifier
of a creator (typically an ORCID in URI form, e.g.,
orcid:000-0000-0000-000X).
xpath:/(curation/creator/|)altIdentifier
alt_identifier gin_trgm_ops
1
Pre-rendered XML fragments for building OAI-PMH documents.
1
1
The spatial coverage of resources. This table associates
footprints (ADQL geometries) with ivoids. The footprints are
intended for resource discovery; a reasonable expectation for
the resolution thus is something like a degree.
xpath:/coverage/spatial
5
1
1
The temporal coverage of resources, given as one or more intervals.
The total coverage is (a subset of) the union of all intervals
given for a resource. All times are understood as MJD for TDB
at the solar system barycenter.
xpath:/coverage/temporal
5
1
1
The spectral coverage of resources, given as one or more intervals.
The total coverage is (a subset of) the union of all intervals
given for a resource. The spectral values are given as
messenger energy.
xpath:/coverage/spectral
5
1
1
TAP-queriable tables.
3
to_tsvector('english', table_description)
to_tsvector('english', table_title)
table_name gin_trgm_ops
1
1
CREATE MATERIALIZED VIEW \qName AS (
SELECT \colNames FROM (
WITH
fromres AS (
-- tables coming in through relationships; only those declaring
-- an auxiliary capability *and* a relationship will be considered
-- The GROUP BY and MIN hack is necessary since multiple of these
-- may declare the same table (e.g., ivoa.obscore for data collections
-- published through obscore).
SELECT
MIN(tabcap.ivoid) as resid,
related_id as svcid,
table_name,
MIN(table_title) as table_title,
MIN(table_description) as table_description,
MIN(table_utype) as table_utype
FROM rr.res_table as tab
NATURAL JOIN rr.capability as tabcap
NATURAL JOIN rr.relationship
JOIN rr.capability AS svccap
ON (svccap.ivoid=related_id)
WHERE
(table_type!='output' OR table_type IS NULL)
AND svccap.standard_id='ivo://ivoa.net/std/tap'
AND tabcap.standard_id='ivo://ivoa.net/std/tap#aux'
AND relationship_type='isservedby'
GROUP BY related_id, table_name),
fromtap AS (
-- tables directly attached to the TAP service
SELECT rt.ivoid as resid, ivoid as svcid,
table_name, table_title,
table_description, table_utype
FROM rr.res_table AS rt
NATURAL JOIN rr.capability
WHERE
(table_type!='output' OR table_type IS NULL)
AND standard_id='ivo://ivoa.net/std/tap'
AND NOT EXISTS (SELECT 1 FROM fromres as fr
WHERE rt.ivoid=fr.svcid
AND rt.table_name=fr.table_name))
-- using WITH here to allow for a lateral union
SELECT * FROM fromtap UNION ALL
SELECT * FROM fromres) q)
if False: yield
\\inputRelativePath
datetime.datetime.now()
make_tap_table
http://reg.g-vo.org/tap
http://dc.zah.uni-heidelberg.de/tap
http://gavo.aip.de/tap
http://voparis-rr.obspm.fr:80/tap
registry
true
RegTAP mirror
GAVO DC searchable registry PMH interface
GAVO DC full PMH
The OAI-PMH endpoint of the GAVO searchable registry. This service
gives access to the full content of the VO registry using the Open
Archive Initiative's protocol for metadata harvesting. Advanced
queries are possible using ADQL in the rr schema at
http://dc.g-vo.org/tap.
For the DC's publishing registry, see http://dc.g-vo.org/oai.xml.
registry
1000
true
A Name Mapping Authority Host for IVOIDs
GAVO DC IRK
A service for easy access to VOResource XML by IVOID -- just
append the IVOID to the base URL of this service.
VOResource Landing Page Generator
VOR lander
A service that turns VOResource into HTML in a way that is
supposed to work as a DataCite-style landing page, explaining
non-VO experts what access options there may be. Use it by prepending
http://dc.g-vo.org/LP to any ivoid and feeding that to your web
browser.
static
Harvest Trigger Service
Operators of publishing registries
can use this service to request a re-harvest of their registry by pasting
in their registry's IVOID below. If you paste in the magic value
``ivo://ivoa.net/rofr``, we will also fetch new registries from the
RofR.
You usually want to use this when you want to see the effect of some
change in your registry on, say, TOPCAT. Note that you cannot start
a full re-harvest of a registry from this interface. Contact the
operators if you think you need that.
harvtrig
msgs = []
regId = inputTable.args["registry"]
if regId=="ivo://ivoa.net/rofr":
harvest_rofr, _ = api.loadPythonModule(
"bin/harvestRofR", relativeTo=rd.resdir+"/dummy")
regs = harvest_rofr.getRegistryRecords()
harvest_rofr.updateRegistries(regs)
msgs.append("Read {} registries from the RofR".format(
len(regs)))
harvest_reg, _ = api.loadPythonModule(
"bin/harvestRegistries", relativeTo=rd.resdir+"/dummy")
regTD = rd.getById("registries")
with api.getWritableAdminConn() as conn:
regTable = api.TableForDef(regTD, connection=conn,
parseOptions=api.parseValidating.change(doTableUpdates=True))
context = harvest_reg.HarvestContext(regTable)
# this defeats our anti-race hack to harvest one extra
# interval in _harvestOneInc
context.incInterval = datetime.timedelta(seconds=0)
for rec in regTable.iterQuery(regTD, "ivoid=%(regId)s",
{"regId": regId.lower()}):
harvest_reg._harvestOneInc(rec, context)
msgs.append("Harvested {} incrementally".format(regId))
break
else:
return api.TableForDef(self.outputTable, rows=[
{"result": "fail", "remarks": "No matching registry"
"known here. Have me harvest the RofR first?"}])
res = api.makeData(rd.getById("import"), connection=conn)
msgs.append("Ingested {} RegTAP rows from material harvested"
.format(res.nAffected))
return api.TableForDef(self.outputTable, rows=[
{"result": "ok", "remarks": " | ".join(msgs)}])
RegTAP examples
This service has the examples from the
RegTAP spec in the form of a DALI examples document.
As the capability type is in :taptable:`rr.capability`, whereas the access URL
can be found from :taptable:`rr.interface`, this requires a (natural) join.
Clients communicating with a RegTAP 1.1 or later service should request the new
``authenticated_only`` column. If this is 1, the service requires some sort of
authentication and should only presented to users if a client has the necessary
infrastructure for the authentication system.
Hence, clients only interested in services not requiring authentication should
use
.. tapquery::
SELECT ivoid, access_url
FROM rr.capability
NATURAL JOIN rr.interface
WHERE standard_id like 'ivo://ivoa.net/std/tap%'
AND intf_role='std'
AND authenticated_only=0
Analogous considerations apply to the other example queries
Other ``standard_id``-s relevant here include:
* ``ivo://ivoa.net/std/registry`` for OAI-PMH services,
* ``ivo://ivoa.net/std/sia`` for SIA services,
* ``ivo://ivoa.net/std/conesearch`` for SCS services, and
* ``ivo://ivoa.net/std/ssa`` for SSA services.
This is somewhat tricky since it is probably hard to image a part of the sky
guaranteed not to have some, possibly distant, spiral galaxy in it. However,
translating the intention into “find all SIA services that mention spiral in
either the subject (from :taptable:`rr.res_subject`), the description, or the
title (which are in :taptable:`rr.resource`)“, the query would become:
.. tapquery::
SELECT ivoid, access_url
FROM rr.capability
NATURAL JOIN rr.resource
NATURAL JOIN rr.interface
NATURAL JOIN rr.res_subject
WHERE standard_id like 'ivo://ivoa.net/std/sia%'
AND intf_role='std'
AND (
1=ivo_nocasematch(res_subject, '%spiral%')
OR 1=ivo_hasword(res_description, 'spiral')
OR 1=ivo_hasword(res_title, 'spiral'))
The waveband information in :taptable:`rr.resource` comes in hash-separated
atoms (which can be terms from https://www.ivoa.net/rdf/messenger). For
matching those, use the ``ivo_hashlist_has`` function as below. The access URL
and the service standard come from :taptable:`rr.interface` and
:taptable:`rr.capability`, respectively.
.. tapquery::
SELECT ivoid, access_url
FROM rr.capability
NATURAL JOIN rr.resource
NATURAL JOIN rr.interface
WHERE standard_id LIKE 'ivo://ivoa.net/std/sia%'
AND intf_role='std'
AND 1=ivo_hashlist_has(waveband, 'infrared')
Metadata on columns exposed by a service are contained in
:taptable:`rr.table_column`. Again, this table can be
naturally joined with
:taptable:`rr.capability` and
:taptable:`rr.interface`.
.. tapquery::
SELECT ivoid, access_url
FROM rr.capability
NATURAL JOIN rr.table_column
NATURAL JOIN rr.interface
WHERE standard_id LIKE 'ivo://ivoa.net/std/conesearch%'
AND intf_role='std'
AND ucd='src.redshift'
Sometimes you want to match a whole set of ucds. Frequently the
simple regular expressions of SQL will help, as in
``AND ucd LIKE 'pos.parallax\%'``. When that is not enough,
use boolean OR expressions.
An “authority” within the VO is something that hands out identifiers.
You can tell what authority a record came from by looking at the “host
part” of the IVO identifier, most naturally obtained from
:taptable:`rr.resource`. Since ADQL cannot actually parse
URIs, we make do with simple string matching:
.. tapquery::
SELECT ivoid
FROM rr.resource
WHERE ivoid LIKE 'ivo://org.gavo.dc%'
This uses the :taptable:`rr.res_role` table both to match names (in this case,
a publisher that has “gavo” in its name) and to ascertain the named entity
actually publishes the resource (rather than, e.g., just being the contact in
case of trouble). The result is a list of ivoids in this case. You could join
this with any other table in the relational registry to find out more about
these services.
.. tapquery::
SELECT ivoid
FROM rr.res_role
WHERE 1=ivo_nocasematch(role_name, '%gavo%')
AND base_role='publisher'
or, if the publisher actually gives its ivo-id in the registry
records::
SELECT ivoid
FROM rr.res_role
WHERE role_ivoid='ivo://ned.ipac/ned'
AND base_role='publisher'
This is mainly a query interesting for registry maintainers. Still, it is a
nice example for joining with the :taptable:`rr.res_detail` table, in this case
to first get a list of all authorities managed by the CDS registry.
.. tapquery::
SELECT ivoid FROM rr.resource
RIGHT OUTER JOIN (
SELECT 'ivo://' || detail_value || '%' AS pat
FROM rr.res_detail
WHERE detail_xpath='/managedAuthority'
AND ivoid='ivo://cds.vizier/registry')
AS authpatterns
ON 1=ivo_nocasematch(resource.ivoid, authpatterns.pat)
This is the discovery query for RegTAP services themselves; note how this
combines :taptable:`rr.res_detail` pairs with :taptable:`rr.capability` and
:taptable:`rr.interface` to locate the desired protocol endpoints. As clients
should not usally be concerned with minor versions of protocols unless they
rely on additions made in later versions, this query will return endpoints
supporting “version 1” rather than exactly version 1.2.
.. tapquery::
SELECT access_url
FROM rr.interface
NATURAL JOIN rr.capability
NATURAL JOIN rr.res_detail
WHERE standard_id LIKE 'ivo://ivoa.net/std/tap%'
AND intf_role='std'
AND detail_xpath='/capability/dataModel/@ivo-id'
AND 1=ivo_nocasematch(detail_value,
'ivo://ivoa.net/std/regtap#1.%')
AND authenticated_only=0
“Certain features” could be “have some word in their description and having a
column with a certain UCD”. Either way, this kind of query fairly invariably
combines the usual :taptable:`rr.capability` and :taptable:`rr.interface` for
service location with :taptable:`rr.table_column` for the column metadata and
:taptable:`rr.res_table` for properties of tables.
.. tapquery::
SELECT ivoid,
name, ucd, column_description,
access_url
FROM rr.capability
NATURAL JOIN rr.interface
NATURAL JOIN rr.table_column
NATURAL JOIN rr.res_table
WHERE standard_id LIKE 'ivo://ivoa.net/std/tap%'
AND intf_role='std'
AND 1=ivo_hasword(table_description, 'quasar')
AND ucd='phot.mag;em.opt.v'
The metadata required to solve this problem is found in the SSAP
registry extension and is thus kept in
:taptable:`rr.res_detail`:
.. tapquery::
SELECT access_url
FROM rr.res_detail
NATURAL JOIN rr.capability
NATURAL JOIN rr.interface
WHERE detail_xpath='/capability/dataSource'
AND intf_role='std'
AND standard_id LIKE 'ivo://ivoa.net/std/ssa%'
AND detail_value='theory'
This uses the :taptable:`rr.res_role` table and returns all information on
it based on the IVOID of a service that in turn was obtained from
:taptable:`rr.interface`. You could restrict to the actual technical
contact person by requiring ``base_role='contact'``.
.. tapquery::
SELECT DISTINCT base_role, role_name, email
FROM rr.res_role
NATURAL JOIN rr.interface
WHERE access_url='http://dc.zah.uni-heidelberg.de/tap'
In the VO, data providers can register data collections either as such
or with “auxiliary capabilities” that are fully described elsewhere; a practice
for doing that is discussed in an Endorsed Note on `discovering data
collections within services`_.
.. _discovering data collections within services: http://ivoa.net/documents/discovercollections/
When following this pattern, data collections records should provide an
*isServedBy* relationship to the resources providing the access
services for the data collection (like a TAP or a SIAP service).
While the access URLs can typically be established from the auxiliary
capabilities themselves, several use cases require finding out more about the
publishing service. To locate its metadata, inspect
:taptable:`rr.relationship` and use it to select records from
:taptable:`rr.capability`; this requires an explicit join condition, as in this
case the capabilities are for the *related* record, not for the originally
matched one.
.. tapquery::
SELECT *
FROM rr.relationship AS a
JOIN rr.capability AS b
ON (a.related_id=b.ivoid)
WHERE
relationship_type='isservedby'
AND a.ivoid='ivo://cds.vizier/j/a+a/649/a25'
Consider the example: ”Give me resources that cover M 101 (α=210.80,
δ=54.35, Diameter about 0.3°) in the mid-infrared around
5μm in August 2010.
Without further database support, clients need to manually convert the
spectral coordinate to energy (hc/λ ≈ 3.97 × 10\ :sup:`-20` J and time (August
1st, 2010 starts MJD 55409.0) to the quantities RegTAP expects.
This would yield a query like (the explicit MOC conversion is a common
device to speed the query up; without it, the database would convert the
circle once for each coverage, to the respective order):
.. tapquery::
SELECT ivoid
FROM rr.stc_spatial
NATURAL JOIN rr.stc_spectral
NATURAL JOIN rr.stc_temporal
WHERE
1=CONTAINS(MOC(8, CIRCLE(210.80, 54.35, 0.3)), coverage)
AND 1=ivo_interval_overlaps(time_start, time_end, 55409, 55440)
AND 3.97e-20 between spectral_start and spectral_end
In particular when more complex geometries are desired, clients will
want to pass in MOCs directly. Conversely, RegTAP services may provide
the additional user-defined functions that allow specifying temporal and
spectral constraints in different, perhaps human-friendlier ways. For
instance, once support for the relevant UDFs is established using the TAP
capabilities, the above query could also be written as (the MOC given is the
circle above at order 8)::
SELECT ivoid
FROM rr.stc_spatial
NATURAL JOIN rr.stc_spectral
NATURAL JOIN rr.stc_temporal
WHERE
1=CONTAINS(MOC('8/182947 182950 182952-182953 182955-182956 8/'), coverage)
AND 1=ivo_interval_overlaps(
time_start, time_end,
gavo_to_mjd('2010-08-01'), gavo_to_mjd('2010-08-31'))
AND gavo_specconv(5e-6, 'm', 'J') between spectral_start and spectral_end
Using the gavo_vocmatch user-defined-functions, you can do what is called
query expansion in information retrieval, that is: not only query for a
keyword, but also for related terms.
In the relational registry, this concerns subjects, which should come from the
`IVOA rendering of the Unified Astronomy Thesaurus`_. To find resources
for brown dwarfs, you would query::
SELECT ivoid, res_subject FROM rr.res_subject
WHERE res_subject='brown-dwarfs'
However, this will miss resources talking about t-dwarfs, l-dwarfs and several
other concepts. To include those (“narrower”) concepts, write::
SELECT ivoid, res_subject FROM rr.res_subject
WHERE 1=gavo_vocmatch('uat', 'brown-dwarfs', res_subject)
instead. In reality, far too few data providers actually use the UAT
(correctly). We hence have a local extension table,
:taptable:`rr.subject_uat`, that is res_subject with legacy terms mapped to UAT
concept identifiers (translated to plain English: use this table instead
of :taptable:`rr.res_subject` for the time being). In there, you would
do something like:
.. tapquery::
SELECT ivoid, uat_concept FROM rr.subject_uat
WHERE 1=gavo_vocmatch('uat', 'brown-dwarfs', uat_concept)
.. _IVOA rendering of the Unified Astronomy Thesaurus: http://www.ivoa.net/rdf/uat
/oai.xml
ivo://org.gavo.dc/rr/q/create",
"use `our TAP service`_.",
'',
"true",
'standardID="ivo://ivoa.net/std/TAP#aux"',
"/tap",)
# add this when we have a tableset: "rr.resource")
]]>
/tap/sync
rows = self.getVOTableRows()
self.assertEqual(len(rows), 1)
self.assertEqual(rows[0], {
u"access_url": "http://dc.zah.uni-heidelberg.de/tap",
u"res_title": "GAVO RegTAP Service",
u"mirror_url": EqualingRE(
"http://reg.g-vo.org/tap#http://gavo.aip.de/tap"
"#http://voparis-rr.obspm.fr:80/tap"
".*")})
/tap/sync
self.assertEqual(len(self.getVOTableRows()), 2)
/tap/sync
self.assertEqual(len(self.getVOTableRows()), 2)
/tap/sync
self.assertEqual(len(self.getVOTableRows()), 2)
pmh/pubreg.xml
self.XPATH_NAMESPACE_MAP["dc"] = "http://purl.org/dc/elements/1.1/"
self.XPATH_NAMESPACE_MAP["oai_dc"] = \
"http://www.openarchives.org/OAI/2.0/oai_dc/"
self.assertValidatesXSD()
self.assertXpath(
"o:GetRecord/o:record/o:header/o:identifier",
{None: "ivo://org.gavo.dc/ohmaser/q/scs"})
self.assertXpath(
"o:GetRecord/o:record/o:metadata/oai_dc:dc/dc:identifier",
{None: "ivo://org.gavo.dc/ohmaser/q/scs"})
self.assertXpath(
"o:GetRecord/o:record/o:metadata/oai_dc:dc/dc:title",
{None: "A Database of Circumstellar OH Masers"})
self.assertXpath(
"o:GetRecord/o:record/o:metadata/oai_dc:dc/dc:description",
{None: EqualingRE("A all-sky compilation.*")})
self.assertFalse(b"ivo_managed" in self.data)
pmh/pubreg.xml
# don't XSD-validate them: we don't have the datacite schema on
# board.
self.XPATH_NAMESPACE_MAP["d"] = "http://datacite.org/schema/kernel-4"
self.assertXpath(
"o:GetRecord/o:record/o:header/o:identifier", {
None: "ivo://org.gavo.dc/lswscans/res/positions/siap"})
self.assertXpath(
"o:GetRecord/o:record/o:metadata/d:resource/d:identifier", {
None: "10.21938/haTEMZmoaCTEK6XZvGU.fQ",
"identifierType": "DOI"})
self.assertXpath(
"o:GetRecord/o:record/o:metadata/d:resource/d:creators/d:creator[1]/d:creatorName", {
None: "Mandel, H."})
self.assertXpath(
"o:GetRecord/o:record/o:metadata/d:resource/d:resourceType", {
"resourceTypeGeneral": "Dataset",
None: "AstroImage"})
self.assertXpath(
"o:GetRecord/o:record/o:metadata/d:resource/d:alternateIdentifiers/d:alternateIdentifier[1]", {
"alternateIdentifierType": "ivoid",
None: "ivo://org.gavo.dc/lswscans/res/positions/siap"})
self.assertXpath(
"o:GetRecord/o:record/o:metadata/d:resource/d:alternateIdentifiers/d:alternateIdentifier[2]", {
"alternateIdentifierType": "reference URL",
None: "http://dc.zah.uni-heidelberg.de/"
"lswscans/res/positions/siap/info"})
self.assertXpath(
"o:GetRecord/o:record/o:metadata/d:resource/d:alternateIdentifiers/d:alternateIdentifier[3]", {
"alternateIdentifierType": "browser URL",
None: "http://dc.zah.uni-heidelberg.de/hdap"})
self.assertFalse(b"ivo_managed" in self.data)
# if the following doesn't work, there's probably something wrong
# with our UAT top-level mapping
subjectsFound = set(e.text for e in
getattr(self, "cached parsed tree").xpath("//d:subject",
namespaces={"d": self.XPATH_NAMESPACE_MAP["d"]}))
self.assertEqual(subjectsFound, {
'history-of-astronomy', 'astrophotography',
'observational-astronomy', 'interdisciplinary-astronomy'})
pmh/pubreg.xml
self.assertValidatesXSD()
R = "o:GetRecord/o:record/o:metadata/eudc:resource/"
self.XPATH_NAMESPACE_MAP["eudc"
] = "http://schema.eudat.eu/schema/kernel-1"
self.assertXpath(
R+"eudc:creators/eudc:creator[1]/eudc:creatorName", {
None: "Mandel, H."})
self.assertXpath(
R+"/eudc:rightsList/eudc:rights[3]", {
None: "https://spdx.org/licenses/CC0-1.0.html"})
self.assertXpath(
R+"/eudc:instruments/eudc:instrument[1]", {
None:"Bruce Double Astrograph",
"instrumentIdentifierType": "Handle",
"instrumentIdentifier": "21.T11975/6447eba9-caa4-4edf-a050-3ebf11b9609d"})
self.assertXpath(
R+"/eudc:instruments/eudc:instrument[2]", {
None:"Calar Alto Schmidt Telescope"})
self.assertXpath(
R+"/eudc:publicationYear", {None: "2007"})
# The following is our UAT concept extension.
subjectsFound = set(e.text for e in
getattr(self, "cached parsed tree").xpath("//eudc:keyword",
namespaces={"eudc": self.XPATH_NAMESPACE_MAP["eudc"]}))
self.assertEqual(subjectsFound, {
'history-of-astronomy', 'astrophotography',
'observational-astronomy', 'interdisciplinary-astronomy'})
# now see if both a WebBrowser interface and the referenceURL are
# turned into relatedIdentifiers, the sequence being determined
# by the XSLT
self.assertXpath(
"//eudc:relatedIdentifier[@relatedIdentifierType='URL'][1]",
{ None:
"http://dc.zah.uni-heidelberg.de/lswscans/res/positions/siap/info"
})
self.assertXpath(
"//eudc:relatedIdentifier[@relatedIdentifierType='URL'][2]",
{ None: "http://dc.zah.uni-heidelberg.de/hdap"})
self.assertXpath(
R+"/eudc:temporalCoverages/eudc:temporalCoverage[1]/eudc:startDate",
{None: "1837-07-08T23:02:24Z"})
pmh/pubreg.xml
self.assertValidatesXSD()
R = "o:GetRecord/o:record/o:metadata/eudc:resource/"
self.XPATH_NAMESPACE_MAP["eudc"
] = "http://schema.eudat.eu/schema/kernel-1"
self.assertXpath(R+"eudc:relatedIdentifiers/"
"eudc:relatedIdentifier[@relatedIdentifierType"
"='bibcode']",
{None: '2017A&A...600L...4A'})
nmah/custom/ivo%3a//org.gavo.dc
The GAVO data center",
'',
'xsi:type="vg:Authority"',
'xmlns:vg=',
'created=')
]]>
lp/custom/org.gavo.dc/hsoy/q/q
The HSOY Catalog",
'',
'',
'href="http://adsabs.harvard.edu/abs/2017A&A...600L...4A">',
'ivo://org.gavo.dc/hsoy/q/q',
'- IVOA Cone Search SCS
',
'onclick="return false"')
]]>