Supported GML flavors :
OGR version | Read | Write |
---|---|---|
OGR >= 1.8.0 | GML2 and GML3 that can be translated into simple feature model |
GML 2.1.2 or GML 3 SF-0 (GML 3.1.1 Compliance level SF-0) |
OGR < 1.8.0 | GML2 and limited GML3 | GML 2.1.2 |
Starting with GDAL 2.2, another driver, GMLAS, for GML driven by application schemas, is also available. Both GML and GMLAS drivers have their use cases.
Note: starting with OGR 1.9.0, if both Xerces and Expat are available at build time, the GML driver will preferentially select at runtime the Expat parser for cases where it is possible (GML file in a compatible encoding), and default back to Xerces parser in other cases. However, the choice of the parser can be overridden by specifying the GML_PARSER configuration option to EXPAT or XERCES.
There also situations where the srsName is of the form "EPSG:XXXX" (whereas "urn:ogc:def:crs:EPSG::XXXX" would have been more explicit on the intent) and the coordinates in the file are in (latitude, longitude) order. By default, OGR will not consider the EPSG axis order and will report the coordinates in (latitude,longitude) order. However, if you set the configuration option GML_CONSIDER_EPSG_AS_URN to YES, the rules explained in the previous paragraph will be applied.
Since OGR 1.10, the above also applied for projected coordinate systems whose EPSG preferred axis order is (northing, easting).
Starting with GDAL 2.1.2, the SWAP_COORDINATES open option (or GML_SWAP_COORDINATES configuration option) can be set to AUTO/YES/NO. It controls whether the order of the x/y or long/lat coordinates should be swapped. In AUTO mode, the driver will determine if swapping must be done from the srsName and value of other options like CONSIDER_EPSG_AS_URN and INVERT_AXIS_ORDER_IF_LAT_LONG. When SWAP_COORDINATES is set to YES, coordinates will be always swapped regarding the order they appear in the GML, and when it set to NO, they will be kept in the same order. The default is AUTO.
Starting with OGR 1.10, it is possible to specify an explicit filename for the XSD schema to use, by using "a_filename.gml,xsd=another_filename.xsd" as a connection string. Staring with GDAL 2.0, the XSD can also be specified as the value of the XSD open option.
The first time a GML file is opened, if the associated .xsd is absent or could not been parsed correctly, it is completely scanned in order to determine the set of featuretypes, the attributes associated with each and other dataset level information. This information is stored in a .gfs file with the same basename as the target gml file. Subsequent accesses to the same GML file will use the .gfs file to predefine dataset level information accelerating access. To a limited extent the .gfs file can be manually edited to alter how the GML file will be parsed. Be warned that the .gfs file will be ignored if the associated .gml file has a newer timestamp.
When prescanning the GML file to determine the list of feature types, and fields, the contents of fields are scanned to try and determine the type of the field. In some applications it is easier if all fields are just treated as string fields. This can be accomplished by setting the configuration option GML_FIELDTYPES to the value ALWAYS_STRING.
Starting with GDAL 1.11, the GML_ATTRIBUTES_TO_OGR_FIELDS configuration option can be set to YES so that attributes of GML elements are also taken into account to create OGR fields.
Configuration options can be set via the CPLSetConfigOption() function or as environment variables.
Since OGR 1.8.0, a specialized GML driver - the NAS driver - is available to read German AAA GML Exchange Format (NAS/ALKIS).
Since OGR 1.8.0, the GML driver has partial support for reading AIXM or CityGML files.
Since OGR 1.11, the GML driver supports reading :
Since OGR 2.2, the GML driver supports reading Japanese FGD GML v4 files.
But, starting with OGR 1.11, if the .xsd schema is understood by the XSD parser and declares several geometry fields, or the .gfs file declares several geometry fields, multiple geometry fields will be reported by the GML driver according to RFC 41.
Starting with OGR 1.10, in case of multiple geometry occurrences, if a geometry is in a <geometry> element, this will be the one selected. This will make default behaviour consistent with Inspire objects.
Starting with OGR 1.8.0, the user can change the .gfs file to select the appropriate geometry by specifying its path with the <GeometryElementPath> element. See the description of the .gfs syntax below.
OGR 1.8.0 adds support for more GML geometries including TopoCurve, TopoSurface, MultiCurve. The TopoCurve type GML geometry can be interpreted as either of two types of geometries. The Edge elements in it contain curves and their corresponding nodes. By default only the curves, the main geometries, are reported as OGRMultiLineString. To retrieve the nodes, as OGRMultiPoint, the configuration option GML_GET_SECONDARY_GEOM should be set to the value YES. When this is set only the secondary geometries are reported.
Starting with GDAL 2.0, Arc, ArcString, ArcByBulge, ArcByCenterPoint, Circle and CircleByCenterPoints will be returned as circular string OGR geometries. If they are included in other GML elements such as CurveComposite, MultiCurve, Surface, corresponding non-linear OGR geometries will be returned as well. When reading GML3 application schemas, declarations of geometry fields such as CurvePropertyType, SurfacePropertyType, MultiCurvePropertyType or MultiSurfacePropertyType will be also interpreted as being potential non-linear geometries, and corresponding OGR geometry type will be used for the layer geometry type.
By default the resolved file will be saved in the same directory as the original file with the extension ".resolved.gml", if it doesn't exist already. This behaviour can be changed using the configuration option GML_SAVE_RESOLVED_TO. Set it to SAME to overwrite the original file. Set it to a filename ending with .gml to save it to that location. Any other values are ignored. If the resolver cannot write to the file for any reason, it will try to save it to a temporary file generated using CPLGenerateTempFilename("ResolvedGML"); if it cannot, resolution fails.
Note that the resolution algorithm is not optimized for large files. For files with more than a couple of thousand xlink:href tags, the process can go beyond a few minutes. A rough progress is displayed through CPLDebug() for every 256 links. It can be seen by setting the environment variable CPL_DEBUG. The resolution time can be reduced if you know any elements that will not be needed. Mention a comma separated list of names of such elements with the configuration option GML_SKIP_RESOLVE_ELEMS. Set it to ALL to skip resolving altogether (default action). Set it to NONE to resolve all the xlinks.
Starting since OGR 1.9.0 an alternative resolution method is available. This alternative method will be activated using the configuration option GML_SKIP_RESOLVE_ELEMS HUGE. In this case any gml:xlink will be resolved using a temporary SQLite DB so to identify any corresponding gml:id relation. At the end of this SQL-based process, a resolved file will be generated exactly as in the NONE case but without their limits. The main advantages in using an external (temporary) DBMS so to resolve gml:xlink and gml:id relations are the following:
Starting since OGR 1.9.0 the GML driver is able to recognize two different interpretation rules for TopoSurface when a polygon contains any internal hole:
NOTE : Using the newest interpretation requires GDAL/OGR to be built against the GEOS library.
Using the GML_FACE_HOLE_NEGATIVE configuration option you can anyway select the actual interpretation to be applied when parsing GML 3 Topologies:
The content returned by OGR will be encoded in UTF-8, after the conversion from the encoding mentioned in the file header is.
If the GML file is not encoded in one of the previous encodings and the only parser available is Expat, it will not be parsed by the GML driver. You may convert it into one of the supported encodings with the iconv utility for example and change accordingly the encoding parameter value in the XML header.
When writing a GML file, the driver expects UTF-8 content to be passed in.
Note: The .xsd schema files are parsed with an integrated XML parser which does not currently understand XML encodings specified in the XML header. It expects encoding to be always UTF-8. If attribute names in the schema file contains non-ascii characters, it is better to use iconv utility and convert the .xsd file into UTF-8 encoding first.
Starting with OGR 1.9.0, the driver autodetects the presence of a fid (GML2) (resp. gml:id (GML3)) attribute at the beginning of the file, and, if found, exposes it by default as a fid (resp. gml_id) field. The autodetection can be overridden by specifying the GML_EXPOSE_FID or GML_EXPOSE_GML_ID configuration option to YES or NO.
Starting with OGR 1.9.0, when creating a GML2 document, if a field is called fid, its content will also be used to write the content of the fid attribute of the created feature.
Starting with OGR 1.9.0, the GML_READ_MODE configuration option can be set to SEQUENTIAL_LAYERS if all features belonging to the same layer are written sequentially in the file. The reader will then avoid unnecessary resets when layers are read completely one after the other. To get the best performance, the layers must be read in the order they appear in the file.
If no .xsd and .gfs files are found, the parser will detect the layout of layers when building the .gfs file. If the layers are found to be sequential, a <SequentialLayers>true</SequentialLayers> element will be written in the .gfs file, so that the GML_READ_MODE will be automatically initialized to SEQUENTIAL_LAYERS if not explicitly set by the user.
Starting with OGR 1.9.0, the GML_READ_MODE configuration option can be set to INTERLEAVED_LAYERS to be able to read a GML file whose features from different layers are interleaved. In the case, the semantics of the GetNextFeature() will be slightly altered, in a way where a NULL return does not necessarily mean that all features from the current layer have been read, but it could also mean that there is still a feature to read, but that belongs to another layer. In that case, the file should be read with code similar to the following one :
int nLayerCount = poDS->GetLayerCount(); int bFoundFeature; do { bFoundFeature = FALSE; for( int iLayer = 0; iLayer < nLayerCount; iLayer++ ) { OGRLayer *poLayer = poDS->GetLayer(iLayer); OGRFeature *poFeature; while((poFeature = poLayer->GetNextFeature()) != NULL) { bFoundFeature = TRUE; poFeature->DumpReadable(stdout, NULL); OGRFeature::DestroyFeature(poFeature); } } } while (bInterleaved && bFoundFeature);
The GML writer supports the following dataset creation options:
The driver supports reading and writing to files managed by VSI Virtual File System API, which include "regular" files, as well as files in the /vsizip/ (read-write) , /vsigzip/ (read-write) , /vsicurl/ (read-only) domains.
Writing to /dev/stdout or /vsistdout/ is also supported. Note that in that case, only the content of the GML file will be written to the standard output (and not the .xsd). The <boundedBy> element will not be written. This is also the case if writing in /vsigzip/
<?xml version="1.0" encoding="UTF-8"?> <gml:FeatureCollection xmlns:gml="http://www.opengis.net/gml"> <gml:featureMember> <LAYER> <attrib1>attrib1_value</attrib1> <attrib2container> <attrib2>attrib2_value</attrib2> </attrib2container> <location1container> <location1> <gml:Point><gml:coordinates>3,50</gml:coordinates></gml:Point> </location1> </location1container> <location2> <gml:Point><gml:coordinates>2,49</gml:coordinates></gml:Point> </location2> </LAYER> </gml:featureMember> </gml:FeatureCollection>and the following associated .gfs file.
<GMLFeatureClassList> <GMLFeatureClass> <Name>LAYER</Name> <ElementPath>LAYER</ElementPath> <GeometryElementPath>location1container|location1</GeometryElementPath> <PropertyDefn> <Name>attrib1</Name> <ElementPath>attrib1</ElementPath> <Type>String</Type> <Width>13</Width> </PropertyDefn> <PropertyDefn> <Name>attrib2</Name> <ElementPath>attrib2container|attrib2</ElementPath> <Type>String</Type> <Width>13</Width> </PropertyDefn> </GMLFeatureClass> </GMLFeatureClassList>Note the presence of the '|' character in the <ElementPath> and <GeometryElementPath> elements to specify the wished field/geometry element that is a nested XML element. Nested field elements are only supported from OGR 1.8.0, as well as specifying <GeometryElementPath> If GeometryElementPath is not specified, the GML driver will use the last recognized geometry element.
The <GeometryType> element can be specified to force the geometry type. Accepted values are : 0 (any geometry type), 1 (point), 2 (linestring), 3 (polygon), 4 (multipoint), 5 (multilinestring), 6 (multipolygon), 7 (geometrycollection).
Starting with OGR 1.11, the <GeometryElementPath> and <GeometryType> can be specified as many times as there are geometry fields in the GML file. Another possibility is to define a <GeomPropertyDefn>element as many times as necessary:
<GMLFeatureClassList> <GMLFeatureClass> <Name>LAYER</Name> <ElementPath>LAYER</ElementPath> <GeomPropertyDefn> <Name>geometry</Name> <-- OGR geometry name --> <ElementPath>geometry</ElementPath> <!-- XML element name possibly with '|' to specify the path --> <Type>MultiPolygon</Type> </GeomPropertyDefn> <GeomPropertyDefn> <Name>referencePoint</Name> <ElementPath>referencePoint</ElementPath> <Type>Point</Type> </GeomPropertyDefn> </GMLFeatureClass> </GMLFeatureClassList>
The output of ogrinfo test.gml -ro -al is:
Layer name: LAYER Geometry: Unknown (any) Feature Count: 1 Extent: (3.000000, 50.000000) - (3.000000, 50.000000) Layer SRS WKT: (unknown) Geometry Column = location1container|location1 attrib1: String (13.0) attrib2: String (13.0) OGRFeature(LAYER):0 attrib1 (String) = attrib1_value attrib2 (String) = attrib2_value POINT (3 50)
<?xml version="1.0" encoding="utf-8"?> <gml:FeatureCollection xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" gml:id="foo" xmlns:gml="http://www.opengis.net/gml/3.2"> <gml:featureMember> <TopLevelObject gml:id="TopLevelObject.1"> <content> <Object gml:id="Object.1"> <geometry> <gml:Polygon gml:id="Object.1.Geometry" srsName="urn:ogc:def:crs:EPSG::4326"> <gml:exterior> <gml:LinearRing> <gml:posList srsDimension="2">48 2 49 2 49 3 48 3 48 2</gml:posList> </gml:LinearRing> </gml:exterior> </gml:Polygon> </geometry> <foo>bar</foo> </Object> </content> <content> <Object gml:id="Object.2"> <geometry> <gml:Polygon gml:id="Object.2.Geometry" srsName="urn:ogc:def:crs:EPSG::4326"> <gml:exterior> <gml:LinearRing> <gml:posList srsDimension="2">-48 2 -49 2 -49 3 -48 3 -48 2</gml:posList> </gml:LinearRing> </gml:exterior> </gml:Polygon> </geometry> <foo>baz</foo> </Object> </content> </TopLevelObject> </gml:featureMember> </gml:FeatureCollection>By default, only the TopLevelObject object would be reported and it would only use the second geometry. This is not the desired behaviour in that instance. You can edit the generated .gfs and modify it like the following in order to specify a full path to the element (top level XML element being omitted) :
<GMLFeatureClassList> <GMLFeatureClass> <Name>Object</Name> <ElementPath>featureMember|TopLevelObject|content|Object</ElementPath> <GeometryType>3</GeometryType> <PropertyDefn> <Name>foo</Name> <ElementPath>foo</ElementPath> <Type>String</Type> </PropertyDefn> </GMLFeatureClass> </GMLFeatureClassList>
Let's consider the following test.gml file :
<?xml version="1.0" encoding="UTF-8"?> <gml:FeatureCollection xmlns:gml="http://www.opengis.net/gml"> <gml:featureMember> <LAYER> <length unit="m">5</length> </LAYER> </gml:featureMember> </gml:FeatureCollection>and the following associated .gfs file.
<GMLFeatureClassList> <GMLFeatureClass> <Name>LAYER</Name> <ElementPath>LAYER</ElementPath> <GeometryType>100</GeometryType> <!-- no geometry --> <PropertyDefn> <Name>length</Name> <ElementPath>length</ElementPath> <Type>Real</Type> </PropertyDefn> <PropertyDefn> <Name>length_unit</Name> <ElementPath>length@unit</ElementPath> <Type>String</Type> </PropertyDefn> </GMLFeatureClass> </GMLFeatureClassList>The output of ogrinfo test.gml -ro -al is:
Layer name: LAYER Geometry: None Feature Count: 1 Layer SRS WKT: (unknown) gml_id: String (0.0) length: Real (0.0) length_unit: String (0.0) OGRFeature(LAYER):0 gml_id (String) = (null) length (Real) = 5 length_unit (String) = m
Several <PropertyDefn> can be defined with the same <ElementPath>, but with <Condition> that must be mutually exclusive.
Let's consider the following testcondition.gml file :
<?xml version="1.0" encoding="utf-8" ?> <ogr:FeatureCollection xmlns:ogr="http://ogr.maptools.org/" xmlns:gml="http://www.opengis.net/gml"> <gml:featureMember> <ogr:testcondition fid="testcondition.0"> <ogr:name lang="en">English name</ogr:name> <ogr:name lang="fr">Nom francais</ogr:name> <ogr:name lang="de">Deutsche name</ogr:name> </ogr:testcondition> </gml:featureMember> </ogr:FeatureCollection>and the following associated .gfs file.
<GMLFeatureClassList> <GMLFeatureClass> <Name>testcondition</Name> <ElementPath>testcondition</ElementPath> <GeometryType>100</GeometryType> <PropertyDefn> <Name>name_en</Name> <ElementPath>name</ElementPath> <Condition>@lang='en'</Condition> <Type>String</Type> </PropertyDefn> <PropertyDefn> <Name>name_fr</Name> <ElementPath>name</ElementPath> <Condition>@lang='fr'</Condition> <Type>String</Type> </PropertyDefn> <PropertyDefn> <Name>name_others_lang</Name> <ElementPath>name@lang</ElementPath> <Condition>@lang!='en' and @lang!='fr'</Condition> <Type>StringList</Type> </PropertyDefn> <PropertyDefn> <Name>name_others</Name> <ElementPath>name</ElementPath> <Condition>@lang!='en' and @lang!='fr'</Condition> <Type>StringList</Type> </PropertyDefn> </GMLFeatureClass> </GMLFeatureClassList>The output of ogrinfo testcondition.gml -ro -al is:
Layer name: testcondition Geometry: None Feature Count: 1 Layer SRS WKT: (unknown) fid: String (0.0) name_en: String (0.0) name_fr: String (0.0) name_others_lang: StringList (0.0) name_others: StringList (0.0) OGRFeature(testcondition):0 fid (String) = testcondition.0 name_en (String) = English name name_fr (String) = Nom francais name_others_lang (StringList) = (1:de) name_others (StringList) = (1:Deutsche name)
An alternate location for the registry file can be defined by setting its full pathname to the GML_REGISTRY configuration option.
An example of such a file is :
<gml_registry> <!-- Finnish National Land Survey cadastral data --> <namespace prefix="ktjkiiwfs" uri="http://xml.nls.fi/ktjkiiwfs/2010/02" useGlobalSRSName="true"> <featureType elementName="KiinteistorajanSijaintitiedot" schemaLocation="http://xml.nls.fi/XML/Schema/sovellus/ktjkii/modules/kiinteistotietojen_kyselypalvelu_WFS/Asiakasdokumentaatio/ktjkiiwfs/2010/02/KiinteistorajanSijaintitiedot.xsd"/> <featureType elementName="PalstanTunnuspisteenSijaintitiedot" schemaLocation="http://xml.nls.fi/XML/Schema/sovellus/ktjkii/modules/kiinteistotietojen_kyselypalvelu_WFS/Asiakasdokumentaatio/ktjkiiwfs/2010/02/palstanTunnuspisteenSijaintitiedot.xsd"/> <featureType elementName="RekisteriyksikonTietoja" schemaLocation="http://xml.nls.fi/XML/Schema/sovellus/ktjkii/modules/kiinteistotietojen_kyselypalvelu_WFS/Asiakasdokumentaatio/ktjkiiwfs/2010/02/RekisteriyksikonTietoja.xsd"/> <featureType elementName="PalstanTietoja" schemaLocation="http://xml.nls.fi/XML/Schema/sovellus/ktjkii/modules/kiinteistotietojen_kyselypalvelu_WFS/Asiakasdokumentaatio/ktjkiiwfs/2010/02/PalstanTietoja.xsd"/> </namespace> <!-- Inspire CadastralParcels schema --> <namespace prefix="cp" uri="urn:x-inspire:specification:gmlas:CadastralParcels:3.0" useGlobalSRSName="true"> <featureType elementName="BasicPropertyUnit" gfsSchemaLocation="inspire_cp_BasicPropertyUnit.gfs"/> <featureType elementName="CadastralBoundary" gfsSchemaLocation="inspire_cp_CadastralBoundary.gfs"/> <featureType elementName="CadastralParcel" gfsSchemaLocation="inspire_cp_CadastralParcel.gfs"/> <featureType elementName="CadastralZoning" gfsSchemaLocation="inspire_cp_CadastralZoning.gfs"/> </namespace> <!-- Czech RUIAN (VFR) schema (v1) --> <namespace prefix="vf" uri="urn:cz:isvs:ruian:schemas:VymennyFormatTypy:v1 ../ruian/xsd/vymenny_format/VymennyFormatTypy.xsd" useGlobalSRSName="true"> <featureType elementName="TypSouboru" elementValue="OB" gfsSchemaLocation="ruian_vf_ob_v1.gfs"/> <featureType elementName="TypSouboru" elementValue="ST" gfsSchemaLocation="ruian_vf_st_v1.gfs"/> </namespace> </gml_registry>XML schema definition (.xsd) files are pointed by the schemaLocation attribute, whereas OGR .gfs files are pointed by the gfsSchemaLocation attribute. In both cases, the filename can be a URL (http://, https://), an absolute filename, or a relative filename (relative to the location of gml_registry.xml).
The schema is used if and only if the namespace prefix and URI are found in the first bytes of the GML file (e.g. xmlns:ktjkiiwfs="http://xml.nls.fi/ktjkiiwfs/2010/02"), and that the feature type is also detected in the first bytes of the GML file (e.g. ktjkiiwfs:KiinteistorajanSijaintitiedot). If the element value is defined than the schema is used only if the feature type together with the value is found in the first bytes of the GML file (e.g. vf:TypSouboru>OB_UKSH).
OGRFeature(myFeature):1 gml_id (String) = myFeature.1 [...] otherFeature_href (StringList) = (2:#otherFeature.10,#otherFeature.20) OGRFeature(myFeature):2 gml_id (String) = myFeature.2 [...] otherFeature_href (StringList) = (2:#otherFeature.30,#otherFeature.10)After running
ogr2ogr -f PG PG:dbname=mydb my.gmlto import it into PostGIS and
python ogr_build_junction_table.py PG:dbname=mydb, a myfeature_otherfeature table will be created and will contain the following content :
myfeature_gml_id | otherfeature_gml_id |
---|---|
myFeature.1 | otherFeature.10 |
myFeature.1 | otherFeature.20 |
myFeature.2 | otherFeature.30 |
myFeature.2 | otherFeature.10 |
Such datasets typically look like:
<wfs:FeatureCollection xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:app="http://app.com" xmlns:wfs="http://www.opengis.net/wfs/2.0" xmlns:gml="http://www.opengis.net/gml/3.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" numberMatched="unknown" numberReturned="2" timeStamp="2015-01-01T00:00:00.000Z" xsi:schemaLocation="http://www.opengis.net/gml/3.2 http://schemas.opengis.net/gml/3.2.1/gml.xsd http://www.opengis.net/wfs/2.0 http://schemas.opengis.net/wfs/2.0/wfs.xsd"> <wfs:member> <wfs:Tuple> <wfs:member> <app:table1 gml:id="table1-1"> <app:foo>1</app:foo> </app:table1> </wfs:member> <wfs:member> <app:table2 gml:id="table2-1"> <app:bar>2</app:bar> <app:baz>foo</app:baz> <app:geometry><gml:Point gml:id="table2-2.geom.0"><gml:pos>2 49</gml:pos></gml:Point></app:geometry> </app:table2> </wfs:member> </wfs:Tuple> </wfs:member> <wfs:member> <wfs:Tuple> <wfs:member> <app:table1 gml:id="table1-2"> <app:bar>2</app:bar> <app:geometry><gml:Point gml:id="table1-1.geom.0"><gml:pos>3 50</gml:pos></gml:Point></app:geometry> </app:table1> </wfs:member> <wfs:member> <app:table2 gml:id="table2-2"> <app:bar>2</app:bar> <app:baz>bar</app:baz> <app:geometry><gml:Point gml:id="table2-2.geom.0"><gml:pos>2 50</gml:pos></gml:Point></app:geometry> </app:table2> </wfs:member> </wfs:Tuple> </wfs:member> </wfs:FeatureCollection>
OGR will group together the attributes from the layers participating to the join and will prefix them with the layer name. So the above example will be read as the following:
OGRFeature(join_table1_table2):0 table1.gml_id (String) = table1-1 table1.foo (Integer) = 1 table1.bar (Integer) = (null) table2.gml_id (String) = table2-1 table2.bar (Integer) = 2 table2.baz (String) = foo table2.geometry = POINT (2 49) OGRFeature(join_table1_table2):1 table1.gml_id (String) = table1-2 table1.foo (Integer) = (null) table1.bar (Integer) = 2 table2.gml_id (String) = table2-2 table2.bar (Integer) = 2 table2.baz (String) = bar table1.geometry = POINT (3 50) table2.geometry = POINT (2 50)
ogr2ogr -f GML output.gml OCI:usr/pwd@db my_feature -where "id = 0"
The ogr2ogr utility can be used to dump the results of a PostGIS query to GML:
ogr2ogr -f GML output.gml PG:'host=myserver dbname=warmerda' -sql "SELECT pop_1994 from canada where province_name = 'Alberta'"