Understand how vocabularies are used in OData metadata documents
- How vocabularies are used to organize annotations
- How they’re included within an OData metadata document
The members of the OData Technical Committee have worked hard on OData as a robust, well-defined and extensible standard. In this tutorial we’ll look at a key extensibility mechanism in the form of vocabularies, and how they’re used to organize annotations.
This tutorial belongs to the OData Deep Dive mission, a re-write of the original. The re-write is a work in progess, please proceed with caution! More info can be found in the blog post OData Deep Dive rewrite in the open.
- Step 1
In the previous Metadata tutorial we saw how the schema was presented within a context. That context is called the entity model wrapper. We left the examination of part of that wrapper - the references to vocabularies - to this tutorial. Let’s start by digging into those now.
Here’s what the relevant section of the wrapper in the Northbreeze OData service’s metadata document looks like:
xmlCopy<edmx:Edmx Version="4.0" xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx"> <edmx:Reference Uri="https://oasis-tcs.github.io/odata-vocabularies/vocabularies/Org.OData.Capabilities.V1.xml"> <edmx:Include Alias="Capabilities" Namespace="Org.OData.Capabilities.V1"/> </edmx:Reference> <edmx:Reference Uri="https://sap.github.io/odata-vocabularies/vocabularies/Common.xml"> <edmx:Include Alias="Common" Namespace="com.sap.vocabularies.Common.v1"/> </edmx:Reference> <edmx:Reference Uri="https://oasis-tcs.github.io/odata-vocabularies/vocabularies/Org.OData.Core.V1.xml"> <edmx:Include Alias="Core" Namespace="Org.OData.Core.V1"/> </edmx:Reference> ... </edmx:Edmx>What are these references? Well, section 3.3 Element edmx:Reference of the CSDL standards document is helpful here (as well as section 3.1 Element edmx:Edmx telling us that there can be zero or more of them within an
<edmx:Edmx>element).Basically,
edmx:Referenceelements point to external CSDL documents, specific content from which (indicated by theedmx:Includeelements within) is then added to the overall scope of the referring (OData metadata) document.Think of it like an “include” or “import” as found in various programming languages; these references might look like this in pseudo-JavaScript, for example:
javascriptCopyimport { "Org.OData.Capabilities.V1" as "Capabilities" } from "https://oasis-tcs.github.io/.../Org.OData.Capabilities.V1.xml"; import { "com.sap.vocabularies.Common.v1" as "Common" } from "https://sap.github.io/.../Common.xml"; import { "Org.OData.Core.V1" as "Core" } from "https://oasis-tcs.github.io/.../Org.OData.Core.V1.xml";Which one of these vocabulary aliases is one that represents a vocabulary which is from SAP?
- Step 2
Note that each of the referenced external documents in our OData metadata document are resources in GitHub repositories:
- two belonging to OASIS in https://oasis-tcs.github.io/odata-vocabularies/
- one belonging to SAP in https://sap.github.io/odata-vocabularies/
Taking the first of the three
<edmx:Reference>elements here:xmlCopy<edmx:Reference Uri="https://oasis-tcs.github.io/odata-vocabularies/vocabularies/Org.OData.Capabilities.V1.xml"> <edmx:Include Alias="Capabilities" Namespace="Org.OData.Capabilities.V1"/> </edmx:Reference>we see that:
- the reference points to an XML representation of a CSDL document “Org.OData.Capabilities.V1”
- moving one level up from that CSDL document resource’s location, there is a vocabularies overview page listing each of the OASIS Technical Committee vocabularies, including this “Capabilities” one.

- for each of these vocabulary resources there are HTML, XML and JSON representations
- the HTML representation is especially useful for us as it describes the vocabulary’s purpose in general, and gives details for each of the terms and types contained within it
Here’s a visual representation of those resources at https://oasis-tcs.github.io/odata-vocabularies/:
textCopyvocabularies/ <-- vocabularies overview page | +-- Org.OData.Capabilities.V1.html <-- detailed info on the vocabulary & its terms | +-- Org.OData.Capabilities.V1.xml <-- an XML representation of the vocabulary | +-- Org.OData.Capabilities.V1.json <-- a JSON representation of the vocabularyIf we look specifically at the XML representation of the “Capabilities” vocabulary in CSDL form, we see this:
xmlCopy<?xml version="1.0" encoding="utf-8"?> ... Abstract: This document contains terms describing capabilities of an OData service. --> <edmx:Edmx xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx" Version="4.0"> <edmx:Reference Uri="https://oasis-tcs.github.io/odata-vocabularies/vocabularies/Org.OData.Authorization.V1.xml"> <edmx:Include Alias="Authorization" Namespace="Org.OData.Authorization.V1" /> </edmx:Reference> <edmx:Reference Uri="https://oasis-tcs.github.io/odata-vocabularies/vocabularies/Org.OData.Core.V1.xml"> <edmx:Include Alias="Core" Namespace="Org.OData.Core.V1" /> </edmx:Reference> <edmx:Reference Uri="https://oasis-tcs.github.io/odata-vocabularies/vocabularies/Org.OData.Validation.V1.xml"> <edmx:Include Alias="Validation" Namespace="Org.OData.Validation.V1" /> </edmx:Reference> <edmx:DataServices> <Schema xmlns="http://docs.oasis-open.org/odata/ns/edm" Namespace="Org.OData.Capabilities.V1" Alias="Capabilities"> ... </Schema> </edmx:DataServices> </edmx:Edmx>It’s another EDMX document! There is definitely a certain beauty to the OData specifications that is special.
Anyway, there are two thing of note here:
- this document also has references to vocabularies
- there is a single
<Schema>element, with the OData namespace “Org.Data.Capabilities.V1”
And that specific schema is exactly the one that’s referenced in the
<edmx:Include>element within our first<edmx:Reference>element:xmlCopy<edmx:Include Alias="Capabilities" Namespace="Org.OData.Capabilities.V1"/>It just so happens that in this referenced CSDL document, there is only one schema, but there could be more.
So an
<edmx:Include>element forms an important part of the<edmx:Reference>.Indeed, section 3.3 Element edmx:Reference states that at least one
<edmx:Include>or<edmx:IncludeAnnotation>is mandatory.The
<edmx:Include>element serves to identify a particular schema to be included, from the referenced vocabulary. It also does one more thing here - it specifies a short name, in the form of a value for anAliasattribute, which can be used to refer to that imported vocabulary schema. Just like theasaliasing in our imaginary JavaScript equivalent example earlier. So instead of the full name “Org.OData.Capabilities.V1” being needed to prefix vocabulary terms, the short form “Capabilities” can be used, as we’ll see in subsequent steps.In the XML representation of the "Capabilities" vocabulary, there are also references to vocabularies. Which ones?
- Step 3
Now we understand how vocabulary resources are referenced to be included into an OData metadata document, and how they’re used to organize annotations, let’s now take a first look at what annotations are used in this particular OData metadata document, and how.
To set the scene, if we take brief look at the CSDL specification, we learn that:
- “Vocabulary annotations can be specified as a child of the model element being annotated or as a child of an
edm:Annotationselement that targets the model element.” (from section 4.6 Annotations) - “An annotation applies a term to a model element and defines how to calculate a value for the applied term.” (from section 14 Vocabulary and Annotation)
Additionally:
- “A service SHOULD NOT require a client to interpret annotations. Clients SHOULD ignore unknown terms and silently treat unexpected or invalid values (including invalid type, invalid literal expression, etc.) as an unknown value for the term.” ( also from section 14 Vocabulary and Annotation)
With the information from the first two points here, we can see in our OData metadata document that both approaches to annotation are used.
First, we see the “annotation as child element” approach where the annotation “Core.Links” is applied directly to the
<Schema>element via the<Annotation>element which appears a direct child of<Schema>:xmlCopy<Schema Namespace="Main" xmlns="http://docs.oasis-open.org/odata/ns/edm"> <Annotation Term="Core.Links"> <Collection> <Record> <PropertyValue Property="rel" String="author"/> <PropertyValue Property="href" String="https://cap.cloud.sap"/> </Record> </Collection> </Annotation> ... </Schema>Here, “Core” is the annotation vocabulary, and “Links” is the term (we’ll look in more detail at this in the next tutorial).
So in this case, the (entire) schema is being annotated with “Core.Links”:
textCopy+--------+ +------+ | | annotates | Core | | Schema | <-------------- +----------+ | | | Links | +--------+ +----------+Further on in the metadata document we see an example of the other approach, where
<Annotation>elements appear as direct children of a containing<Annotations>element, and the schema element to which the annotations are to be applied are specified in theTargetattribute of that<Annotations>container:Again, as explained in the previous Metadata tutorial, in the “Get acquainted with the schema element” step, we’ll leave out the XML namespace prefix
edmhere when writing elements that belong to that namespace.xmlCopy<Schema Namespace="Main" xmlns="http://docs.oasis-open.org/odata/ns/edm"> ... <EntityContainer Name="EntityContainer"> <EntitySet Name="Categories" EntityType="Main.Categories"> <NavigationPropertyBinding Path="Products" Target="Products"/> </EntitySet> </EntityContainer> ... <Annotations Target="Main.EntityContainer/Categories"> <Annotation Term="Capabilities.DeleteRestrictions"> <Record Type="Capabilities.DeleteRestrictionsType"> <PropertyValue Property="Deletable" Bool="false"/> </Record> </Annotation> <Annotation Term="Capabilities.InsertRestrictions"> <Record Type="Capabilities.InsertRestrictionsType"> <PropertyValue Property="Insertable" Bool="false"/> </Record> </Annotation> <Annotation Term="Capabilities.UpdateRestrictions"> <Record Type="Capabilities.UpdateRestrictionsType"> <PropertyValue Property="Updatable" Bool="false"/> </Record> </Annotation> </Annotations> </Schema>Here, three different annotations terms:
- Capabilities.DeleteRestrictions
- Capabilities.InsertRestrictions
- Capabilities.UpdateRestrictions
are being applied via
Target="Main.EntityContainer/Categories"to the “Categories” entityset in the entity container named “EntityContainer” in the “Main” OData namespace.textCopy+--------------+ | Capabilities | +--- +--------------------+ | | DeleteRestrictions | | +--------------------+ +----------------------+ | | Main.EntityContainer | | +--------------+ +--------------------------+ annotates | | Capabilities | | Categories | <-----------+--- +--------------------+ +--------------------------+ | | InsertRestrictions | | +--------------------+ | | +--------------+ | | Capabilities | +--- +--------------------+ | UpdateRestrictions | +--------------------+In the next tutorial we’ll dig in to the detail of the annotations used in this OData metadata document.
What is the (short name of the) namespace that qualifies the XML elements such as
, and in the examples here? - “Vocabulary annotations can be specified as a child of the model element being annotated or as a child of an