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

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>

Related

Show "all possible" extended data fields in balloon

Background: Alright so I am working on an application that uses SharpKML to produce a number of Placemarks that each have properties associated with it. I want to show these properties as custom data elements within the popup balloon.
Problem: I cannot seem to be able to set my balloon style to show all of the extended data elements in a table regardless of how many there are or their name.
Please if you can help with this.
Cheers.
Edit:
Added the KML code that is produced.
<Style id="cim-default-conductors">
<LabelStyle>
<color>ff7814b4</color>
<colorMode>normal</colorMode>
<scale>1</scale>
</LabelStyle>
<LineStyle>
<color>ff7814b4</color>
<colorMode>normal</colorMode>
<width>3</width>
</LineStyle>
<BalloonStyle>
<bgColor>ffffffff</bgColor>
<textColor>ff000000</textColor>
<text><![CDATA[<b>$[name]</b><br/>Conductor Spacing: $[amst:phase_spacing_summary]<br/>Description: $[description]<br/>]]></text>
<displayMode>default</displayMode>
</BalloonStyle>
</Style>
================Different kml doc=======================
<Placemark>
<name>CIM_ACLineSegment Name: 17470033 mRID: _111192568740L1</name>
<description>cim:ACLineSegment</description>
<styleUrl>../master.kml#cim-default-conductors</styleUrl> <--references the produced style that is shown above.
<ExtendedData>
<Data name="mRID">
<value>111192568740L1</value>
</Data>
<Data name="name">
<value>17470033</value>
</Data>
<Data name="length">
<value>30</value>
</Data>
<Data name="ratedVoltage">
<value>600</value>
</Data>
<Data name="conductorMaterial">
<value>other</value>
</Data>
</ExtendedData>
<LineString>
<altitudeMode>relativeToGround</altitudeMode>
<coordinates>126.795933456158,-45.6023587778821,0</coordinates>
</LineString>
</Placemark>

How to use SimpleFieldExtension in KML?

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.

KML file in Google Earth shows name of entity replacement

I've got a question referring to the BalloonStyle Tutorial in the KML documentiation:
BalloonStyle Documentation
Playing around with this KML file:
<kml xmlns="http://www.opengis.net/kml/2.2">
<Document>
<name>ExtendedData+SchemaData</name>
<open>1</open>
<!-- Create a balloon template referring to the user-defined type -->
<Style id="trailhead-balloon-template">
<BalloonStyle>
<text>
<![CDATA[
<h2>My favorite trails!</h2>
<br/><br/>
The $[TrailHeadType/TrailHeadName/displayName] is <i>$[TrailHeadType/TrailHeadName]</i>.
The trail is $[TrailHeadType/TrailLength] miles. <br/>
The climb is $[TrailHeadType/ElevationGain] meters. <br/><br/>
]]>
</text>
</BalloonStyle>
</Style>
<!-- Declare the type "TrailHeadType" with 3 fields -->
<Schema name="TrailHeadType" id="TrailHeadTypeId">
<SimpleField type="string" name="TrailHeadName">
<displayName><![CDATA[<b>Trail Head Name</b>]]></displayName>
</SimpleField>
<SimpleField type="double" name="TrailLength">
<displayName><![CDATA[<i>The length in miles</i>]]></displayName>
</SimpleField>
<SimpleField type="int" name="ElevationGain">
<displayName><![CDATA[<i>change in altitude</i>]]></displayName>
</SimpleField>
</Schema>
<!-- Instantiate some Placemarks extended with TrailHeadType fields -->
<Placemark>
<name>Easy trail</name>
<styleUrl>#trailhead-balloon-template</styleUrl>
<ExtendedData>
<SchemaData schemaUrl="#TrailHeadTypeId">
<SimpleData name="TrailHeadName">Pi in the sky</SimpleData>
<SimpleData name="TrailLength">3.14159</SimpleData>
<SimpleData name="ElevationGain">10</SimpleData>
</SchemaData>
</ExtendedData>
<Point>
<coordinates>-122.000,37.002</coordinates>
</Point>
</Placemark>
<Placemark>
<name>Difficult trail</name>
<styleUrl>#trailhead-balloon-template</styleUrl>
<ExtendedData>
<SchemaData schemaUrl="#TrailHeadTypeId">
<SimpleData name="TrailHeadName">Mount Everest</SimpleData>
<SimpleData name="TrailLength">347.45</SimpleData>
<SimpleData name="ElevationGain">10000</SimpleData>
</SchemaData>
</ExtendedData>
<Point>
<coordinates>-121.998,37.0078</coordinates>
</Point>
</Placemark>
</Document>
</kml>
When you remove one of the SimpleData elements, Google Earth shows the Entity Replacement from the Balloon Template. For example you remove the line <SimpleData name="ElevationGain">10000</SimpleData>
it shows up in the Balloon like "The climb is $[TrailHeadType/ElevationGain] meters." Which doesn't look very nice.
Any idea how to tell Google Earth, that it shouldn't display the line from the balloon, if there is a missing SimpleData?
Thanks in Advance
I don't think* you can do what you are asking here - i.e. apply conditional logic within this style text. I have had a similar requirement in the past (certain pieces of data were missing from some of my placemarks) and I ended up applying different styles for each of the possible scenarios of missing information when generating the KML.
It felt both very clunky and if you have a large number of scenarios of one or more items being missing while others exist it could quickly be a mess.
*Would love to be wrong.
UPDATE
Just looked at my code for this, and I actually ended up putting all the text in the placemark fields of my schema, and printing out empty nodes when I did not have data - also less elegant, but did not require additional styles in the end. Based on your example something like:
<BalloonStyle>
<text>
<![CDATA[
<h2>My favorite trails!</h2>
$[TrailHeadType/TrailHeadName/displayName]
$[TrailHeadType/TrailLengthBalloonText]
$[TrailHeadType/ElevationGainBalloonText]
]]>
</text>
</BalloonStyle>
<Placemark>
<name>Difficult trail</name>
<styleUrl>#trailhead-balloon-template</styleUrl>
<ExtendedData>
<SchemaData schemaUrl="#TrailHeadTypeId">
<SimpleData name="TrailHeadName">Mount Everest</SimpleData>
<SimpleData name="TrailLength">347.45</SimpleData>
<SimpleData name="ElevationGain">10000</SimpleData>
<SimpleData name="TrailHeadNameBalloonText"><![CDATA[The trail name is Mount Everest</br>]]></SimpleData>
<SimpleData name="TrailLengthBalloonText"><![CDATA[The trail is 347.45 miles.</br>]]></SimpleData>
<SimpleData name="ElevationGainBalloonText"><![CDATA[The climb is 10000 meters.</br>]]></SimpleData>
</SchemaData>
</ExtendedData>
<Point>
<coordinates>-121.998,37.0078</coordinates>
</Point>
</Placemark>
Then when you have no data you leave that item blank:
<Placemark>
<name>Difficult trail</name>
<styleUrl>#trailhead-balloon-template</styleUrl>
<ExtendedData>
<SchemaData schemaUrl="#TrailHeadTypeId">
<SimpleData name="TrailHeadName">Mount Everest</SimpleData>
<SimpleData name="TrailLength">347.45</SimpleData>
<SimpleData name="ElevationGain">10000</SimpleData>
<SimpleData name="TrailHeadNameBalloonText"><![CDATA[The trail name is Mount Everest</br>]]></SimpleData>
<SimpleData name="TrailLengthBalloonText"></SimpleData>
<SimpleData name="ElevationGainBalloonText"></SimpleData>
</SchemaData>
</ExtendedData>
<Point>
<coordinates>-121.998,37.0078</coordinates>
</Point>
</Placemark>
As my data are changing somehow quite often, I'm now providing a xml file linked to an css file and embed it as an iframe in the description. For offline use, create a kmz and put the xml and css into it.
For a small tutorial have a look here:
http://www.w3schools.com/xml/xml_display.asp
In the kml, it looks as follows:
<description>
<![CDATA[
<iframe src="http://www.w3schools.com/xml/cd_catalog_with_css.xml"></iframe>
]]>
</description>

Changing placemark balloons for hundreds of points

I have a KML file with individual placemarks for gas station locations in the the city. (I had created this in GeoMedia and exported to KML).
I would like to revise the balloon style of each of the placemarks to something similar to one of these balloon styles -
http://earth.google.com/outreach/tutorial_balloon.html
Is there any manner in which I can apply the balloon style to each placemark in the file? Would I have to do it point by point, or can I place the balloon style at the top of the file and have the other placemarks reference that style?
I am very new to KML so any insight would be appreciated.
Thanks
#Matt - I have used your suggestions and tried various iterations but just cant seem to get it right. The file already has the placemarks created - and I want to just edit the style which includes adding logo, remove the directions, and so on.
The new style appears, but the schema text is not appearing in the placemark balloon.
I have pasted some of the code below - any thoughts would be appreciated.
<Schema name="" id="Schema20">
<SimpleField type="xsd:int" name="Building_ID"></SimpleField>
<SimpleField type="xsd:string" name="Building Name"></SimpleField>
<SimpleField type="xsd:string" name="Street Address"></SimpleField>
<SimpleField type="xsd:string" name="Office Type"></SimpleField>
<SimpleField type="xsd:double" name="GFA (m2)"></SimpleField>
<SimpleField type="xsd:string" name="GFA_(sqft)"></SimpleField>
<SimpleField type="xsd:int" name="Storeys"></SimpleField>
<SimpleField type="xsd:int" name="Year Built/Occupied">
</SimpleField></Schema>
<Style id="TestStyle">
<BalloonStyle>
<bgColor>ffffffbb</bgColor>
<text><![CDATA[<b><font color="#CC0000" size="+3">$[name]</font></b><br/><br/>
<font face="Courier">$[description]</font><br/><br/> $[geDirections] ]]>
</text>
</BalloonStyle>
</Style>
<Folder>
<name>Office Buildings</name>
<Placemark>
<name>539</name>
<styleUrl>#TestStyle</styleUrl>
<ExtendedData>
<SchemaData schemaUrl="#Schema20">
<SimpleData name="Building_ID">111</SimpleData>
<SimpleData name="Building Name">Name</SimpleData>
<SimpleData name="Street Address">Address</SimpleData>
<SimpleData name="Office Type">Secondary Office</SimpleData>
<SimpleData name="GFA (m2)">100</SimpleData>
<SimpleData name="GFA_(sqft)">1000</SimpleData>
<SimpleData name="Storeys">5</SimpleData>
<SimpleData name="Year Built/Occupied">2010</SimpleData>
</SchemaData>
</ExtendedData><Point>
<coordinates>-122.370533,37.823842,0</coordinates></Point>
</Placemark>
..... 1000 more like this
#Matt -
What I am running into is that if I use in the balloon style, then the data from the Schema which I referenced in my earlier post does not appear in the balloon.
If I leave the blank then the Schema will appear in the balloon.
Do you know how I can have both appear?
Thanks,
<BalloonStyle>
<text>
<![CDATA[<img align="right" src="http://www.website.com/logo.jpg" width="175">]]>
$[description]
</text>
<bgColor>ffffffbb</bgColor>
</BalloonStyle>
you can use styleUrl for you placemarks (which you will need to apply to all of your placemarks that you want to have a selected style):
<styleUrl>#someIDforStyle</styleUrl>
if the style section is in a different file then just add in the link:
<styleUrl>styles\pathToFile\StyleFile.kml#someIDforStyle</styleUrl>
both above will link a certain Style with that ID similar to:
<Style id='someIDforStyle'>
<BalloonStyle>
<text>
<![CDATA[ ....
your are going to want to add html here to make your balloons similar to that link
...
]]>
</text>
</BalloonStyle>
</Style>
you might check this kml link out for adding Custom Data: https://developers.google.com/kml/documentation/extendeddata

Google Earth elevation profile and the missing values

I have some nice data from research aircrafts that I put into kml-files like the example below. If you check the elevation profile, you find the
extended Data plotted nicely.
My problem: my data contains missing values. If I try an empty in place of the missing data, the extended data doesn't appear
more in the profile frame (you can delete one of the floats in the gx-value pair to see).
My question to you: Is there any hack to make GoogleEarth draw the profile without the missing values (i.e. interrupted)?
Or do you know a way to give the GE developers a feedback?
<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:gx="http://www.google.com/kml/ext/2.2" xmlns:kml="http://www.opengis.net/kml/2.2" xmlns:xal="urn:oasis:names:tc:ciq:xsdschema:xAL:2.0">
<Document id="feat_1">
<Style id="stylesel_0">
<LineStyle>
<color>ff0000ff</color>
<colorMode>normal</colorMode>
<width>4</width>
</LineStyle>
</Style>
<visibility>1</visibility>
<Schema id="schema_1" name="Flight Track">
<gx:SimpleArrayField name="bb" type="int">
<displayName>Flight Track</displayName>
</gx:SimpleArrayField>
</Schema>
<Placemark id="feat_2">
<name>example</name>
<styleUrl>#stylesel_0</styleUrl>
<gx:Track>
<gx:coord>-140.0 10.0 0.0</gx:coord>
<gx:coord>-133.572123903 7.66044443119 4131.75911167</gx:coord>
<gx:coord>-130.15192247 1.73648177667 9698.46310393</gx:coord>
<gx:coord>-131.339745962 -5.0 7500.0</gx:coord>
<gx:coord>-136.579798567 -9.39692620786 1169.77778441</gx:coord>
<gx:coord>-143.420201433 -9.39692620786 1169.77778441</gx:coord>
<gx:coord>-148.660254038 -5.0 7500.0</gx:coord>
<gx:coord>-149.84807753 1.73648177667 9698.46310393</gx:coord>
<gx:coord>-146.427876097 7.66044443119 4131.75911167</gx:coord>
<gx:coord>-140.0 10.0 5.99864288729e-28</gx:coord>
<altitudeMode>absolute</altitudeMode>
<ExtendedData>
<SchemaData schemaUrl="#schema_1">
<gx:SimpleArrayData name="ext">
<gx:value>0.00217237382056</gx:value>
<gx:value>0.107224360838</gx:value>
<gx:value>1.99669920652</gx:value>
<gx:value>14.0278818114</gx:value>
<gx:value>37.1819210687</gx:value>
<gx:value>37.1819210687</gx:value>
<gx:value>14.0278818114</gx:value>
<gx:value>1.99669920652</gx:value>
<gx:value>0.107224360838</gx:value>
<gx:value>0.00217237382056</gx:value>
</gx:SimpleArrayData>
</SchemaData>
</ExtendedData>
</gx:Track>
</Placemark>
</Document>
</kml>
This does look like a bug.
I have created an issue at http://code.google.com/p/earth-issues/issues/detail?id=1399
If you star it then you will be notified of any updates.
Meanwhile you may wish to preprocess your KML data and place interpolated values where you have missing ExtendedData.

Resources