4 Encoding GML

4.1 Introduction

This section describes how to encode geospatial (geographic) features in GML. The encoding of spatial features using GML 2.0 requires the use of two XML Schemas: the GML Feature Schema (feature.xsd) and the GML Geometry Schema (geometry.xsd); with these two simple schemas it is possible to encode a wide variety of geospatial information.

The remainder of this sub-section introduces the two XML Schemas using UML notation. The following sub-sections provide an introduction to encoding geospatial information in GML 2.0, broken down as follows:

  • 4.2 Encoding a feature without geometry

  • 4.3 Encoding geometry

  • 4.4 Encoding a feature with geometry

  • 4.5 Encoding collections of features

  • 4.6 Encoding associations between features

First-time readers may wish to skip this sub-section and proceed directly to 4.2; starting from section 4.2 we present an extended set of examples which progessively introduce the components of GML 2.0. Individuals wishing to use GML as a simple means of structuring spatial information for transport are referred to Listing 6.6.

4.1.1 The Geometry schema

The Unified Modeling Language (UML) offers a fairly general means of visually representing the elements of an application schema; a class diagram presents a concise overview of defined types, and a package diagram depicts higher-level groupings of model elements. The base schemas can be viewed as distinct packages with the dependencies as illustrated in Figure 4.1.

Figure 4.1. Base schemas as packages

graphics/bfig05.jpg

The GML Geometry schema includes type definitions for both abstract geometry elements, concrete (multi) point, line and polygon geometry elements, as well as complex type definitions for the underlying geometry types. Figure 4.2 is a UML representation of the Geometry schema; this diagram provides a bridge between the wide-ranging OGC Abstract Specification (Topic 1: Feature Geometry) and the GML Geometry schema?it includes many of the 'well-known' structures described in the abstract specification.

Figure 4.2. UML representation of the Geometry schema

graphics/bfig06.gif

The <<restriction>> stereotype applied to a generalization relationship indicates that a subtype defined in the schema is derived by restriction from its supertype. For example, the MultiLineString class is a geometry collection in which a member must be a LineString. The complete GML Geometry schema appears in Appendix A; it is liberally documented with <annotation> elements. By convention, explicity named type definitions take the corresponding class name and append the 'Type' suffix (e.g. LineString becomes LineStringType). Type names are in mixed case with a leading capital; the names of geometric properties and attributes are in mixed case with a leading lower case character. The names of abstract elements are in mixed case with a leading underscore (e.g. _Feature) to highlight their abstract character.

The Geometry schema targets the 'gml' namespace. A namespace is a conceptual entity identified by a URI ("http://www.opengis.org/gml" for the core gml namespace) that denotes a collection of element names and type definitions that belong together?they comprise a cohesive vocabulary. User-defined schemas are required to declare their own target namespace as discussed in section 5.2.4.

4.1.2 The Feature schema

The Feature schema uses the <include> element to bring in the GML geometry constructs and make them available for use in defining feature types:

<include schemaLocation="geometry.xsd"/>

Figure 4.3 is a UML representation of the Feature schema. Note that a geometric property is modeled as an association class that links a feature with a geometry; concrete geometric property types such as PointProperty constrain the geometry to a particular type (e.g. Point).

Figure 4.3. UML representation of the Feature schema

graphics/bfig07.jpg

The GML Feature schema is listed in Appendix B. The <include> element in the Feature schema brings in the definitions and declarations contained in the Geometry schema. Like the geometry schema, the Feature schema defines both abstract and concrete elements and types. User-written schemas may define elements and/or types to name and distinguish significant features and feature collections from each other.

4.2 Encoding features without geometry

Although it is not anticipated that many features will be encoded in GML 2.0 without any geometry properties, this section starts off with a simple example based on an aspatial feature. This is referred to as the 'Dean' example. There is a feature type called Dean that is defined to have a string property called familyName and an integer property called age. In addition a Dean feature can have zero or more string properties called nickName. Thus a single instance of the Dean feature type might be encoded in XML as:

<Dean>
  <familyName>Smith</familyName>
  <age>42</age>
  <nickName>Smithy</nickName>
  <nickName>Bonehead</nickName>
</Dean>

Without any thought for GML, one could define the relevant XML Schema to support this as:

<element name="Dean" type="ex:DeanType" />
<complexType name="DeanType">
  <sequence>
    <element name="familyName" type="string"/>
    <element name="age" type="integer"/>
    <element name="nickName" type="string" minOccurs="0"
      maxOccurs="unbounded"/>
  </sequence>
</complexType>

However, using the Feature schema from GML, it is necessary to identify what plays the role of features (and their types) and what plays the role of properties. In the Dean example Dean is a feature type and age is a property. This is indicated in GML by the following:

<element name="Dean" type="ex:DeanType"
  substitutionGroup="gml:_Feature" />

<complexType name="DeanType">
  <complexContent>
    <extension base="gml:AbstractFeatureType">
      <sequence>
        <element name="familyName" type="string"/>
        <element name="age" type="integer"/>
        <element name="nickName" type="string" minOccurs="0"
          maxOccurs="unbounded"/>
      </sequence>
    </extension>
  </complexContent>
</complexType>

It should be noted that not only does the instance document validate against both of these XML Schema definitions but the content model of DeanType is the same in both XML Schema definitions. Using the Feature schema from GML enables the use of pre-defined attributes. For example features can be identified with the 'fid' attribute, and features can be described using a predefined gml:description property. These capabilities are inherited from gml:AbstractFeatureType (to be more precise Dean extends gml:AbstractFeatureType).

<Dean fid="D1123">
  <gml:description>A nice old chap</gml:description>
  <familyName>Smith</familyName>
  <age>42</age>
  <nickName>Smithy</nickName>
  <nickName>Bonehead</nickName>
</Dean>

4.3 Encoding geometry

This section describes how GML encodes basic geometry types, and it introduces the GML Geometry schema (geometry.xsd) that supports this encoding. The geometry schema corresponds quite closely to the geometry encoding embodied by the DTD put forth in the GML 1.0 document. The material in this section should be read by all prospective GML users.

In accord with the OGC Simple Features model, GML provides geometry elements corresponding to the following geometry classes:

  • Point

  • LineString

  • LinearRing

  • Polygon

  • MultiPoint

  • MultiLineString

  • MultiPolygon

  • MultiGeometry

In addition there are <coordinates> and <coord> elements for encoding coordinates, and a <Box> element for defining extents. The following sections describe in detail the encoding of each of these fundamental types of geometry elements.

4.3.1 Coordinates

The coordinates of any Geometry class instance are encoded either as a sequence of <coord> elements that encapsulate tuple components, or as a single string contained within a <coordinates> element. The advantage of using <coord> elements is that a validating XML parser can perform basic type checking and enforce constraints on the number of tuples that appear in a particular geometry instance. Both approaches can convey coordinates in one, two, or three dimensions. The relevant schema fragments can be found in the Geometry schema:

<element name="coord" type="gml:CoordType" />

<complexType name="CoordType">
  <sequence>
    <element name="X" type="decimal"/>
    <element name="Y" type="decimal" minOccurs="0"/>
    <element name="Z" type="decimal" minOccurs="0"/>
  </sequence>
</complexType>

An additional level of constraint restricts the number of tuples by data type. For example, a <Point> element contains exactly one coordinate tuple:

<Point srsName="http://www.opengis.net/gml/srs/epsg.xml#4326">
  <coord><X>5.0</X><Y>40.0</Y></coord>
</Point>

As an alternative, coordinates can also be conveyed by a single string. By default the coordinates in a tuple are separated by commas, and successive tuples are separated by a space character (#x20). While these delimiters are specified by several attributes, a user is free to define a localized coordinates list that is derived by restriction from gml:CoordinatesType. An instance document could then employ the xsi:type attribute to substitute the localized coordinates list wherever a <coordinates> element is expected; such a subtype could employ other delimiters to reflect local usage.

It is expected that a specialized client application will extract and validate string content, as these functions will not be performed by a general XML parser. The formatting attributes will assume their default values if they are not specified for a particular instance; the <coordinates> element must conform to these XML Schema fragments:

<element name="coordinates" type="gml:CoordinatesType"/>

<complexType name="CoordinatesType">
  <simpleContent>
    <extension base="string">
      <attribute name="decimal" type="string" use="default" value="."/>
      <attribute name="cs" type="string" use="default" value=","/>
      <attribute name="ts" type="string" use="default" value="&#x20;"/>
    </extension>
  </simpleContent>
</complexType>

This would allow the Point example provided above to be encoded as:

<Point srsName="http://www.opengis.net/gml/srs/epsg.xml#4326">
  <coordinates>5.0,40.0</coordinates>
</Point>
4.3.2 Geometry elements

The coordinates for a geometry are defined within some spatial reference system (SRS), and all geometries must specify this SRS. GML 2.0 does not address the details of defining spatial reference systems. There is currently a proposed XML-based specification for handling coordinate reference systems and coordinate transformations [OGC00-040]. The srsName attribute of the geometry types can be used to test for the equality of SRS between different geometries. The srsName (since it is a URI reference) may be navigated to the definition of the SRS. It is expected that the pending SRS specification will be applicable to GML encodings, perhaps in the guise of a Geodesy module derived from that specification.

The optional gid attribute of the geometry types represents a unique identifier for geometry elements; this is an ID-type attribute whose value must be text string that conforms to all XML name rules (i.e. the first character cannot be a digit).

4.3.3 Primitive geometry elements

The Point element is used to encode instances of the Point geometry class. Each <Point> element encloses either a single <coord> element or a <coordinates> element containing exactly one coordinate tuple; the srsName attribute is optional since a Point element may be contained in other elements that specify a reference system. Similar considerations apply to the other geometry elements. The Point element, in common with other geometry types, also has an optional gid attribute that serves as an identifier. Here's an example:

<Point gid="P1" srsName="http://www.opengis.net/gml/srs/epsg.xml#4326">
  <coord><X>56.1</X><Y>0.45</Y></coord>
</Point>

The Box element is used to encode extents. Each <Box> element encloses either a sequence of two <coord> elements or a <coordinates> element containing exactly two coordinate tuples; the first of these is constructed from the minimum values measured along all axes, and the second is constructed from the maximum values measured along all axes. A value for the srsName attribute should be provided, since a Box cannot be contained by other geometry classes. A Box instance looks like this:

<Box srsName="http://www.opengis.net/gml/srs/epsg.xml#4326">
  <coord><X>0.0</X><Y>0.0</Y></coord>
  <coord><X>100.0</X><Y>100.0</Y></coord>
</Box>

A LineString is a piece-wise linear path defined by a list of coordinates that are assumed to be connected by straight line segments. A closed path is indicated by having coincident first and last coordinates. At least two coordinates are required. Here's an example of a LineString instance:

<LineString srsName="http://www.opengis.net/gml/srs/epsg.xml#4326">
  <coord><X>0.0</X><Y>0.0</Y></coord>
  <coord><X>20.0</X><Y>35.0</Y></coord>
  <coord><X>100.0</X><Y>100.0</Y></coord>
</LineString>

A LinearRing is a closed, simple piece-wise linear path which is defined by a list of coordinates that are assumed to be connected by straight line segments. The last coordinate must be coincident with the first coordinate and at least four coordinates are required (the three to define a ring plus the fourth duplicated one). Since a LinearRing is used in the construction of Polygons (which specify their own SRS), the srsName attribute is not needed.

A Polygon is a connected surface. Any pair of points in the polygon can be connected to one another by a path. The boundary of the Polygon is a set of LinearRings. We distinguish the outer (exterior) boundary and the inner (interior) boundaries; the LinearRings of the interior boundary cannot cross one another and cannot be contained within one another. There must be at most one exterior boundary and zero or more interior boundary elements. The ordering of LinearRings and whether they form clockwise or anti-clockwise paths is not important. A following example of a Polygon instance has two inner boundaries and uses coordinate strings:

<Polygon gid="_98217" srsName="http://www.opengis.net/gml/srs/
  epsg.xml#4326">
  <outerBoundaryIs>
    <LinearRing>
      <coordinates>0.0,0.0 100.0,0.0 100.0,100.0 0.0,100.0 0.0,0.0
        </coordinates>
    </LinearRing>
  </outerBoundaryIs>
  <innerBoundaryIs>
    <LinearRing>
      <coordinates>10.0,10.0 10.0,40.0 40.0,40.0 40.0,10.0 10.0,10.0
        </coordinates>
    </LinearRing>
  </innerBoundaryIs>
  <innerBoundaryIs>
    <LinearRing>
      <coordinates>60.0,60.0 60.0,90.0 90.0,90.0 90.0,60.0 60.0,60.0
        </coordinates>
    </LinearRing>
  </innerBoundaryIs>
</Polygon>
4.3.4 Geometry collections

There are a number of homogeneous geometry collections that are predefined in the Geometry schema. A MultiPoint is a collection of Points; a MultiLineString is a collection of LineStrings; and a MultiPolygon is a collection of Polygons. All of these collections each use an appropriate membership property to contain elements. It should be noted that the srsName attribute can only occur on the outermost GeometryCollection and must not appear as an attribute of any of the enclosed geometry elements. Here's an example of a MultiLineString instance with three members:

<MultiLineString srsName="http://www.opengis.net/gml/srs/
  epsg.xml#4326">
  <lineStringMember>
    <LineString>
      <coord><X>56.1</X><Y>0.45</Y></coord>
      <coord><X>67.23</X><Y>0.98</Y></coord>
    </LineString>
  </lineStringMember>
  <lineStringMember>
    <LineString>
      <coord><X>46.71</X><Y>9.25</Y></coord>
      <coord><X>56.88</X><Y>10.44</Y></coord>
    </LineString>
  </lineStringMember>
  <lineStringMember>
    <LineString>
      <coord><X>324.1</X><Y>219.7</Y></coord>
      <coord><X>0.45</X><Y>4.56</Y></coord>
    </LineString>
  </lineStringMember>
</MultiLineString>

In addition the Geometry schema defines a heterogeneous geometry collection represented by the MultiGeometry element that provides a container for arbitrary geometry elements; it might contain any of the primitive geometry elements such as Points, LineStrings, Polygons, MultiPoints, MultiLineStrings, MultiPolygons and even other GeometryCollections. The MultiGeometry element has a generic geometryMember property which returns the next geometry element in the collection. An example of a heterogeneous MultiGeometry instance appears below.

<MultiGeometry gid="c731" srsName="http://www.opengis.net/gml/srs/
  epsg.xml#4326">
  <geometryMember>
    <Point gid="P6776">
      <coord><X>50.0</X><Y>50.0</Y></coord>
    </Point>
  </geometryMember>

  <geometryMember>
    <LineString gid="L21216">
      <coord><X>0.0</X><Y>0.0</Y></coord>
      <coord><X>0.0</X><Y>50.0</Y></coord>
      <coord><X>100.0</X><Y>50.0</Y></coord>
    </LineString>
  </geometryMember>

  <geometryMember>
    <Polygon gid="_877789">
      <outerBoundaryIs>
        <LinearRing>
          <coordinates>0.0,0.0 100.0,0.0 50.0,100.0 0.0,0.0
            </coordinates>
        </LinearRing>
      </outerBoundaryIs>
    </Polygon>
  </geometryMember>
</MultiGeometry>

4.4 Encoding features with geometry

GML 2.0 provides a pre-defined set of geometry properties that can be used to relate geometries of particular types to features. Consider the case where the DeanType feature definition has a point property called location, which is one of the pre-defined descriptive names that can substitute for the formal name pointProperty.

<Dean>
  <familyName>Smith</familyName>
  <age>42</age>
  <nickName>Smithy</nickName>
  <nickName>Bonehead</nickName>
  <gml:location>
    <gml:Point>
      <gml:coord><gml:X>1.0</gml:X><gml:Y>1.0</gml:Y></gml:coord>
    </gml:Point>
  <gml:location>
</Dean>

which is based on the following application schema fragment:

<element name="Dean" type="ex:DeanType"
substitutionGroup="gml:_Feature"/>

<complexType name="DeanType">
  <complexContent>
    <extension base="gml:AbstractFeatureType">
      <sequence>
        <element name="familyName" type="string"/>
        <element name="age" type="integer"/>
        <element name="nickName" type="string" minOccurs="0"
          maxOccurs="unbounded"/>
        <element ref="gml:location"/>
      </sequence>
    </extension>
  </complexContent>
</complexType>

Alternatively one can define geometry properties specific to an application schema. For example one might wish to name the property specifying the location of the Dean instance as deanLocation:

<element name="Dean" type="ex:DeanType"
substitutionGroup="gml:_Feature"/>

<complexType name="DeanType">
  <complexContent>
    <extension base="gml:AbstractFeatureType">
      <sequence>
        <element name="familyName" type="string"/>
        <element name="age" type="integer"/>
        <element name="nickName" type="string" minOccurs="0"
          maxOccurs="unbounded"/>
        <element name="deanLocation" type="gml:PointPropertyType"/>
      </sequence>
    </extension>
  </complexContent>
</complexType>

In this example gml:PointPropertyType is available as a useful pre-defined property type for a feature to employ in just the same way that strings and integers are. The local declaration of the <deanLocation> element basically establishes an alias for <gml:pointProperty> as a subelement of Dean.

The exclusive use of globally-scoped element declarations reflects a different authoring style that 'pools' all elements in the same symbol space (see section 2.5 of the XML Schema specification, Part 1 for further details); this style also allows us to assign elements to a substitution group such that designated elements can substitute for a particular head element, which must be declared as a global element. The deanLocation property would be declared globally and referenced in a type definition as shown below:

<element name="Dean" type="ex:DeanType" substitutionGroup="gml:_Feature"/>
<element name="deanLocation" type="gml:PointPropertyType"
  substitutionGroup="gml:pointProperty"/>

<complexType name="DeanType">
  <complexContent>
    <extension base="gml:AbstractFeatureType">
      <sequence>
        <element name="familyName" type="string"/>
        <element name="age" type="integer"/>
        <element name="nickName" type="string" minOccurs="0"
          maxOccurs="unbounded"/>
        <element ref="ex:deanLocation" />
      </sequence>
    </extension>
  </complexContent>
</complexType>

4.5 Encoding feature collections

GML 2.0 provides support for building feature collections. An element in an application schema that plays the role of a feature collection must derive from gml:AbstractFeatureCollectionType and declare that it can substitute for the (abstract) <gml:_FeatureCollection> element. A feature collection can use the featureMember property to show containment of other features and/or feature collections.

Consider the 'Cambridge' example (described in Section 5) where a CityModel feature collection contains Road and River feature members. In this modification to the example the features are contained within the CityModel using the generic gml:featureMember property that instantiates the gml:FeatureAssociationType:

<CityModel fid="Cm1456">
  <dateCreated>Feb 2000</dateCreated>
  <gml:featureMember>
    <River fid="Rv567">....</River>
  </gml:featureMember>

  <gml:featureMember>
    <River fid="Rv568">....</River>
  </gml:featureMember>

  <gml:featureMember>
    <Road fid="Rd812">....</Road>
  </gml:featureMember>
</CityModel>

With the following associated application schema fragments:

<element name="CityModel" type="ex:CityModelType"
  substitutionGroup="gml:_FeatureCollection"/>
<element name="River" type="ex:RiverType" substitutionGroup=
  "gml:_Feature"/>
<element name="Road" type="ex:RoadType" substitutionGroup=
  "gml:_Feature"/>

<complexType name="CityModelType">
  <complexContent>
    <extension base="gml:AbstractFeatureCollectionType">
      <sequence>
        <element name="dateCreated" type="month"/>
      </sequence>
    </extension>
  </complexContent>
</complexType>

<complexType name="RiverType">
  <complexContent>
    <extension base="gml:AbstractFeatureType">
      <sequence>....</sequence>
    </extension>
  </complexContent>
</complexType>

<complexType name="RoadType">
  <complexContent>
    <extension base="gml:AbstractFeatureType">
      <sequence>.....</sequence>
    </extension>
  </complexContent>
</complexType>

GML 2.0 provides a mechanism for feature identification. All GML features have an optional 'fid' attribute of type ID inherited from gml:AbstractFeatureType; this means that features in the same GML document cannot share a 'fid' value. The 'fid' attribute and simple link elements constructed using XLink attributes provide a means of unambiguously referencing specific features within a GML document.

Within a feature collection, a <featureMember> element can either contain a single feature or point to a feature that is stored remotely (including elsewhere in the same document). A simple link element can be constructed by including a specific set of XLink attributes. The XML Linking Language (XLink) is currently a Proposed Recommendation of the World Wide Web Consortium [XLink]. XLink allows elements to be inserted into XML documents so as to create sophisticated links between resources; such links can be used to reference remote properties.

A simple link element can be used to implement pointer functionality, and this functionality has been built into various GML 2.0 elements by including the gml:AssociationAttributeGroup in these constructs:

  • gml:FeatureAssociationType,

  • the geometry collection types, and

  • all of the pre-defined geometry property types.

As an example, we can modify the CityModel fragment shown above to include a remote River members without making any changes to the application schema.

<CityModel fid="Cm1456">
  <dateCreated>Feb 2000</dateCreated>

  <gml:featureMember xlink:type="simple"
    xlink:href="http://www.myfavoritesite.com/rivers.xml#Rv567"/>

  <gml:featureMember xlink:type="simple"
    xlink:href="http://www.myfavoritesite.com/rivers.xml#Rv568"/>

  <gml:featureMember>
    <Road fid="Rd812">....</Road>
  </gml:featureMember>
</CityModel>

It should be noted that the featureMember property can both point to a remote feature and contain a feature. It is not possible in XML Schema to preclude this practice using a purely grammar-based validation approach. The GML 2.0 specification regards a featureMember in this state to be undefined.

The most basic syntax for a simple link is as follows:

<propertyName xlink:type="simple"
  xlink:title="Description of target instance"
  xlink:href="http://www.myfavoritesite.com/locations.xml#identifier" />

where the xlink:title attribute is optional. The xlink:href attribute must point to an object whose type matches that of the value type of the property. It is up to the application to validate that this is the case, an XML parser would not place any constraints on the element linked to by the href attribute.

To enhance clarity a new attribute defined in the 'gml' namespace is introduced to supplement the basic XLink attributes: remoteSchema. The remoteSchema attribute is a URI reference that uses XPointer syntax to identify the GML schema fragment that constrains the resource pointed to by the locator attribute; this additional attribute is included in the gml:AssociationAttributeGroup and so is already available to featureMember properties so that they can be expressed like this (assuming "RiverType" is the value of some identifier):

<gml:featureMember xlink:type="simple"
  gml:remoteSchema="http://www.myfavoritesite.com/types.xsd#RiverType"
  xlink:href="http://www.myfavoritesite.com/rivers#Rv567"/>

XLink attributes can only be placed on property elements, and there are no constraints on the values of the xlink:title attribute. Simple XLinks also allow the use of the xlink:role attribute. However this is most commonly a reflection of the property (for example the featureMember role name) that is using the link.

The XLink specification requires that the xlink:href attribute point to the resource participating in the link by providing a Uniform Resource Identifier (URI). For example, such a URI may constitute a request to a remote server such as an OGC Web Feature Server (WFS). It might be noted that in response to a 'GETFEATURE' request a WFS will return the GML description of a feature, provided the feature identifier (the value of its 'fid' attribute) is known:

xlink:href="http://www.myfavoritesite.com/wfs?WFSVER=0.0.12
  &amp;REQUEST=GETFEATURE
  &amp;FEATUREID=Rv567"

The value of the xlink:href must be a valid URI per IETF RFC 2396 [RFC2396] and RFC 2732 [RFC2732]; as a consequence, certain characters in the URI string must be escaped according to the URI encoding rules set forth in the XLink specification and in the aforementioned IETF documents.

It might be noted that the WFS 'GETFEATURE' request returns a single feature. If the gml:remoteSchema attribute is being used, then it should point to the definition of the relevant feature type. Alternatively an XLink can be used to encode an entire query request to a WFS (required character references do not appear in the query string for clarity):

xlink:href="http://www.myfavoritesite.com/wfs?
  WFSVER=0.0.12&
  REQUEST=GETFEATURE&
  TYPENAME=INWATERA_1M&
  FILTER='<Filter>
            <Not>
              <Disjoint>
                <PropertyName>INWATERA_1M.WKB_GEOM</PropertyName>
                <Polygon srsName="http://www.opengis.net/gml/srs/
                  epsg.xml#4326">
                  <outerboundaryIs>
                    <LinearRing>
                      <coordinates>
                        -150,50 -150,60 -125,60 -125,50 -150,50
                      </coordinates>
                    </LinearRing>
                  </outerboundaryIs>
                </Polygon>
              </Disjoint>
            </Not>
          </Filter>'"

In this case the WFS may 'manufacture' a generic feature collection to hold the results of the query. But since feature collections also have a feature type, the gml:remoteSchema attribute (if used) should point to the feature type definition of this feature collection, not the types of the features returned by the query.

4.6 Encoding feature associations

The essential purpose of XML document structure is to describe data and the relationships between components within it. With GML it is possible to denote relationships either by containment (binary relationships only) or by linking, but there is no a priori reason for preferring one style over another. The examples presented so far have emphasized containment, generally using the property name (i.e. the role name) as a 'wrapper' to make the logical structure explicit.

The GML data model is based on three basic constructs: Feature, Feature Type (i.e. Class), and Property. Both Classes and Properties are resources that are independently defined in GML. A property is defined by specifying the range and domain of the property, each of which must be defined GML types. A GML feature is a Class on which are defined a number of properties; zero, one, or more of these properties are geometry-valued. A Resource is anything that has an identity [RFC2396]; this can include electronic documents, a person, a service or a geographic feature.

In the previous section specialized links were used to allow a feature collection in a GML document to contain features external to the document. Had the features been present in the GML document, there would have been no compelling reason to use a link, since the 'containment' relationship could have been indicated by using nesting in the GML document. However there are many relationships that cannot be encoded using containment. Consider the 'adjacency' relationship between three LandParcel features. In total there are three relationships representing the three pairings of features. Using the nesting approach encouraged so far, one might be tempted to encode this in the following, albeit messy, way using an adjacentTo property (we will present a much cleaner form later):

<LandParcel fid="Lp2034">
  <area>2345</area>
  <gml:extentOf>...</extentOf>
  <adjacentTo>
    <LandParcel fid="Lp2035">
      <area>9812</area>
      <gml:extentOf>...</extentOf>
      <adjacentTo xlink:type="simple" xlink:href="#Lp2034"/>
      <adjacentTo>
        <LandParcel fid="Lp2036">
          <area>8345</area>
          <gml:extentOf>...</extentOf>
          <adjacentTo xlink:type="simple" xlink:href="#Lp2034"/>
          <adjacentTo xlink:type="simple" xlink:href="#Lp2035"/>
        </LandParcel>
      </adjacentTo>
    </LandParcel>
  </adjacentTo>
  <adjacentTo xlink:type="simple" xlink:href="#Lp2036"/>
</LandParcel>

In the above fragment the links are being used to identify features within the same GML document. In this example the adjacency relationship is binary (it connects pairs of features) and bi-directional (it can be navigated in both directions). This has been achieved by using two adjacentTo properties (each with a simple XLink) to represent each relationship. The relationship itself has no identity in this encoding, and it is not possible to record properties on the relationship. Relationships with these characteristics are sometimes referred to as 'lightweight' relationships.

In the above encoding the adjacentTo property sometimes 'nests' the related feature and sometimes 'points' to it. A more symmetrical version of the above would be:

<LandParcel fid="Lp2034">
  <area>2345</area>
  <gml:extentOf>...</extentOf>
  <adjacentTo xlink:type="simple" xlink:href="#Lp2035"/>
  <adjacentTo xlink:type="simple" xlink:href="#Lp2036"/>
</LandParcel>
....
<LandParcel fid="Lp2035">
  <area>9812</area>
  <gml:extentOf>...</extentOf>
  <adjacentTo xlink:type="simple" xlink:href="#Lp2034"/>
  <adjacentTo xlink:type="simple" xlink:href="#Lp2036"/>
</LandParcel>
....
<LandParcel fid="Lp2036">
  <area>8345</area>
  <gml:extentOf>...</extentOf>
  <adjacentTo xlink:type="simple" xlink:href="#Lp2034"/>
  <adjacentTo xlink:type="simple" xlink:href="#Lp2035"/>
</LandParcel>

Here the ellipses represent the necessary containment constructs holding this set of LandParcels in some root feature collection. However both examples conform to the same application schema:

<element name="LandParcel" type="ex:LandParcelType"
  substitutionGroup="gml:_Feature"/>
<element name="adjacentTo" type="ex:AdjacentToType"
  substitutionGroup="gml:featureMember" />

<complexType name="LandParcelType">
  <complexContent>
    <extension base="gml:AbstractFeatureType">
      <sequence>
        <element name="area" type="integer"/>
        <element ref="gml:extentOf"/>
        <element ref="ex:adjacentTo" minOccurs="0"
          maxOccurs="unbounded"/>
      </sequence>
    </extension>
  </complexContent>
</complexType>

<complexType name="AdjacentToType">
  <complexContent>
    <restriction base="gml:FeatureAssociationType">
      <sequence>
        <element ref="ex:LandParcel"/>
      </sequence>
    </restriction>
  </complexContent>
</complexType>

A 'heavyweight' relationship provides identity for the relationship and an opportunity to have properties on the relationship. To extend the adjacency example, one might wish to have a heavyweight adjacency relationship represented by an AdjacentPair feature type with the length of the common border recorded as a commonBoundaryLength property. This might be encoded in GML as:

<LandParcel fid="Lp2034">
  <area>2345</area>
  <gml:extentOf>...</extentOf>
</LandParcel>
....
<LandParcel fid="Lp2035">
  <area>9812</area>
  <gml:extentOf>...</extentOf>
</LandParcel>
....
<AdjacentPair fid="Ad1465">
  <commonBoundaryLength>231</commonBoundaryLength>
  <adjacentTo xlink:type="simple" xlink:href="#Lp2034"/>
  <adjacentTo xlink:type="simple" xlink:href="#Lp2035"/>
</Adjacent>

Note that in this example the AdjacentPair instances could exist in a separate GML document from the LandParcel features since the adjacentTo properties can point to features outside of the GML document. Whether the instances are in a single or multiple documents, they all conform to the same application schema:

<element name="LandParcel" type="ex:LandParcelType"
  substitutionGroup="gml:_Feature"/>
<element name="adjacentTo" type="ex:AdjacentToType"
  substitutionGroup="gml:featureMember"/>
<element name="AdjacentPair" type="ex:AdjacentPairType"
  substitutionGroup="gml:_Feature"/>

<complexType name="LandParcelType">
  <complexContent>
    <extension base="gml:AbstractFeatureType">
      <sequence>
        <element name="area" type="integer"/>
        <element ref="gml:extentOf"/>
        <!-- note adjacentTo has been removed -->
      </sequence>
    </extension>
  </complexContent>
</complexType>

<complexType name="AdjacentToType">
  <complexContent>
    <restriction base="gml:FeatureAssociationType">
      <sequence>
        <element ref="ex:LandParcel"/>
      </sequence>
    </restriction>
  </complexContent>
</complexType>

<complexType name="AdjacentPairType">
  <complexContent>
    <extension base="gml:AbstractFeatureType">
      <sequence>
        <element name="commonBoundaryLength" type="integer"/>
        <element ref="ex:adjacentTo" minOccurs="2" maxOccurs="2"/>
      </sequence>
    </extension>
  </complexContent>
</complexType>

The use of extended-type XLink elements offers a more concise means of handling n-ary associations and support for creating third-party linkbases. However, such topics are beyond the scope of this document and interested readers are encouraged to consult the XLink specification for details.