Skip to content

As a user, I want to receive API search results in VOTable format #771

@jordanpadams

Description

@jordanpadams

💪 Motivation

VOTable (Virtual Observatory Table) is the standard tabular data exchange format defined by the International Virtual Observatory Alliance (IVOA). Astronomy and planetary science tools such as TOPCAT, Aladin, and PyVO natively consume VOTable, and many VO-compatible services (TAP, SSAP, SIAP) mandate it. Supporting application/x-votable+xml as a response format would make the PDS Registry API interoperable with the broader Virtual Observatory ecosystem and enable users to pipe results directly into standard astronomy analysis tools without conversion.

📖 Additional Details

MIME Type

  • Request via Accept: application/x-votable+xml
  • Response Content-Type: application/x-votable+xml

VOTable Document Structure (VOTable 1.4, IVOA REC-VOTable-1.4-20191021)

<?xml version="1.0" encoding="UTF-8"?>
<VOTABLE version="1.4"
  xmlns="http://www.ivoa.net/xml/VOTable/v1.3"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <RESOURCE type="results">
    <INFO name="QUERY_STATUS" value="OK"/>
    <INFO name="hits" value="42"/>
    <TABLE>
      <FIELD name="lidvid"             ID="lidvid"             datatype="char" arraysize="*" ucd="meta.id;meta.main"/>
      <FIELD name="lid"                ID="lid"                datatype="char" arraysize="*" ucd="meta.id"/>
      <FIELD name="title"              ID="title"              datatype="char" arraysize="*" ucd="meta.title"/>
      <FIELD name="start_date_time"    ID="start_date_time"    datatype="char" arraysize="*" ucd="time.start" unit="ISO-8601"/>
      <FIELD name="stop_date_time"     ID="stop_date_time"     datatype="char" arraysize="*" ucd="time.stop"  unit="ISO-8601"/>
      <FIELD name="ops:archive_status" ID="ops:archive_status" datatype="char" arraysize="*" ucd="meta.code.status"/>
      <!-- additional properties mapped from the product summary -->
      <DATA>
        <TABLEDATA>
          <TR><TD>urn:nasa:pds:...</TD><TD>...</TD></TR>
        </TABLEDATA>
      </DATA>
    </TABLE>
  </RESOURCE>
</VOTABLE>

Key FIELD Attributes

Attribute Required Description
name Yes Column name matching PDS property key
datatype Yes VOTable datatype (char, int, float, double, etc.)
arraysize For strings "*" for variable-length strings
ucd Recommended IVOA Unified Content Descriptor (e.g. meta.id;meta.main)
unit If applicable Unit string (e.g. ISO-8601, deg)
utype Optional Link to a data model (e.g. ObsCore utype)

UCD Mappings (Initial Set)

PDS Field UCD
lidvid meta.id;meta.main
lid meta.id
title meta.title
start_date_time time.start
stop_date_time time.stop
target_name meta.id;src
instrument instr.setup
archive_status meta.code.status

Serialization

  • Use TABLEDATA serialization (inline XML TR/TD) as the default — human-readable and simplest to implement.
  • BINARY / BINARY2 may be considered as a future optimization for large result sets.

Implementation Notes (Spring Boot / MVC view layer)

  1. Add a new view class (e.g. PdsProductsVOTableSerializer) in gov.nasa.pds.api.registry.view, following the existing serializer pattern.
  2. Register application/x-votable+xml as a supported MediaType in the Spring MVC content negotiation configuration.
  3. Map ProductSummary / Pds4Products model fields to <FIELD> definitions and <TR><TD> rows.
  4. Populate <INFO name="hits"> from the total hit count on the search response.
  5. Propagate query errors into <INFO name="QUERY_STATUS" value="ERROR"> per IVOA convention.
  6. Set version="1.4" on the <VOTABLE> root; use the VOTable 1.3 namespace URI (reused by 1.4): http://www.ivoa.net/xml/VOTable/v1.3.

Endpoints to Support

At minimum:

  • GET /products — product list
  • GET /products/{identifier} — single product (TABLE with one row)
  • GET /classes/{class} — class-filtered product list
  • GET /collections, GET /bundles — collection and bundle listings

⚖️ Acceptance Criteria

Given a deployed registry-api with products indexed
When I request GET /products with header Accept: application/x-votable+xml
Then I receive a 200 response with Content-Type: application/x-votable+xml and a valid VOTable 1.4 XML document containing one <TR> per product in the result page


Given a valid VOTable response
When I inspect the document structure
Then the root element is <VOTABLE version="1.4">, it contains a <RESOURCE type="results">, a <TABLE> with at least one <FIELD> per returned property, and a <DATA><TABLEDATA> block with one <TR> per product


Given a valid VOTable response
When I inspect the <INFO> elements
Then <INFO name="QUERY_STATUS" value="OK"/> is present, and <INFO name="hits"> reflects the total number of matching products (not just the current page size)


Given a request with Accept: application/x-votable+xml
When the query returns zero results
Then the response is still a valid VOTable with an empty <TABLEDATA> and <INFO name="QUERY_STATUS" value="OK"/>


Given a request with Accept: application/x-votable+xml
When an upstream search error occurs
Then <INFO name="QUERY_STATUS" value="ERROR"> contains a human-readable error message, and the HTTP status code is appropriate (4xx or 5xx)


Given the VOTable response
When I load it in TOPCAT or another IVOA-compliant tool
Then it parses without errors and all columns and rows are correctly displayed


Given a request for a single product GET /products/{identifier} with Accept: application/x-votable+xml
When the product exists
Then the response contains a VOTable with exactly one <TR> row

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    Status

    ToDo

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions