Adding Custom Data

KML offers three ways to add custom data to a KML Feature. Which approach you choose depends on the kind of data you're adding as well as how you plan to use the data in your KML presentation. Specifically, the <ExtendedData> element provides the following mechanisms:

  • <Data> element - allows you to add untyped name/value pairs to the user data associated with a given Feature (NetworkLink, Placemark, GroundOverlay, PhotoOverlay, ScreenOverlay, Document, or Folder). These name/value pairs are displayed in the balloon by default. This information can also be used for entity replacement in the <text> element of <BalloonStyle>. (See the section on Using the BalloonStyle Element as a Template.)
  • <Schema> and <SchemaData> elements - allow you to add typed data to the user data associated with a given Feature.
  • Arbitrary XML data - allows you to preserve user data within a KML file. Google Earth passes this data along with the file and saves it, but does not use it.

Note: These three mechanisms can be combined in the same file. If you're adding different types of data from different sources, it may be appropriate to use the typed data approach (Schema/SchemaData) for some of the custom data and to use untyped data (Data) for other custom data.

Which Approach Should You Use?

In most cases the <Data> element offers the simplest and most powerful mechanism for adding untyped data to a KML Feature. This method is relatively easy to implement, and it offers the advantage of facilitating the use of a BalloonStyle template, which can be applied to all Placemarks in a KML file. (See Entity Replacement for Extended Data Elements for an example of this use.)

The <Schema> and <SchemaData> elements allow you to add typed user data. These elements are offered primarily for users with GIS (Geographic Information System) data. If you have typed data that is used by an external computer application, you will probably need to use the <Schema> and <SchemaData> elements to add structured data types to a Feature. (Google Earth does not use this typed information, but your other application may require it.) Casual users wil probably not need the more technical aspects offered by this mechanism. Like <Data>, <SchemaData> facilitates use of templates for BalloonStyle.

If you simply need to pass data along with a KML file and do not need Google Earth to process the data, use the arbitrary XML data feature, which allows you to reference an XML namespace prefix and pass along the data in the current KML context. For more information, see the section on Arbitrary XML Data.

Adding Untyped Name/Value Pairs

The <Data> element is a simple yet powerful mechanism for adding untyped name/value pairs to a KML Feature. The syntax for this element is as follows:

<ExtendedData>                       
<Data name="string">
  <displayName>...</displayName>    <!-- string -->
   <value>...</value>                <!-- string -->
</Data> </ExtendedData>

The name attribute is a unique ID for this piece of data. The <displayName> element is used when you want to display the name of this data in a user-friendly form. The <displayName> can contain CDATA that includes spaces, URLs, and hyperlinks.

Here is an example of a Placemark that contains custom data about several holes in a golf course:

<kml xmlns="http://www.opengis.net/kml/2.2">
<Document>
  <name>My Golf Course Example</name>
  <Placemark>
    <name>Club house</name>
    <ExtendedData>
      <Data name="holeNumber">
        <value>1</value>
      </Data>
      <Data name="holeYardage">
        <value>234</value>
      </Data>
      <Data name="holePar">
        <value>4</value>
      </Data>
    </ExtendedData>
    <Point>
      <coordinates>-111.956,33.5043</coordinates>
    </Point>
</Placemark> <Placemark> <name>By the lake</name> <ExtendedData> <Data name="holeNumber"> <value>5</value> </Data> <Data name="holeYardage"> <value>523</value> </Data> <Data name="holePar"> <value>5</value> </Data> </ExtendedData> <Point> <coordinates>-111.95,33.5024</coordinates> </Point>
</Placemark> </Document> </kml>

This screen capture shows how the <Data> elements are, by default, displayed in a table in the Placemark's balloon:

Data example using default styling for the balloon

Review: Using the BalloonStyle Element as a Template

In KML, you can define a Style once and assign an ID to it. After defining the Style in this manner, you can reference it multiple times within the KML file (or within other KML files) using the <styleUrl> element. A style defined in this way is referred to as a shared style. The <text> element within <BalloonStyle> supports entity replacement. Individual values can be substituted for each instance of the entity. Standard entities that can be replaced are as follows:

$[name]
Replaced with the name of the Placemark
$[description]
Replaced with the description of the Placemark
$[address]
Replaced with the address of the Placemark
$[id]
Replaced with the ID of the Placemark
$[Snippet]
Replaced with the Snippet of the Placemark
$[geDirections]
Replaced with the To/From driving directions of the Placemark

Entity Replacement for Extended Data Elements

Google Earth also supports entity replacement of certain extended data elements within the <text> element of <BalloonStyle>. The following entities can be referenced within the <text> element:

Variable Replaced With Example
$[name_attribute_of_Data_element] Contents of <value> element holeNumber, holeYardage
$[name_attribute_of_Data/displayName] Contents of <displayName> element Hole Number, Hole Yardage

Here is an example that creates a <BalloonStyle> template for the golf course example. For each Placemark balloon, Google Earth substitutes the name of the Placemark and then writes out information containing the hole number, par, and yardage for each individual hole:

<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2">
<Document>
  <name>Data+BalloonStyle</name>
  <Style id="golf-balloon-style">
    <BalloonStyle>
      <text>
        <![CDATA[
          This is $[name]
          This is hole $[holeNumber]
          The par for this hole is $[holePar]
          The yardage is $[holeYardage]
        ]]>
      </text>
    </BalloonStyle>
  </Style>
  <!-- Shared style sample
        Two Placemarks use the same balloon template
  -->
  <Placemark>
    <name>Club house</name>
    <styleUrl>#golf-balloon-style</styleUrl>
    <ExtendedData>
      <Data name="holeNumber">
        <value>1</value>
      </Data>
      <Data name="holeYardage">
        <value>234</value>
      </Data>
      <Data name="holePar">
        <value>4</value>
      </Data>
    </ExtendedData>
    <Point>
      <coordinates>-111.956,33.5043</coordinates>
    </Point>
  </Placemark>
  <Placemark>
    <name>By the lake</name>
    <styleUrl>#golf-balloon-style</styleUrl>
    <ExtendedData>
      <Data name="holeNumber">
        <value>5</value>
      </Data>
      <Data name="holeYardage">
        <value>523</value>
      </Data>
      <Data name="holePar">
        <value>5</value>
      </Data>
    </ExtendedData>
    <Point>
      <coordinates>-111.95,33.5024</coordinates>
    </Point>
  </Placemark>
</Document>
</kml>

Here is a screen capture of this example:

Data example using default styling for the balloon

Here is a more realistic example of how the <displayName> element would be used. This technique lends itself to localization of the text and more elaborate formatting.

<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2">
<Document>
<name>Entity-Replacement</name>
<Style id="displayName-value">
<BalloonStyle>
<text>
<![CDATA[
This is $[name]<br/>
$[holeNumber/displayName] $[holeNumber]<br/>
$[holePar/displayName] $[holePar]<br/>
$[holeYardage/displayName] $[holeYardage]
]]>
</text>
</BalloonStyle>
</Style>
<!-- Shared style sample
Two Placemarks use the same balloon template
-->
<Placemark>
<name>Club house</name>
<styleUrl>#displayName-value</styleUrl>
<ExtendedData>
<Data name="holeNumber">
<displayName><![CDATA[
<b>This is hole </b>
]]></displayName>
<value>1</value>
</Data>
<Data name="holePar">
<displayName><![CDATA[
<i>The par for this hole is </i>
]]></displayName>
<value>4</value>
</Data>
<Data name="holeYardage">
<displayName><![CDATA[
<b><i>The yardage is </i></b>
]]></displayName>
<value>234</value>
</Data>
</ExtendedData>
<Point>
<coordinates>-111.956,33.5043</coordinates>
</Point>
</Placemark>
<Placemark>
<name>By the lake</name>
<styleUrl>#Entity-Replacement</styleUrl>
<ExtendedData>
<Data name="holeNumber">
<displayName><![CDATA[
<b>This is hole </b>
]]></displayName>
<value>5</value>
</Data>
<Data name="holePar">
<displayName><![CDATA[
<i>The par for this hole is </i>
]]></displayName>
<value>5</value>
</Data>
<Data name="holeYardage">
<displayName><![CDATA[
<b><i>The yardage is </i></b>
]]></displayName>
<value>523</value>
</Data>
</ExtendedData>
<Point>
<coordinates>-111.95,33.5024</coordinates>
</Point>
</Placemark>
</Document>
</kml>

Here is an example of a balloon using this balloon style template:

Adding Typed Data to a Feature

The <Schema> and <SchemaData> elements allow you to add typed data to a Feature. Certain GIS and programming applications require this feature because they deal with typed data.

Overview of Adding Typed Data

To add a custom type to a KML Feature, you perform two basic tasks:

  1. Create the <Schema> element, which declares your new type.
  2. Create instances of the new type using the <SchemaData> element.

Declare the Schema Element

The Schema element declares a structured type. <Schema> is always a child of <Document>. A Document can contain zero or more Schema elements.

The id Attribute

The <Schema> element always has an id attribute, whish is referenced when instances of this type are created (using <SchemaData>). This ID must be unique within the KML file.

The name Attribute

The name attribute, which is used for entity replacement, is optional.

Syntax

The Schema element has the following syntax:

<Schema name="string" id="ID">   
  <SimpleField type="string" name="string">     
    <displayName>...</displayName>            <!-- string -->   
  </SimpleField> 
</Schema> 

A <SimpleField> always has both name and type attributes. If it does not have both attributes, the field is ignored. The name attribute is used for entity replacement in the <text> element of <BalloonStyle>. The type of a Simplefield can be one of the following:

  • string
  • int
  • uint
  • short
  • ushort
  • float
  • double
  • bool

Define Each Instance of the Data

Use the <SchemaData> element to create an instance of the user-defined type. The syntax for <SchemaData> is as follows:

<ExtendedData>                   
  <SchemaData schemaUrl="anyURI">
    <SimpleData name=""> ... </SimpleData>       <!-- string -->
  </SchemaData>
</ExtendedData>

The schemaUrl attribute references the id of the Schema that declares the type (just as a styleUrl references the id of a Style that has already been declared).If schemaUrl is an http address, Google Earth fetches this file across the network. There can be only one instance of a given user-defined type per Placemark.

Example

The following example declares a user-defined type named ScenicVista. This type contains three fields: TrailHeadName, TrailLength and ElevationGain. The TrailHeadName field contains values of type string. The TrailLength field contains values of type double. The ElevationGain field contains values of type int. The Placemark named Easy trail contains an instance of this user type. This instance has a value of "Pi in the sky" for its TrailHeadName field, a value of 3.14159 for its TrailLength field, and a value of 10 for its ElevationGain field.

<kml xmlns="http://www.opengis.net/kml/2.2"> 
<Document>   
  <name>ExtendedData+SchemaData</name>   
  <open>1</open>

  <!-- 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>Length in miles</i>]]></displayName>     
    </SimpleField>     
    <SimpleField type="int" name="ElevationGain">       
      <displayName><![CDATA[<i>Change in altitude</i>]]></displayName>     
    </SimpleField>   
  </Schema> 

<!-- This is analogous to adding three fields to a new element of type TrailHead:

  <TrailHeadType>        
    <TrailHeadName>...</TrailHeadName>        
    <TrailLength>...</TrailLength>        
    <ElevationGain>...</ElevationGain>    
 </TrailHeadType>
--> <!-- Instantiate some Placemarks extended with TrailHeadType fields --> <Placemark> <name>Easy trail</name> <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> <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>

SchemaData example using default styling for the balloon

Entity Replacement for displayName

The Schema/SchemaData mechanism also supports entity replacement in the <text> element of the <BalloonStyle> element.

The <displayName> of <Schema> allows you to supply a user friendly version for a custom data type. Changing the string once in the <Schema> has the effect of changing the <displayName> for all Features that contain that type.

In the <text> element of the <BalloonStyle> element, use the following syntax to qualify the <displayName>:

$[TYPENAME/TYPEFIELD/displayName] 

where

TYPENAME
is the name attribute of <Schema>
TYPEFIELD
is the name attribute of <SimpleField>
displayName
is the <displayName> element within <SimpleField>

The following code adds a BalloonStyle template to the previous SchemaData example. As in the Golf Course example, the template is created using the <Style>, <BalloonStyle>, and <text> elements at the beginning of the Document. Each Placemark in the file references this style template (named "ExtendedData+SchemaData").

<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>

SchemaData example using a BalloonStyle template

Compare the balloon created using a BalloonStyle template to the default balloon style for the same data shown in the previous screen capture.

Adding Arbitrary XML Data to a Feature

The simplest way to add user data to a Feature is to add the data directly as a value of <ExtendedData>. Google Earth preserves this data but does not process it.

Custom data elements added in this way need to include a namespace prefix (xmlns:prefix="namespace"). This prefix can be added to the <kml> element or to the <ExtendedData> element. The external namespace prefix must qualify each instance of user data, as shown in the following example:

<kml xmlns="http://www.opengis.net/kml/2.2">
<Document>
  <name>ExtendedData Test</name>
  <Placemark>
    <name>CampsiteData</name>
    <!-- Imported schema requires use of namespace prefix -->
    <ExtendedData xmlns:camp="http://campsites.com">
      <camp:number>14</camp:number>
      <camp:parkingSpaces>2</camp:parkingSpaces>
      <camp:tentSites>4</camp:tentSites>
    </ExtendedData>
    <Point>
      <coordinates>-114.041,53.7199</coordinates>
    </Point>
  </Placemark>
</Document>
</kml>

Back to top