DAP4 Dataset Services Response: Difference between revisions

From OPeNDAP Documentation
⧼opendap2-jumptonavigation⧽
Line 253: Line 253:


== Discussion ==
== Discussion ==
=== Static or Dynamic Response? ===
As the DAP servers evolve to support user authentication and sessions the content of the dataset services description document should become dynamic. By this I mean that some services and server functions might be available only to certain users. If an authenticated user asks for a particular dataset services description document they would see all the the services available to them, which might differ significantly from those available to a different user.  As powerful server side functions such as re-gridding and re-projection become available we anticipate that data providers may not wish to allow just anyone to utilize them because of the potential burden they may place on the data center's computing resources.
It may be that some services may not be available for all datasets. This argues (along with the previous comment about users and roles) that the service description needs to be generated dynamically and that it should be context sensitive w.r.t. user, role, and dataset.
Implementation of a ''dynamic'' services response implies that the software generating that response ''can'' get information about what is applicable for a given user and a given dataset, where the latter could be quite complicated. The alternative is to have all possible responses described in the services description with the understanding that they might return an error code under one set of circumstances. This would be far easier for servers, and likely require no additional logic in clients (because they will have to account that unforeseen errors will happen in any case). The opposing argument is that presenting information known to be false is a poor practice - and it's hard not to agree.
I suggest that we split this into two cases:
; Authenticated/privileged versus anonymous users: For this case, the response should be dynamic and reflect what the user can actually do.
; Datasets for which server-side functions are/are-not applicable: For this case, however, the response should not attempt to determine what is applicable to a particular dataset, but that it optionally can indicate that a particular function ''can'', with certainty, be applied.
These are two fundamentally different cases because the semantics or the first are under our control, while those of the latter are not. In the first cases, the server defines the classes of users and the sets that describe their capabilities. It is possible for the server to know that a given user can never run a regridding operation, for example, because they lack the authorization to do so. However, for datasets, determining which functions are applicable, for example, requires ''understanding the semantics of the metadata bound to that dataset'' which can be done in some cases, but not all.
==== How this limits the response's utility, plus a solution ====
The problem with not providing a list of functions that is known to be applicable to a dataset, is that limits an important source of semantic information about those datasets. If we know that a regridding function can be allied to dataset X, then we know a fair amount that dataset. In addition, it is possible that the service response could include, at some future time, either directly or via inference, semantic information based on server-side operations that were known to be possible.
If we extend the ''Function'' element of the service response so that the element listing a function contains an attribute that indicates that the server knows that this function can definitely be used with the dataset, then we can support semantic systems without forcing the server to know about the applicability of each function to each dataset. I would suggest that we add the attribute ''applicability'' and support the three values of ''yes'', ''no'', and ''unknown'' with the latter being the default value.
=== Comments from version 1 ===
[[User:Jimg|Jimg]] 12:47, 3 February 2012 (PST) This proposed feature is an example of [http://tools.ietf.org/html/draft-ietf-httpbis-p3-payload-16#section-5.2 agent-driven content negotiation]. To wit:
<blockquote>With agent-driven negotiation, selection of the best representation for a response is performed by the user agent after receiving an initial response from the origin server.  Selection is based on a list of the available representations of the response included within the header fields or body of the initial response, with each representation identified by its own URI.</blockquote>
[[User:Jimg|Jimg]] 16:22, 14 November 2011 (PST)
:We should think about making this a JSON response, or think about having ''http://server/file.nc'' return the XML and ''http://server/file.nc.json'' return JSON using an XSLT transform.
[[User:Jimg|Jimg]] 16:22, 14 November 2011 (PST)
: Nathan and I both conclude that the XML response should include the full URL and not do some weird hack where URLs are 'built'.
:While this might be specific to HTTP and the web, I think we should include in the design that a JSON version of this document will be returned if the client announces that it understands such thing (the default response will be XML with an embedded XSL stylesheet that provides a transform to HTML). The HTTP/1.1 request and response would look like:
<pre>
GET / HTTP/1.1
Host: api.example.com
Accept: application/vnd.example.link_templates+json
HTTP/1.1 200 OK
Content-Type: application/vnd.example.link_templates+json
Cache-Control: max-age=3600
Connection: close
</pre>
:Where the request header ''Accept:'' is the key bit. See the post Ethan referenced for more information about this: [http://www.mnot.net/blog/2011/10/25/web_api_versioning_smackdown Web API Versioning Smackdown]
[[User:dmh|Dennis]] 4/12/2012
: I would like to propose an (possibly off-the-wall) alternate response format based on treating the service terminus as a DAP4 dataset more or less like any other dataset. This means that the response would be a DDX plus content. The DDX would encode the capabilities of the server using the DAP4 notions of group, variable, attribute, etc. The specific values would be returned as the associated content. This would allow us to use our (yet to be defined) query capability to extract specific capability values. It would also (IMO) simplify programmatic access to the server capability information.
[[User:Ndp|ndp]] 20:17, 19 April 2012 (PDT)
: I stood up  a prototype of the Dataset Services (a.k.a. the Service Terminus) on test.o.o. I quickly discovered the following mixed result: Now that the web pages contain links to all of the services, the crawler bots find them all!
: This is great news because, well, the services are exposed and our experiment in improving  our servers RESTfulness succeeded.
: This is bad news because the bots are asking for the ASCII, NetCDF file out, and XML data responses for everything on the server. Which is trashing it. By which I mean all of the servers memory and CPU resources are being consumed by bots. The server logs are full of BES client timeouts and broken pipes. Response times are in the gutter.
: This is an unintended consequence to our new Dataset Services response and I think we need to carefully consider how we might remediate this problem.
: On the one hand I think we want the catalog/web pages to be crawled and indexed. On the other we really don't want bots asking for all of the data in all of the ways it can be transmitted.
=== Issues (from version 1)===
* This a change in server behavior that will change the response content of file access URLs. These URLs are not part of the regular DAP URL pattern and their current behavior is a function of server configuration.
* How might we describe the way to elicit DAP3.x and DAP4 versions of the responses in this description given that we currently rely on the XDAP-Accept HTTP header to inform the server of the version being requested? [[User:Jimg|Jimg]] 16:18, 14 November 2011 (PST) We can define a new set of extensions for these responses, especially since there are only two (ddx4 and dap4, e.g.). There are several other syntaxes that put this information in the URL, but if we use unique URLs to reference these new responses, then we don't break REST. This would mean that the XDAP-Accept: header would be dropped, but that's a separate discussion.
* [[User:Jimg|Jimg]] 10:42, 26 January 2012 (PST) I am now leaning toward using ''.ddx'' and ''.dap'' to be the way that DAP4 metadata and data are accessed, period. This means dropping the idea of version negotiation, which I think is a poor design for a web service. the extensions ''.das'', ''.dds'' and ''.dods''  woud return the tried and true DAP2 response objects and any server hat support the five extensions clearly support DAP2 and DAP4. No client will every ask for a DAP2 DDX and be surprised by getting DAP4 (which it won't be able to parse) because to do so would be nonsensical (and anti-causal, sort of...). The one hitch with this idea is that there are some DAP2++ clients out there that gobble up DDX responses...
*''<font color="red">I know we discussed additional issues, but I can't recall them. Please add them if you do!</font>''


= Atom - How might we express this response as an Atom 1.0 document. =
= Atom - How might we express this response as an Atom 1.0 document. =

Revision as of 20:00, 5 July 2012


<-- back to OPULS Development

Author: ndp

Background

DAP2, while successful within several arenas in the scientific community, failed to live up to some the basic tenants of the world wide web. On of theses weaknesses was it's lack of RESTful interfaces.

Problem addressed

Currently DAP servers provide a number of dataset level responses (services). These include DAP services such as the DDS, DAS, and DDX, plus other services that have been added over time such as the RDF and ISO responses. There is currently no way for a user (or software agent) to discover which of these many services might be available for a particular dataset. While THREDDS catalogs do provide a mechanism for determining which services are associated with which datasets, they don't actually provide a mechanism for discovering the details of the various service URLs. A THREDDS catalog might identify a DAP service, but the URL that can be assembled from the THREDDS catalog for that service is limited to just the base dataset URL. Typically dereferencing this URL will provide one of two things - either the underlying data file (for example a netcdf file) or an HTTP 403 error if direct access to the underlying files has been disabled in the server configuration.

Example:

This URL points to a dataset on a DAP server:

http://test.opendap.org:8080/opendap/data/nc/fnoc1.nc

Dereferencing the link will not connect you to a DAP service or DAP response. It will only return the underlying netcdf file. The only way to know that DAP services exist for this is by reading the URL path and recognizing that it is likely an instance of a DAP server based on the position of the 'opendap' string in the URL.

There is no guarantee that dereferencing this URL will even yield the underlying file, as that behavior is a configuration option for the server. If that access is not allowed in the configuration, then dereferencing the URL will simply return an HTTP 403 (forbidden) error.

Proposed solution

We intend to provide a 'Services' or 'Capabilities' response for DAP4. By default, DAP dataset resource URLs should return an XML document describing the DAP services available for the dataset.

At minimum this document MUST provide for each service available for the dataset:

  • A human readable title of the service (DDX, DDS, etc.)
  • One or more links that can be dereferenced to get the various representations of service response for the dataset in question.
  • An unambiguous, unique to the service, xlink:role identifier that serves as a way to clearly identify what each service on the list purports to do.
  • A brief description of the service
  • A link to a complete, human readable, description of the service response and it's semantics

The response should also include:

  • A reference to an XSLT that a browser would use to render the description into HTML for a presentation view.
  • Descriptions and syntax of server side functions available for the dataset


DAP4 Web Services

A DAP4 web service is described by:

  • A simple human readable name called 'title'.
  • One or more access URLs and each with an associated media-type for the representation returned by that URL.
  • A unique "namespace" like id that is used to define an xlink:role attribute. This is intended to allow people and software to unambiguously identify specific services, irrespective of their human readable title. The idea is that that the xlink:role tells you what is going to happen when you go to xlink:href.
  • An optional description.

A service is accessed by dereferencing its access URL, which is typically constructed by adding some type of suffix to the dataset's referent (aka base) URL. The way in which the query string (aka constraint expression) is used is defined by each service, and there is no requirement for inter-service query string API conformity.

A more extensive discussion of the various services that might appear in a DatasetServices document can be found on the DAP4 Web Services v3 page.

Jimg 22:49, 2 July 2012 (PDT) In this example, I think we should modify it so that the link element follows HTML's (and ATOM's) form (http://tools.ietf.org/html/rfc4287, http://www.atomenabled.org/developers/syndication/) where href is the attribute for the hyperlink reference, type is as it's shown here and rel can be used for stuff like enclosure to indicate something. I think xlink::role is right on the money for describing how the thing referenced by the link should be used. Note that if Service becomes entry and Description becomes title and we add id and updated to entry/Service we have a valid ATOM entry element. Then we can start thinking of these responses as both things that describe a resource and can be used as part of a data cast feed.

It might look like:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<?xml-stylesheet type="text/xsl" href="/opendap/xsl/serviceDescription.xsl"?>
<DatasetServices 
    xmlns:xlink="http://www.w3.org/1999/xlink" 
    xml:base="http://test.opendap.org:8090/opendap/hyrax/ECMWF_ERA-40_subset.ncml">
    
    <entry title="Data Request Form" >
        <id>http://test.opendap.org:8090/opendap/hyrax/ECMWF_ERA-40_subset.ncml.html</id>
        <updated>2003-12-13T18:30:02-05:00</updated>
        <link type="text/xml"  href="http://test.opendap.org:8090/opendap/hyrax/ECMWF_ERA-40_subset.ncml.html" 
             xlink:role="http://services.opendap.org/dap4/data-request-form#">
        <title>OPeNDAP HTML Data Request Form for data sub-setting and access.</title>
    </entry>

...

</DatasetServices>

A trivial change, but then we can reuse these in an ATOM feed.

One thing, the id element of entry is tricky although I think the URL works.

Example Response

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<?xml-stylesheet type="text/xsl" href="/opendap/xsl/serviceDescription.xsl"?>
<DatasetServices 
    xmlns:xlink="http://www.w3.org/1999/xlink" 
    xml:base="http://test.opendap.org:8090/opendap/hyrax/ECMWF_ERA-40_subset.ncml">
    
    <Service title="Data Request Form" >
        <link type="text/xml" 
             xlink:href="http://test.opendap.org:8090/opendap/hyrax/ECMWF_ERA-40_subset.ncml.html" 
             xlink:role="http://services.opendap.org/dap4/data-request-form#">
        <Description xlink:href="http://docs.opendap.org/index.php/DAP4_Web_Services#DAP4:_HTML_DATA_Request_Form_Service">OPeNDAP HTML Data Request Form for data sub-setting and access.</Description>
    </Service>

    <Service title="Dataset">
        <link type="text/xml" 
             xlink:href="http://test.opendap.org:8090/opendap/hyrax/ECMWF_ERA-40_subset.ncml.xml" 
             xlink:role="http://services.opendap.org/dap4/dataset#">
        <link type="application/json" 
             xlink:href="http://test.opendap.org:8090/opendap/hyrax/ECMWF_ERA-40_subset.ncml.xml.json" 
             xlink:role="http://services.opendap.org/dap4/dataset#">
        <Description xlink:href="http://docs.opendap.org/index.php/DAP4_Web_Services#DAP4:_Dataset_Service_-_The_metadata">DAP4 Dataset Description and Attribute XML Document.</Description>
    </Service>

    <Service title="DAP4 Data">
        <link type="multipart/mixed" 
             xlink:href="http://test.opendap.org:8090/opendap/hyrax/ECMWF_ERA-40_subset.ncml.dap" 
             xlink:role="http://services.opendap.org/dap4/data#">
        <Description xlink:href="http://docs.opendap.org/index.php/DAP4_Web_Services#DAP4:_Data_Service">DAP4 Data object.</Description>
    </Service>

    <Service title="DAP2 Data">
        <link type="application/octet-stream" 
             xlink:href="http://test.opendap.org:8090/opendap/hyrax/ECMWF_ERA-40_subset.ncml.dods"
             xlink:role="http://services.opendap.org/dap2/dods#">
        <Description xlink:href="http://docs.opendap.org/index.php/DAP4_Web_Services#DAP2:_Data_Service">DAP2 Data Object.</Description>
    </Service>

    <Service title="ASCII Data">
        <link type="text/plain" 
             xlink:href="http://test.opendap.org:8090/opendap/hyrax/ECMWF_ERA-40_subset.ncml.asc"
             xlink:role="http://services.opendap.org/dap4/ascii#">
        <Description xlink:href="http://docs.opendap.org/index.php/DAP4_Web_Services#DAP4:_ASCII_Data_Service">The DAP4 Data response in ASCII form.</Description>
    </Service>

    <Service title="NetCDF-File">
        <link type="application/x-netcdf" 
             xlink:href="http://test.opendap.org:8090/opendap/hyrax/ECMWF_ERA-40_subset.ncml.nc"
             xlink:role="http://services.opendap.org/dap4/netcdf-3#">
        <Description xlink:href="http://docs.opendap.org/index.php/DAP4_Web_Services#DAP4:_NetCDF_File-out_Service">NetCDF file-out response.</Description>
    </Service>

    <Service title="XML Data Response">
         <link type="text/xml" 
             xlink:href="http://test.opendap.org:8090/opendap/hyrax/ECMWF_ERA-40_subset.ncml.xdap"
             xlink:role="http://services.opendap.org/dap4/xml-data#">
        <Description xlink:href="http://docs.opendap.org/index.php/DAP4_Web_Services#DAP4:_XML_Data_Service">An XML document containing both the dataset's structural metadata along with data values.</Description>
    </Service>

    <Service title="DDX">
        <link type="text/xml" 
             xlink:href="http://test.opendap.org:8090/opendap/hyrax/ECMWF_ERA-40_subset.ncml.ddx"
             xlink:role="http://services.opendap.org/dap2/ddx#">
        <Description xlink:href="http://docs.opendap.org/index.php/DAP4_Web_Services#DAP2:_DDX_Service">OPeNDAP Data Description and Attribute XML Document.</Description>
    </Service>

    <Service title="DDS">
        <link type="text/plain" 
             xlink:href="http://test.opendap.org:8090/opendap/hyrax/ECMWF_ERA-40_subset.ncml.dds"
             xlink:role="http://services.opendap.org/dap2/dds#">
        <Description xlink:href="http://docs.opendap.org/index.php/DAP4_Web_Services#DAP2:_DDS_Service">OPeNDAP Data Description Structure.</Description>
    </Service>

    <Service title="DAS"
        <link type="text/plain" 
             xlink:href="http://test.opendap.org:8090/opendap/hyrax/ECMWF_ERA-40_subset.ncml.das"
             xlink:role="http://services.opendap.org/dap2/das#">
        <Description xlink:href="http://docs.opendap.org/index.php/DAP4_Web_Services#DAP2:_DAS_Service">OPeNDAP Dataset Attribute Structure.</Description>
    </Service>

    <Service title="RDF">
        <link type="application/rdf+xml" 
             xlink:href="http://test.opendap.org:8090/opendap/hyrax/ECMWF_ERA-40_subset.ncml.rdf"
             xlink:role="http://services.opendap.org/dap4/rdf#">
        <Description xlink:href="http://docs.opendap.org/index.php/DAP4_Web_Services#DAP4:_RDF_Service">An RDF representation of the Dataset response (DDX) document.</Description>
    </Service>

    <Service title="INFO">
        <link type="text/html" 
             xlink:href="http://test.opendap.org:8090/opendap/hyrax/ECMWF_ERA-40_subset.ncml.info"
             xlink:role="http://services.opendap.org/dap2/info#">
        <Description xlink:href="http://docs.opendap.org/index.php/DAP4_Web_Services#DAP2:_Info_Service">OPeNDAP Dataset Information Page.</Description>
    </Service>

    <Service title="Server Version">
        <link type="text/xml" 
             xlink:href="http://test.opendap.org:8090/opendap/hyrax/ECMWF_ERA-40_subset.ncml.ver"
             xlink:role="http://services.opendap.org/dap4/version#">
        <Description xlink:href="http://docs.opendap.org/index.php/DAP4_Web_Services#DAP4:_Server_Version_Service">An XML document containing information about the software version of the server..</Description>
    </Service>

    <Service title="ISO-19115">
        <link type="text/xml" 
             xlink:href="http://test.opendap.org:8090/opendap/hyrax/ECMWF_ERA-40_subset.ncml.iso"
             xlink:role="http://services.opendap.org/dap4/iso-19115-metadata#">
        <Description xlink:href="http://docs.opendap.org/index.php/DAP4_Web_Services#DAP4:_ISO_19115_Service">ISO 19115 Metadata Representation of the Dataset (DDX) response.</Description>
    </Service>

    <Service title="ISO-19115-Score">
        <link type="text/html" 
             xlink:href="http://test.opendap.org:8090/opendap/hyrax/ECMWF_ERA-40_subset.ncml.rubric"
             xlink:role="http://services.opendap.org/dap4/iso-19115-score#">
        <Description xlink:href="http://docs.opendap.org/index.php/DAP4_Web_Services#DAP4:_ISO_Conformance_Score_Service">ISO 19115 Metadata Representation conformance score for this dataset.</Description>
    </Service>

    <Service title="File Access"
        <link type="text/xml"  ## This value depends on the file being accessed.
             xlink:href="http://test.opendap.org:8090/opendap/hyrax/ECMWF_ERA-40_subset.ncml.file"
             xlink:role="http://services.opendap.org/dap4/file#">
        <Description xlink:href="http://docs.opendap.org/index.php/DAP4_Web_Services#DAP4:_Native_File_Access_Service">Access to dataset file.</Description>
    </Service>

    <Service title="Dataset Services Description">
        <link type="text/xml" 
             xlink:href="http://test.opendap.org:8090/opendap/hyrax/ECMWF_ERA-40_subset.ncml" 
             xlink:role="http://services.opendap.org/dap4/dataset#">
        <link type="application/json" 
             xlink:href="http://test.opendap.org:8090/opendap/hyrax/ECMWF_ERA-40_subset.ncml.json" 
             xlink:role="http://services.opendap.org/dap4/dataset#">
        <Description xlink:href="http://docs.opendap.org/index.php/DAP4_Web_Services#DAP4:_Dataset_Services_Description_Service">An XML document itemizing the Services available for this dataset.</Description>
    </Service>

    <ServerSideFunctions>
        <Function name="geogrid"
          xlink:href="http://docs.opendap.org/index.php/Server_Side_Processing_Functions#geogrid">
            <Description>Allows a DAP Grid variable to be sub-sampled using georeferenced values.</Description>
        </Function>
        <Function name="grid"
          xlink:href="http://docs.opendap.org/index.php/Server_Side_Processing_Functions#grid">
            <Description>Allows a DAP Grid variable to be sub-sampled using the values of the coordinate axes.</Description>
        </Function>
        <Function name="linear_scale"
          xlink:href="http://docs.opendap.org/index.php/Server_Side_Processing_Functions#linear_scale">
            <Description>Applies a linear scale transform to the named variable.</Description>
        </Function>
        <Function name="version"
          xlink:href="http://docs.opendap.org/index.php/Server_Side_Processing_Functions#version">
            <Description>Returns version information for each server side function.</Description>
        </Function>
    </ServerSideFunctions>
</DatasetServices>


I also put together a simple XSLT to make this a human friendly HTML. I added a reference to it in the XML document. When you point a browser at the resource URL (For example http://localhost:8080/opendap/data/nc/fnoc1.nc ) the Service Description response is returned as an XML file (above), the browser detects the xml-stylesheet reference, grabs the XSLT, uses it to convert the XML to HTML and renders it like this:

ServiceDescriptionPrototype-01.png


Rationale for the solution

The solution provides DAP4 servers with RESTful interface that allows for both server-driven and agent driven content negotiation as described in [section 12 of the HTTP 1.1 specification]. Providing the DatasetServices response in XML allows many down stream applications to ingest the content and leaves open the option for server implementers to add XSLT references to the document so that clients like browsers can easily build a presentation view of the information.

Discussion

Atom - How might we express this response as an Atom 1.0 document.

Here are two examples in which I attempted to take all of the semantics from the previous proprietary example and represent them in an Atom document.

Both of these documents validated using the W3C Feed Validation Service.

All of the content components of each document are required with the exception of the atom:link/@title attribute, which is optional.


Example: Validated Atom Document for a dataset, each service as an atom:entry

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<feed xmlns="http://www.w3.org/2005/Atom">
 
        <title>Example Feed</title>
        <subtitle>A subtitle.</subtitle>
        <link href="http://test.opendap.org:8090/opendap/hyrax/ECMWF_ERA-40_subset.ncml" title="DatasetServices: ECMWF_ERA-40_subset.ncml" rel="self" />
        <id>urn:uuid:60a76c80-d399-11d9-b91C-0003939e0af6</id>
        <updated>2003-12-13T18:30:02Z</updated>
        
            

    <entry xmlns="http://www.w3.org/2005/Atom">
        <id>http://test.opendap.org:8090/opendap/hyrax/ECMWF_ERA-40_subset.ncml</id>
        <title>DAP Dataset Services Response.</title>
        <updated>2003-12-13T18:30:02Z</updated>
        <author>
            <name>Nathan Potter</name>
            <email>johndoe@devnull.com</email>
        </author>
        
        <content type="xhtml" xml:lang="en" xml:base="http://test.opendap.org:8090/opendap/hyrax/ECMWF_ERA-40_subset.ncml">
            <div xmlns="http://www.w3.org/1999/xhtml">DAP4 Dataset Metadata Service for http://test.opendap.org:8090/opendap/hyrax/ECMWF_ERA-40_subset.ncml</div>
        </content>

        <link rel="self"
              title="Dataset Services" 
              type="application/atom+xml" 
              href="http://test.opendap.org:8090/opendap/hyrax/ECMWF_ERA-40_subset.ncml"/>
    </entry>

    <entry>
        <id>http://test.opendap.org:8090/opendap/hyrax/ECMWF_ERA-40_subset.ncml.xdp</id>
        <title>DAP4 Dataset Description and metadata Attributes XML Document.</title>
        <updated>2003-12-13T18:30:02Z</updated>
        <author>
            <name>Nathan Potter</name>
            <email>johndoe@devnull.com</email>
        </author>
        
        <content type="xhtml" xml:lang="en" xml:base="http://test.opendap.org:8090/opendap/hyrax/ECMWF_ERA-40_subset.ncml">
            <div xmlns="http://www.w3.org/1999/xhtml">DAP4 Dataset Metadata Service for http://test.opendap.org:8090/opendap/hyrax/ECMWF_ERA-40_subset.ncml</div>
        </content>

        <link rel="related"
              title="Dataset Metadata" 
              type="application/vnd.opendap.org.dap4.ddx+xml" 
              href="http://test.opendap.org:8090/opendap/hyrax/ECMWF_ERA-40_subset.ncml.xdp"/>
    </entry>

    <entry>
        <id>http://test.opendap.org:8090/opendap/hyrax/ECMWF_ERA-40_subset.ncml.dap</id>
        <title>DAP4 Data object.</title>
        <updated>2003-12-13T18:30:02Z</updated>
        <author>
            <name>Nathan Potter</name>
            <email>johndoe@devnull.com</email>
        </author>
        
        <content type="xhtml" xml:lang="en" xml:base="http://test.opendap.org:8090/opendap/hyrax/ECMWF_ERA-40_subset.ncml">
            <div xmlns="http://www.w3.org/1999/xhtml">DAP4 Data Service for http://test.opendap.org:8090/opendap/hyrax/ECMWF_ERA-40_subset.ncml</div>
        </content>
        
        <link rel="related"
              title="DAP4 Data" 
              type="application/vnd.opendap.org.dap4.data" 
              href="http://test.opendap.org:8090/opendap/hyrax/ECMWF_ERA-40_subset.ncml.dap"/>
    </entry>

    <entry>
    
        <id>http://test.opendap.org:8090/opendap/hyrax/ECMWF_ERA-40_subset.ncml.html</id>
        <title>OPeNDAP HTML Data Request Form for data sub-setting and access.</title>
        <updated>2003-12-13T18:30:02Z</updated>
        
        <author>
            <name>Nathan Potter</name>
            <email>johndoe@devnull.com</email>
        </author>
        
        <content type="xhtml" xml:lang="en" xml:base="http://test.opendap.org:8090/opendap/hyrax/ECMWF_ERA-40_subset.ncml">
            <div xmlns="http://www.w3.org/1999/xhtml">HTML Data Request Form http://test.opendap.org:8090/opendap/hyrax/ECMWF_ERA-40_subset.ncml</div>
        </content>
        

        <link rel="related"
              title="Data Request Form" 
              type="text/xml"  
              href="http://test.opendap.org:8090/opendap/hyrax/ECMWF_ERA-40_subset.ncml.html"/>
              
    </entry>

        .
        .
        .
    
</feed>

Example: Validated Atom Document with one atom:entry for a dataset, and an atom:link for each service

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<entry xmlns="http://www.w3.org/2005/Atom">

    <title>DAP Dataset Services: ECMWF_ERA-40_subset.ncml</title>

    <id>http://test.opendap.org:8090/opendap/hyrax/ECMWF_ERA-40_subset.ncml</id>

    <updated>2003-12-13T18:30:02-05:00</updated>
    
    <author>
        <name>Nathan Potter</name>
        <email>johndoe@devnull.com</email>
    </author>
    <summary>DAP Dataset Services for http://test.opendap.org:8090/opendap/hyrax/ECMWF_ERA-40_subset.ncml</summary>
    
    <link title="Dataset Services Description"
          rel="self"
          type="application/atom+xml" 
          href="http://test.opendap.org:8090/opendap/hyrax/ECMWF_ERA-40_subset.ncml"/>
    
    <link title="DAP4 Dataset Metadata XML Document."
          rel="alternate"
          type="application/vnd.opendap.org.dap4.ddx+xml" 
          href="http://test.opendap.org:8090/opendap/hyrax/ECMWF_ERA-40_subset.ncml.xml"/>
    
    <link title="DAP4 Data object."
          rel="related"
          type="application/vnd.opendap.org.dap4.data" 
          href="http://test.opendap.org:8090/opendap/hyrax/ECMWF_ERA-40_subset.ncml.dap"/>

    <link title="OPeNDAP HTML Data Request Form for data sub-setting and access."
          rel="related"
          type="text/html" 
          href="http://test.opendap.org:8090/opendap/hyrax/ECMWF_ERA-40_subset.ncml.html" />

    <link title="DAP2 Data Object."
          rel="related"
          type="application/vnd.opendap.org.dap2.data" 
          href="http://test.opendap.org:8090/opendap/hyrax/ECMWF_ERA-40_subset.ncml.dods"/>
          
    <link title="DAP4 Data response in ASCII form."
          rel="related"
          type="text/plain" 
          href="http://test.opendap.org:8090/opendap/hyrax/ECMWF_ERA-40_subset.ncml.asc"/>
          
    <link title="NetCDF-3 file-out response."
          rel="related"
          type="application/x-netcdf" 
          href="http://test.opendap.org:8090/opendap/hyrax/ECMWF_ERA-40_subset.ncml.nc"/>
          
    <link title="XML Data Response"
          rel="related"
          type="application/vnd.opendap.org.dap4.data+xml" 
          href="http://test.opendap.org:8090/opendap/hyrax/ECMWF_ERA-40_subset.ncml.xdap"/>
          
    <link title="DAP2 DDX document"
          rel="related"
          type="application/vnd.opendap.org.dap2.ddx+xml" 
          href="http://test.opendap.org:8090/opendap/hyrax/ECMWF_ERA-40_subset.ncml.ddx"/>
          
    <link title="DAP2 DDS document"
          rel="related"
          type="application/vnd.opendap.org.dap2.dds" 
          href="http://test.opendap.org:8090/opendap/hyrax/ECMWF_ERA-40_subset.ncml.dds"/>
          
    <link title="DAP2 DAS document"
          rel="related"
          type="application/vnd.opendap.org.dap2.dds" 
          href="http://test.opendap.org:8090/opendap/hyrax/ECMWF_ERA-40_subset.ncml.das"/>
          
    <link title="RDF representation of the Dataset Metadata response."
          rel="related"
          type="application/rdf+xml" 
          href="http://test.opendap.org:8090/opendap/hyrax/ECMWF_ERA-40_subset.ncml.rdf"/>
          
    <link title="DAP2 Dataset Information Page"
          rel="related"
          type="text/html" 
          href="http://test.opendap.org:8090/opendap/hyrax/ECMWF_ERA-40_subset.ncml.info"/>
          
    <link title="Server Version Document"
          rel="related"
          type="text/xml" 
          href="http://test.opendap.org:8090/opendap/hyrax/ECMWF_ERA-40_subset.ncml.ver"/>
          
    <link title="ISO 19115 Metadata Representation of the Dataset (DDX) response."
          rel="related"
          type="text/xml" 
          href="http://test.opendap.org:8090/opendap/hyrax/ECMWF_ERA-40_subset.ncml.iso"/>
          
    <link title="ISO 19115 Metadata Representation conformance score for this dataset."
          rel="related"
          type="text/html" 
          href="http://test.opendap.org:8090/opendap/hyrax/ECMWF_ERA-40_subset.ncml.rubric"/>
          
    <link title="Dataset file access"
          rel="related"
          type="text/xml"  
          href="http://test.opendap.org:8090/opendap/hyrax/ECMWF_ERA-40_subset.ncml.file"/>
          
</entry>