How to use SimpleFieldExtension in KML? - xsd

I'm creating a geopositioning application and we intent to use KML as our import/export data scructure.
We need to store extra information on field definitions, but I'm having trouble understant how to use KML SimpleFieldExtension (in fact my problem is understant XML Schema and validation).
The Google KML tutorial https://developers.google.com/kml/documentation/extendeddata doesn't teach how to do it.
I understand that SimpleFieldExtension is an abstract element and there is no concrect element in the KML specfication.
<element name="SimpleFieldExtension" abstract="true"/>
So I need to extend it and create my own, rigth?
I would like to do something like this:
<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2">
<Document>
<Schema name="mySchemaName" id="mySchemaId">
<SimpleField type="xsd:int" name="myValue">
<displayName>MyValue</displayName>
<mySimpleFieldExtension>
<someExtraInfo>...</someExtraInfo>
<otherExtraInfo>...</otherExtraInfo>
</mySimpleFieldExtension>
</SimpleField>
</Schema>
<!-- Some placemarks with myValue fields -->
</Document>
</kml>
When I was trying to figure this out, I came with the impression that I need to create a .xsd file with my own mySimpleFieldExtension, and some how points the .kml file to it. But I'm not sure if that is the right path.
<element name="mySimpleFieldExtension" substitutionGroup="kml:SimpleFieldExtension"/>
Can some one give me an example? Thank you in advance.
I'm using http://www.kmlvalidator.com/ to check my files.

If you want to create SimpleFieldExtension elements and validate it then you will need to create an XML Schema (.xsd) and refer that file in your KML documents.
Example XML Schema with KML extension:
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema"
xmlns:kml="http://www.opengis.net/kml/2.2"
xmlns:ext="http://myextension"
targetNamespace="http://myextension"
elementFormDefault="qualified"
version="2.2.0">
<import namespace="http://www.opengis.net/kml/2.2"
schemaLocation="http://schemas.opengis.net/kml/2.2.0/ogckml22.xsd" />
<element name="SimpleMetadata" type="ext:SimpleMetadataType"
substitutionGroup="kml:SimpleFieldExtension"/>
<complexType name="SimpleMetadataType" final="#all">
<sequence>
<element name="description" type="string"/>
<element name="observedProperty">
<complexType>
<simpleContent>
<extension base="string">
<attribute name="type" type="string" use="required"/>
</extension>
</simpleContent>
</complexType>
</element>
<any namespace="##other" processContents="lax" minOccurs="0"
maxOccurs="unbounded"/>
</sequence>
</complexType>
</schema>
Here's KML document:
<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ext="http://myextension"
xsi:schemaLocation="http://myextension ext.xsd
http://www.opengis.net/kml/2.2 http://schemas.opengis.net/kml/2.2.0/ogckml22.xsd">
<Document>
<Schema id="SensorTypesId" name="SensorTypes">
<SimpleField name="model" type="string"/>
<SimpleField name="reason" type="string"/>
<SimpleField name="speed" type="double">
<ext:SimpleMetadata>
<ext:description>this is the true air speed of a given
aircraft in meters per second</ext:description>
<ext:observedProperty type="urn:ogc:def:phenomenon:OGC:speed" />
</ext:SimpleMetadata>
</SimpleField>
</Schema>
...
A proposed example of a SimpleFieldExtension and discussion can be found here.
Note that http://www.kmlvalidator.com/ checks the strict KML specification and doesn't check KML extensions such as Google's KML extensions so you won't be able to validate custom extensions either.
You can validate such a KML document using the XML Validator which is a standalone command-line validator.
You'll need to add the namespace definition in the XML Validator ns.map config file:
http://myextension=${XV_HOME}/schemas/ext.xsd
or absolute path like this:
http://myextension=C:/myPath/ext.xsd
Even though the SimpleFieldExtension is supported by the KML standard, adding a custom SimpleFieldExtension through a custom XML Schema requires more testing to verify it doesn't cause problems to applications using it especially if you plan to share your KML outside your organization. Applications like Google Earth will simply ignore your extensions so only use extensions when you absolutely must.

Related

How to generate a KML with nested attributes and attributes with cardinality greater than one

I have a set of events that I want to export to KML. Those events have nested attributes and attributes with cardinality greater than one (maxOccur > 1).
Here is an example of one event presented as JSON:
{
"id": 1,
"date": "2018-01-01",
"client": {
"name": "Brad",
"since": "2017-12-01"
},
"products": [
{
"name": "P1",
"quantity": 20
},
{
"name": "P2",
"quantity": 40
},
]
}
One option that we are considering is use an arbitrary XML at ExtendedData. This option sounds good for Machine-to-Machine data interchange, but not for human read, because the Google Earth does not show those data very well in balloons:
<ExtendedData>
<id>1</id>
<date>2018-01-01</date>
<client>
<name>Brad</name>
<since>2017-12-01</since>
</client>
<products>
<product>
<name>P1</name>
<quantity>20</quantity>
</product>
<product>
<name>P2</name>
<quantity>40</quantity>
</product>
</products>
</ExtendedData>
Other option that we are considering is use Schema + SchemaData + BallonStyle, but the cardinality and nested attributes are not supported...
<Schema name="myEvent" id="myEvent">
<SimpleField type="int" name="id">
<displayName>Event id</displayName>
</SimpleField>
<SimpleField type="string" name="date">
<displayName>Event date</displayName>
</SimpleField>
<!-- workaround to nested data -->
<SimpleField type="string" name="clientName">
<displayName>Client name</displayName>
</SimpleField>
<SimpleField type="string" name="clientSince">
<displayName>Client since</displayName>
</SimpleField>
<!-- no idea how present attributes with more than one occurrence -->
</Schema>
There is another option that we should consider?
Data and SimpleData elements in KML ExtendedData are limited to name/value pairs with values as text but custom XML is allowed using a different namespace.
You can add arbitrary XML data to a Feature in KML from a non-KML XML namespace like Dublin core, RDF, or your own namespace. Here is a related tutorial.
Here's an example with arbitrary Dublin core XML in KML:
<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2">
<Document>
<name>ExtendedData Test with Dublin core XML</name>
<Placemark>
<name>Test data</name>
<ExtendedData xmlns:ns="http://example.org/myapp/">
<ns:metadata xmlns:dc="http://purl.org/dc/elements/1.1/">
<dc:description>
KML features a rich mix of
metadata information and services for the XML community.
</dc:description>
<dc:subject>XML, RDF, metadata, information
syndication services</dc:subject>
<dc:identifier>http://earth.google.com</dc:identifier>
<dc:language>en-us</dc:language>
<dc:date>2000-10-13</dc:date>
<dc:rights>Copyright 2000, O'Reilly Network</dc:rights>
<dc:publisher>O'Reilly and Associates, Inc.</dc:publisher>
</ns:metadata>
</ExtendedData>
<Point>
<coordinates>-71.7571,42.953</coordinates>
</Point>
</Placemark>
</Document>
</kml>
With your own namespace, you can store whatever XML you want with whatever nesting.
<Placemark>
<name>Test data</name>
<ExtendedData>
<data xmlns="urn:my.org:data">
<id>1</id>
<date>2018-01-01</date>
<client>
<name>Brad</name>
<since>2017-12-01</since>
</client>
<products>
<product>
<name>P1</name>
<quantity>20</quantity>
</product>
<product>
<name>P2</name>
<quantity>40</quantity>
</product>
</products>
</data>
</ExtendedData>
</Placemark>
Note however that this approach passes along the data within the KML for a machine-to-machine exchange since Google Earth does not process nor display this type of data. A third party application could take advantage of this type of XML data contained within the KML.
If you want at least part of the data to be human-readable via Google Earth, consider a hybrid solution with name-value pairs in Data/value elements for the simple values and a custom XML element for the more complex nested XML data.
<Placemark>
<name>Test data</name>
<ExtendedData>
<Data name="id">
<value>123</value>
</Data>
<Data name="date">
<value>2018-01-01</value>
</Data>
<customData xmlns="urn:custom">
<client>
<name>Brad</name>
<since>2017-12-01</since>
</client>
</customData>
</ExtendedData>
<Point>
<coordinates>-71.7571,42.953</coordinates>
</Point>
</Placemark>

JAXB generated classes of certain types implementing a custom interface

I am working on an application that uses XJC to generate Java POJOs from XSDs. There are dozens of schemas, and that number will grow. The application also needs to be able to handle different versions of the same schema, which means that I will have multiple schemas defining common types. I am trying to customize the bindings so that certain core types implement a common interface. The Inheritance plugin of JAXB2 Basics seems to do what I need, but I can't seem to nail the right syntax.
Here is the relevant part of my schema:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:my="http://example.com/core"
targetNamespace="http://example.com/core"
xmlns:xml="http://www.w3.org/XML/1998/namespace">
...
<xs:complexType name="addressType">
<xs:sequence>
<xs:element name="Address" type="xs:string"/>
<xs:element name="City" type="xs:string"/>
<xs:element name="Province" type="xs:string"/>
<xs:element name="Country" type="xs:string"/>
<xs:element name="County" type="xs:string" minOccurs="0"/>
<xs:element name="PostalCode" type="xs:string"/>
</xs:sequence>
</xs:complexType>
...
</xs:schema>
... and this is what my custom binding file looks like:
<?xml version="1.0"?>
<jaxb:bindings
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
xmlns:inheritance="http://jaxb2-commons.dev.java.net/basic/inheritance"
xmlns:my="http://example.com/core"
jaxb:extensionBindingPrefixes="inheritance"
version="2.1">
<jaxb:bindings scd="x-schema::my" xmlns:my="http://example.com/core">
<jaxb:globalBindings localScoping="toplevel">
<jaxb:serializable/>
<xjc:simple/>
</jaxb:globalBindings>
<jaxb:bindings scd="/type::my:addressType">
<inheritance:implements>com.mysite.validator.ValidatableAddress</inheritance:implements>
<!--<xjc:superInterface name="com.mysite.validator.ValidatableAddress"/>-->
</jaxb:bindings>
</jaxb:bindings>
</jaxb:bindings>
I'm using the scd approach, because in all the "traditional" binding examples that show how to use the inheritence plugin, schemaLocation is specified. I want to avoid having to specify schemaLocation because of our large (and growing) number of schemas. I don't want to have to change the binding file every time we add a new schema. So, scd seems like it will satisfy this requirement.
However when I run the build using the above binding, I get this:
[xjc] [ERROR] cvc-elt.1: Cannot find the declaration of element 'inheritance:implements'.
[xjc] line 18 of file:/dev/workspace/my_app/etc/schemas/bindings-common.xml
[xjc] failure in the XJC task. Use the Ant -verbose switch for more details
[xjc] classLoader = java.net.URLClassLoader#ebcdbb
[xjc] SharedSecrets.getJavaNetAccess()=java.net.URLClassLoader$7#14562c5
If I comment out the inheritance:implements line and uncomment the xjc:superInterface line, the error goes away and the build completes successfully, but my AddressType classes don't implement the ValidatableAddress type.
Can the inheritence plugin be used with scd? Can xjc:superInterface be limited to only certain elements?
Cheers.
Author of jaxb2-basics here.
See this issue in XJC. In short, XJC for some reason does not allow custom/vendor customization elements in SCD bindings.
inheritance:implements is such customization element.
So no, this does not work due a problem in XJC.
I personally bind via schemaLocation and XPath but use a "virtual" schema location URI and rewrite it via catalogs.
SCD would have been a much better choice (you're absolutely right here) but it just does not work.
Update on virtual schema location and catalogs.
Here's an example of binding which customizes some complex type:
<jaxb:bindings
schemaLocation="http://schemas.opengis.net/wps/2.0/wpsCommon.xsd"
node="/xs:schema">
<jaxb:bindings node="xs:element[#name='Data']/xs:complexType">
<wildcard:lax/>
</jaxb:bindings>
</jaxb:bindings>
It is bound via schemaLocation and XPath. The schemaLocation is an existing URL, but in the build it is rewritten via catalog into the resource inside a Maven artifact:
REWRITE_SYSTEM "http://schemas.opengis.net" "maven:org.jvnet.ogc:ogc-schemas:jar::!/ogc"
So basically http://schemas.opengis.net/wps/2.0/wpsCommon.xsd will be loaded from the ogc-schema.jar!/ogc/wps/2.0/wpsCommon.xsd.
Using maven-jaxb2-plugin you can refer to binding files inside Maven artifacts as well:
<binding>
<dependencyResource>
<groupId>${project.groupId}</groupId>
<artifactId>ows-v_2_0</artifactId>
<resource>ows-v_2_0.jsonix.xjb</resource>
<version>${project.version}</version>
</dependencyResource>
</binding>
So, in combination, it allows writing binding files once and reuse them across modules.
But this was all a huge pain to figure out. I did it for the ogc-schemas project which is now some 50 heavily interconnected schemas. I heavily suffer from XJC drawbacks and issues, but this is the best possible at the moment. I even thought about forking and patching XJC, but this is far of effort limits I can afford.
So I've ended up with a number of mindblogging workarounds which somehow do the job at the end of the day.
Thanks to lexicore for the prompt and detailed answers. However that approach wasn't working for me, so I ended up with the following solution...
Because I am using Ant to invoke XJC, I ended up leveraging Ant's <copy filtering="true"...> capabilities to dynamically generate the binding file.
Here is my binding "template" file (bindings-common.xml):
<?xml version="1.0"?>
<jaxb:bindings
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
xmlns:inheritance="http://jaxb2-commons.dev.java.net/basic/inheritance"
xmlns:my="http://http://example.com/core"
jaxb:extensionBindingPrefixes="inheritance"
version="2.1">
<jaxb:bindings>
<jaxb:globalBindings localScoping="toplevel">
<jaxb:serializable/>
<xjc:simple/>
</jaxb:globalBindings>
</jaxb:bindings>
<jaxb:bindings
schemaLocation="#bindingSchema#"
node="/xs:schema">
<jaxb:bindings node="//xs:complexType[#name='addressType']">
<inheritance:implements>com.example.validator.ValidatableAddress</inheritance:implements>
</jaxb:bindings>
</jaxb:bindings>
</jaxb:bindings>
Note this line:
<jaxb:bindings
schemaLocation="#bindingSchema#"
node="/xs:schema">
This variable will get populated by Ant for each of the schemas that I am processing:
<property name="jaxb.binding.template" value="../etc/form-schemas/bindings-common.xml"/>
<property name="jaxb.binding.file" value="${jaxb.src.dir}/bindings-common${schema.version}.xml"/>
<echo message="Filtering ${jaxb.binding.file} using template ${jaxb.binding.template}"/>
<copy file="${jaxb.binding.template}"
tofile="${jaxb.binding.file}"
filtering="true">
<filterset>
<filter token="bindingSchema" value="../../etc/form-schemas/${schema.version}/common.xsd"/>
</filterset>
</copy>
<xjc destdir="${jaxb.src.dir}"
extension="true"
schema="${schema.file}"
package="${package}"
binding="${jaxb.binding.file}">
<arg value="-episode"/>
<arg value="${jaxb.src.dir}/common${schema.version}.episode"/>
<arg line="-Xinheritance"/>
<!-- Plugins -->
<classpath>
<fileset dir="../build-libs/">
<!-- JAXB2 Basics library -->
<include name="jaxb2-basics-0.6.4.jar"/>
<!-- JAXB2 Basics library dependencies -->
<include name="jaxb2-basics-runtime-0.6.4.jar"/>
<include name="jaxb2-basics-tools-0.6.4.jar"/>
<include name="javaparser-1.0.8.jar"/>
<include name="commons-beanutils-*.jar"/>
<include name="commons-lang-*.jar"/>
<include name="commons-logging-*.jar"/>
</fileset>
</classpath>
</xjc>
</target>
Hopefully this will help future generations of JAXB victims.

jaxb-generate classes from wsdl ,each schema classes should go to corrsponding package

i have one wsdl file which have schhemas included in it, i want to generate java classes for each schema in different package,please help me.
i have used following code,its generating classes related to all schemas
<?xml version="1.0" encoding="UTF-8"?>
<jaxb:bindings version="1.0"
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<jaxb:bindings schemaLocation="Event.xsd" node="/xsd:schema">
<jaxb:schemaBindings>
<jaxb:package name="com.event.dto" />
<jaxb:nameXmlTransform>
<jaxb:typeName suffix="CHASE"/>
</jaxb:nameXmlTransform>
For each shema file add xml like in your question, but with different name of
<jaxb:package name="com.event.dto" />

Explanation of target namespaces in Xml schema?

For example, let us say we have the following schema (listed in http://www.w3.org/TR/xmlschema-0/#NS)
<schema xmlns="http://www.w3.org/2001/XMLSchema"
xmlns:po="http://www.example.com/PO1"
targetNamespace="http://www.example.com/PO1"
elementFormDefault="unqualified"
attributeFormDefault="unqualified">
<element name="purchaseOrder" type="po:PurchaseOrderType"/>
<element name="comment" type="string"/>
<complexType name="PurchaseOrderType">
<sequence>
<element name="shipTo" type="po:USAddress"/>
<element name="billTo" type="po:USAddress"/>
<element ref="po:comment" minOccurs="0"/>
<!-- etc. -->
</sequence>
<!-- etc. -->
</complexType>
<complexType name="USAddress">
<sequence>
<element name="name" type="string"/>
<element name="street" type="string"/>
<!-- etc. -->
</sequence>
</complexType>
<!-- etc. -->
</schema>
Can you explain what the purpose of each of the attributes in the "schema" node mean? I have been trying to wrap my head around it, but I don't get it. Please correct me if I am wrong:
I assume xmlns="http://www.w3.org/2001/XMLSchema" refers to elements & attributes that have no prefix.
xmlns:po="http://www.example.com/PO1" seems like it means that anything prefixed with po, refers to this url (example.com/p01).
I don't understand what targetNamespace is for. I also don't understand what qualified or unqualified means.
This is a bit of a terminology minefield, but essentially, xmlns="http://www.w3.org/2001/XMLSchema" and xmlns:po="http://www.example.com/PO1" are there to declare namespaces for the schema document itself. Remember, an XML Schema is just an XML document, and it needs to declare the namespaces it uses just like any other XML document.
targetNamespace is used to define the namespace of the schema's instance documents, i.e. the documents which will conform to your schema. Such documents would declare their namespace to be http://www.example.com/PO1, with whatever prefix they choose e.g. they could use xmlns="http://www.example.com/PO1" or xmlns:po="http://www.example.com/PO1"

Disallow an element to be a child of itself in XML Schema

Im writing a XML schema for a project. I cannot solve following problem:
A element cannot be nested by itself, ex:
<document>
<text>
<b>
<i>
<a link="http://wikipedia.org">
<b />
</a>
</i>
</b>
</text>
</document>
This example shouldn't be allow because the b is nesting itself. So my question for you is: "Is it possible to disallow a element to nest it self, and if yes whats the procedure to do the trick?"
Thx in advantage!
\Morten Møller
Edit:
Until now I only have made sure that a element can be a child of itself, but not that a element cant have a descendant that is itself.
<?xml version="1.0"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema"
xmlns:xs="http://cs.au.dk/dWebTek/WikiXML"
targetNamespace="http://cs.au.dk/dWebTek/WikiXML"
elementFormDefault="qualified">
<element name="wiki">
<complexType>
<choice maxOccurs="unbounded">
<!-- A lot of other element is listed here -->
<element name="bold" type="xs:boldnest"/> <!-- Missing nest function -->
</choice>
<complexType>
</element>
<complexType name="boldnest">
<choice maxOccurs="unbounded">
<element name="bold" minOccurs="0" maxOccurs="0" type="xs:boldnest"/>
<!-- All the other element is copy pasted in here -->
</choice>
</complexType>
What you are trying to do is not possible. In XML Schema, if you are using a type-based approach, you can only control the children of an element through the content model, not all possible descendants.
The only way you could possibly get close to what you are trying to do is to fully define the contents of document down to the last level. But you cannot establish a recursive structure and then put in place the sort of constraint you are thinking of.
You will need to validate this using some other mechanism, after XML schema validation is done.

Resources