The XRD schema is intentionally minimalistic. It includes a small number of elements, leaving it up to each application to define new use-case-specific elements and attributes. The XRD schema allows new elements at every level, and new attributes in every element. It uses standard XML namespaces to accomplish this. Extensibility is, after all, right in the name: eXtensible Resource Descriptor.
Let’s consider a simple use case.
A weather service is being updated consistently every few hours. Clients using the service need to know how often to come back and check for new forecasts. The service and client developers meet, and decide to write a specification for this so that others can use it to enable interoperability. They all agree that XRD fits their requirements well.
The question is, how to express the weather update frequency information using the XRD schema?
All or Nothing
XRD uses URI-formatted type identifiers to indicate support for a feature, or as a property identifier. For example, if the hot.example.com weather service wants to specify support for a sunrise time feature, it could do so using an agreed upon type identifier:
When a client sees the http://spec.example.org/weather/etc/sunrise type identifier, it knows it can use the ‘sunrise‘ parameter to ask for sunrise information from the forecast endpoint. But the forecast update frequency isn’t simply a boolean feature (supported / not supported), it takes a variable – the update frequency.
One of Few
Weather forecasting is often performed on regular intervals like weekly, daily, or hourly. When a variable uses a small set of predefined values, each can be assigned a specialized type identifier. For example, if hot.example.com updates its forecast on a daily basis, it can express it using the following XRD:
Clients processing such XRDs will look for a possible match to one of three frequency identifier types. Since the number of identifiers is low (three in this case), the burden of matching to multiple types is worth the simplicity in design and readability.
In the frequency case, the developers decided that a 3-level approach isn’t flexible enough. They want to express frequency using multiple units (seconds, minutes, hours, and days) and support any value (0 – 32bit max value). This requirement does not allow for minting a unique URI for each combination.
XRD does not prevent type identifiers from using a meaningful structure. For example:
means the forecast is updated once every 3 days.
The problem with this approach is that it requires the client to perform a partial string match against each type identifier and parse the dynamic part of the identifier. One thing that can help is to place the variable part in the URI query instead of the path so that clients can match the type URI up to the ‘?‘ character as an indication of support for the feature, and the query to store the variables:
This approach still suffers from the same problem. Generic client libraries are not likely to have built-in support for structured type URIs, and even if they did, there are just too many ways to structure a URI. This is why XRD generally treats type identifiers as opaque identifiers, performing case-sensitive string comparison on the entire <Type> value.
So now what?
This is where XRD extensibility kicks in. There are two main approaches to extending the XRD schema to express a type with variables: custom attributes and custom elements.
Custom Type Attributes
<Type> is a general purpose element used to express a resource property. The examples above show how this element can be used effectively for many common uses. However, with minor adjustments <Type> can be extended to support the weather frequency use case:
<Type weather:frequency=”3d” xmlns:weather=”http://spec.exmaple.org/weather”>
By adding custom attributes, clients can look for the configuration type identifier http://spec.example.org/weather/config and if found (and understood), look for the extension attribute ‘weather:frequency‘.
There are other cases where <Type> is limited in its ability to express complex attributes. In such cases, specifications are encouraged to mint new custom elements specifically designed for their needs. It is better to mint a new element than stretch the <Type> element beyond what it was designed to do.
It is likely that a weather API configuration includes more than just a single frequency parameter. For example, it can specify different frequency values for different countries:
<Country code=”us” frequency=”1h” />
<Country code=”uk” frequency=”1d” />
The Sweet Spot
As you can see, XRD offers multiple levels of extensibility with varying complexity. The trick is to find the sweet spot in which the right level of customization comes with minimum complexity. One way to find the right solution for a given problem is to try each of the approaches described here in order, and see if they accommodate the requirements.
The trick is, as often the case, to know when a practical design moves into a astronaut territory.