We make use of a traditional XML transform idiom to produce XML content. The Transform walks through an existing data structure generating SAX events during the walk.
Writing a Style to a SLD document
The SLD 1.0 specification defines a document format for style information. GeoTools has an style transformer that can generate these documents.
SLDTransformer styleTransform = new SLDTransformer(); String xml = styleTransform.transform(sld);
The SLD 1.0 specification provides the schema for these documents here:
They also provide an example file:
Writing a FeatureCollection to XML
You are warned that the Transform may visit data several times during the output of a FeatureCollection (once to generate the bounds, and a second to output the content).
FeatureCollection features = ... OutputStream output = ... FeatureTransformer transform = new FeatureTranformer(); // optional set up transform.setIndentation(4); transform.getFeatureNamesapces().declarePrefix("myns","http://somewhere.org"); transform.setSrsName( "EPSG:4326" ); // generate XML transform.transform( features, output );
You are warned that some transformations (like the above GML FeatureCollection output) perform better when additional information (like namespace) provided before the transformation is called. The "myns" is supposed to line up with an XML Schema document which you have defined
to describe your document.
About GML and your Application Schema
There is no such thing as a "GML" document; you need to created your own XML Schema. Your XML Schema will extends GML concepts like AbstractFeature and define specific concepts from your application - like ROAD, RIVER, CITY etc...
This line is where you tell the Transform about your XML Schema:
ft.getFeatureNamesapces().declarePrefix("myns","http://somewhere.org");
About SRS
Internally in GeoTools we use real CoordianteReferenceSystem instances to record what the numbers mean. In GML they use a simple string called "SRS" (ie Spatial Reference System).
transform.setSrsName( "EPSG:4326" );
It is common practice to make the SRS the same as the identifier for your CoordainteReferenceSystem. But really this is just an "understanding" between you and the people who are going to read your document.
FeatureType type = collection.getSchema(); CoordinateReferenceSystem crs = type.getDefaultGeometry().getCoordianteReferenceSystem(); transform.setSrsName( crs.getIdentifier().toString() );
Example from Email
The following example has yet to be placed into subversion:
// Important to note: this solution only works with a single homogeneous FeatureType in the FeatureCollection. FeatureType ft = fc.getSchema(); FeatureTransformer tx = new FeatureTransformer(); // set the SRS for the entire featureCollection. tx.setSrsName(ft.getDefaultGeometry().getAuthority().getIdentifier().toString() ); // set the namespace and the prefix tx.getFeatureTypeNamespaces().declareNamespace(ft,"wps", ft.getNamespace().toASCIIString()); // also work-around, get the schema of the featureType Schema s = SchemaFactory.getInstance(ft.getNamespace()); // define a schemaLocation and allow thereby validation! tx.addSchemaLocation(ft.getNamespace().toASCIIString(),s.getURI().toASCIIString());
Thanks to foerster@itc.nl for the example.
|
Although this point was made above - it is worth repeating. The GML specification does not describe a document format, it does include an XMLSchema - but all the good parts are abstract. You need to roll your own schema. |
How to Roll Your Own Schema
I am going to wimp out here and just give you an example generated by GeoServer:
<?xml version="1.0" encoding="UTF-8"?> <xs:schema targetNamespace="http://www.openplans.org/topp" xmlns:topp="http://www.openplans.org/topp" xmlns:gml="http://www.opengis.net/gml" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:citef="http://www.opengis.net/cite/functions" elementFormDefault="qualified" attributeFormDefault="unqualified" version="1.0"> <xs:import namespace="http://www.opengis.net/gml" schemaLocation="http://schemas.opengis.net/gml/2.1.2/feature.xsd" /> <xs:complexType xmlns:xs="http://www.w3.org/2001/XMLSchema" name="states_Type"> <xs:complexContent> <xs:extension base="gml:AbstractFeatureType"> <xs:sequence> <xs:element name="the_geom" minOccurs="0" nillable="true" type="gml:MultiPolygonPropertyType" /> <xs:element name="STATE_NAME" minOccurs="0" nillable="true"> <xs:simpleType> <xs:restriction base="xs:string"> <xs:maxLength value="25" /> </xs:restriction> </xs:simpleType> </xs:element> <xs:element name="STATE_FIPS" minOccurs="0" nillable="true"> <xs:simpleType> <xs:restriction base="xs:string"> <xs:maxLength value="2" /> </xs:restriction> </xs:simpleType> </xs:element> <xs:element name="SUB_REGION" minOccurs="0" nillable="true"> <xs:simpleType> <xs:restriction base="xs:string"> <xs:maxLength value="7" /> </xs:restriction> </xs:simpleType> </xs:element> <xs:element name="STATE_ABBR" minOccurs="0" nillable="true"> <xs:simpleType> <xs:restriction base="xs:string"> <xs:maxLength value="2" /> </xs:restriction> </xs:simpleType> </xs:element> <xs:element name="LAND_KM" minOccurs="0" nillable="true" type="xs:double" /> <xs:element name="WATER_KM" minOccurs="0" nillable="true" type="xs:double" /> <xs:element name="PERSONS" minOccurs="0" nillable="true" type="xs:double" /> <xs:element name="FAMILIES" minOccurs="0" nillable="true" type="xs:double" /> <xs:element name="HOUSHOLD" minOccurs="0" nillable="true" type="xs:double" /> <xs:element name="MALE" minOccurs="0" nillable="true" type="xs:double" /> <xs:element name="FEMALE" minOccurs="0" nillable="true" type="xs:double" /> <xs:element name="WORKERS" minOccurs="0" nillable="true" type="xs:double" /> <xs:element name="DRVALONE" minOccurs="0" nillable="true" type="xs:double" /> <xs:element name="CARPOOL" minOccurs="0" nillable="true" type="xs:double" /> <xs:element name="PUBTRANS" minOccurs="0" nillable="true" type="xs:double" /> <xs:element name="EMPLOYED" minOccurs="0" nillable="true" type="xs:double" /> <xs:element name="UNEMPLOY" minOccurs="0" nillable="true" type="xs:double" /> <xs:element name="SERVICE" minOccurs="0" nillable="true" type="xs:double" /> <xs:element name="MANUAL" minOccurs="0" nillable="true" type="xs:double" /> <xs:element name="P_MALE" minOccurs="0" nillable="true" type="xs:double" /> <xs:element name="P_FEMALE" minOccurs="0" nillable="true" type="xs:double" /> <xs:element name="SAMP_POP" minOccurs="0" nillable="true" type="xs:double" /> </xs:sequence> </xs:extension> </xs:complexContent> </xs:complexType> <xs:element name='states' type='topp:states_Type' substitutionGroup='gml:_Feature' /> </xs:schema>
We should be able to hunt down the code where they generate the schema from a FeatureType.
You can find the GML 2.1.2 xml schema to use as a starting place here: