Converting GML (Geography Markup Language) files looks simple until the reader cannot find the XML schema. A GML file describes its feature types and attributes in a separate XSD that is referenced through the schemaLocation attribute. When that schema has been lost, moved, or cannot be downloaded, the attribute definitions go with it, and a conversion job that worked on your machine starts failing on a build server. This guide shows how to preserve GML schema information during conversion in C# using Aspose.GIS for .NET, and how to prove that features and attributes survived the round trip.
Why Preserving the GML Schema Matters
GML is a popular interchange format because it carries geometry and attribute data together. The structure of that data, meaning the feature types, attribute names, and data types, is defined by an application schema. Aspose.GIS reads this schema to build a layer’s attribute collection, so the schema is what turns raw XML into usable columns in your code, in QGIS, or in ArcGIS.
In real pipelines the schema is often the weakest link. Files are copied without their XSD, schemaLocation points to an outdated URL, or the server running the conversion has no internet access. In these cases Aspose.GIS stops with a GisException explaining that it failed to build the feature attribute collection. The GmlOptions.RestoreSchema option solves this by allowing the reader to reconstruct the attribute schema from the feature data itself, so your conversions keep their attributes instead of failing or producing incomplete output.
Getting Started with Aspose.GIS for .NET
Aspose.GIS for .NET is a managed library for reading, writing, and converting GIS formats such as GML, Shapefile, GeoJSON, KML, and File Geodatabase, without requiring ArcGIS or QGIS on the machine. Add it to your project from NuGet:
Install-Package Aspose.GIS
Or with the .NET CLI:
dotnet add package Aspose.GIS
You can learn more on the Aspose.GIS for .NET product page and in the Aspose.GIS .NET API Reference. The two namespaces used in this tutorial are Aspose.Gis, which contains VectorLayer, Drivers, and ConversionOptions, and Aspose.Gis.Formats.Gml, which contains GmlOptions.
Step-by-Step Tutorial to Preserve GML Schema
The following C# example converts a GML file to a new GML file while restoring the attribute schema, then verifies the result. It targets .NET 6 or later.
What the example does
- Creates reader options with
GmlOptions.RestoreSchemaset totrue. - Opens the source GML and records its feature count and attribute names.
- Converts the file with
VectorLayer.Convert, passing the reader options throughConversionOptions.SourceDriverOptions. - Reopens the output with schema restoration and compares it against the source.
using System;
using System.IO;
using System.Linq;
using Aspose.Gis;
using Aspose.Gis.Formats.Gml;
class PreserveGmlSchema
{
static void Main()
{
// Input and output paths. Adjust them to your environment.
string sourcePath = Path.Combine("data", "input.gml");
string destinationPath = Path.Combine("data", "output.gml");
// Step 1: Capture the structure of the source layer.
// RestoreSchema lets the reader infer attributes when the XSD is missing or unreachable.
int sourceFeatureCount;
string[] sourceAttributeNames;
using (VectorLayer source = VectorLayer.Open(sourcePath, Drivers.Gml, CreateReadOptions()))
{
sourceFeatureCount = source.Count;
sourceAttributeNames = source.Attributes.Select(a => a.Name).ToArray();
}
// Step 2: Convert GML to GML. RestoreSchema is a reader option,
// so it is supplied through SourceDriverOptions.
var conversionOptions = new ConversionOptions
{
SourceDriverOptions = CreateReadOptions()
};
VectorLayer.Convert(sourcePath, Drivers.Gml, destinationPath, Drivers.Gml, conversionOptions);
// Step 3: Reopen the output and compare it with the source.
using (VectorLayer output = VectorLayer.Open(destinationPath, Drivers.Gml, CreateReadOptions()))
{
if (output.Count != sourceFeatureCount)
{
throw new InvalidOperationException(
$"Feature count mismatch: source has {sourceFeatureCount}, output has {output.Count}.");
}
string[] outputAttributeNames = output.Attributes.Select(a => a.Name).ToArray();
string[] missingAttributes = sourceAttributeNames.Except(outputAttributeNames).ToArray();
if (missingAttributes.Length > 0)
{
throw new InvalidOperationException(
$"Attributes missing from output: {string.Join(", ", missingAttributes)}");
}
Console.WriteLine($"Converted {output.Count} features with {output.Attributes.Count} attributes:");
foreach (FeatureAttribute attribute in output.Attributes)
{
Console.WriteLine($" {attribute.Name} ({attribute.DataType})");
}
}
}
// A fresh options instance for each read keeps the configuration explicit.
static GmlOptions CreateReadOptions() => new GmlOptions { RestoreSchema = true };
}
Explanation of Each Step
- Creating reader options –
GmlOptionsholds GML-specific driver settings. According to the GmlOptions.RestoreSchema reference, setting it totruemeans the reader no longer requires an XML schema. The driver scans the file for known GML structures and infers the feature classes and their properties. The default isfalse. - Capturing the source structure – Opening the source with
VectorLayer.Opengives you a baseline.layer.Countreturns the number of features, andlayer.Attributesexposes the attribute collection, where eachFeatureAttributehas aNameand aDataType. - Calling
VectorLayer.Convert– The overload used here accepts the source path, source driver, destination path, destination driver, and aConversionOptionsobject.SourceDriverOptionscontrols how the input is read, whileDestinationDriverOptionscontrols how the output is written. SinceRestoreSchemaaffects reading, it goes on the source side. - Verifying the output – The output is reopened with the same reader option so verification does not depend on an XSD being present. Instead of hard-coded numbers, the sample compares the output against the source. It fails when features or attributes are lost and prints the restored attribute names and data types for review. Extra attributes are not treated as errors, because identifiers such as
gml_idmay be exposed differently after conversion.
Reading GML When the Original XSD Is Available
Schema restoration is a fallback. If you still have the original schema file, point the reader to it with SchemaLocation so attribute definitions come from the XSD rather than being inferred:
using System;
using Aspose.Gis;
using Aspose.Gis.Formats.Gml;
var options = new GmlOptions
{
// Space-separated pair: namespace URI, then the path to its XML schema.
SchemaLocation = "http://www.example.com/myfeatures schema.xsd",
LoadSchemasFromInternet = false
};
using (VectorLayer layer = VectorLayer.Open("input.gml", Drivers.Gml, options))
{
Console.WriteLine($"Features: {layer.Count}, attributes: {layer.Attributes.Count}");
}
When SchemaLocation is null (the default), Aspose.GIS reads schemaLocation from the root element of the GML document. LoadSchemasFromInternet is false by default, so schemas referenced by absolute non-file:// URIs are not downloaded unless you enable it.
Get a Free License
Aspose.GIS runs in evaluation mode with limitations until a license is applied. To test the full feature set, request a Free Temporary License and apply it before your first GIS operation:
var license = new Aspose.Gis.License();
license.SetLicense("Aspose.GIS.NET.lic");
Free Additional Resources
Conclusion
Preserving GML schema information during conversion comes down to controlling how the source is read. With GmlOptions.RestoreSchema passed through ConversionOptions.SourceDriverOptions, Aspose.GIS for .NET can rebuild attribute definitions even when the XSD is missing or unreachable, so conversions keep their data instead of failing. Pairing that option with a source-to-output comparison gives you evidence that features and attributes made it through, and switching to SchemaLocation when the original schema is available gives you the most faithful result. Together, these practices make GML conversion reliable in batch jobs, web services, and CI pipelines.
FAQs
1. What does GmlOptions.RestoreSchema actually do?
It lets the Aspose.GIS GML reader parse feature attributes when the XML schema (XSD) referenced by the file is missing or cannot be loaded. The driver scans the document for known GML structures and infers the feature classes and their properties from the data. The default value is false.
2. Do I need to set RestoreSchema for both the conversion and the output file?
Only for files whose schema cannot be loaded. RestoreSchema is a reader option, so during conversion it belongs in ConversionOptions.SourceDriverOptions, and when you reopen the output you pass it to VectorLayer.Open. The sample sets it in both places so the workflow does not depend on an XSD being available.
3. What happens if RestoreSchema is false and the schema is missing?
Aspose.GIS cannot build the feature attribute collection and throws a GisException. The exception message suggests setting RestoreSchema to true, or LoadSchemasFromInternet to true when the schema is hosted online.
4. Is a restored schema identical to the original XSD?
Not necessarily. Aspose.GIS describes schema restoration as error prone because attributes are inferred by scanning the file. Verify the result, as the sample does, and use GmlOptions.SchemaLocation when you have the original XSD.
5. Can I use RestoreSchema when converting GML to Shapefile, GeoJSON, or other formats?
Yes. SourceDriverOptions controls how the GML source is read regardless of the destination driver. The restored attributes are then written using the destination format’s own attribute model.
6. Do I need a license to run this code? No. Without a license, Aspose.GIS runs in evaluation mode with limitations. A free temporary license removes those limitations for testing, and production use requires a purchased license.
