Tuesday, January 25, 2011

Address Locator Style: Customizing Guide

Please read “Address Locator Style: Introduction” before reading this post.

Editing the Locator Style files:

I am going through this guide by ESRI.

What am I changing?

For me it’s to create an address locator without state (here in Israel we don’t have a state).

Also an optional change is adding common spelling mistakes in Hebrew to the mix.

 

Basic Change: Name and Description

1. Copied: USAddress.lot.xml, LocatorStyle.xsd, and LocatorStyle.xslt to my projects folder.

2. Rename USAddress.lot.xml

3. Change the name and description for the address locator:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <?xml-stylesheet type="text/xsl" href="LocatorStyle.xslt"?>
  3. <locators xsi:noNamespaceSchemaLocation="LocatorStyle.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  4.   <locator>
  5.     <name>Dll Shepherd Address</name>
  6.     <desc>Locator style for Dll Shepherd addresses</desc>
  7.     <version>10</version>

 

Change: create an address locator without state

1. Create ref_data_style with the name City Street House Number

  1. <ref_data_style>
  2.   <name>City Street House Number</name>
  3.   <desc>City,Street and House Number</desc>
  4.   <table_roles>
  5.     <table_role name="Primary">
  6.       <display_name>Primary Table</display_name>
  7.       <desc>streets feature class</desc>
  8.       <field_roles>
  9.         <field_role name="Primary.Shape" is_geometry="true">
  10.           <display_name>Geometry</display_name>
  11.           <preferred_name>Shape</preferred_name>
  12.         </field_role>
  13.         <field_role name="Primary.ID">
  14.           <display_name>Feature ID</display_name>
  15.           <preferred_name>ID</preferred_name>
  16.           <preferred_name>POINTID</preferred_name>
  17.           <preferred_name>FEATUREID</preferred_name>
  18.           <preferred_name>FEATURE_ID</preferred_name>
  19.           <preferred_name>FEAT_ID</preferred_name>
  20.           <preferred_name>FEATUREID_1</preferred_name>
  21.           <preferred_name>FEATUREID_2</preferred_name>
  22.           <preferred_name>DYNAMAPID</preferred_name>
  23.           <preferred_name>DYNAMAP_ID</preferred_name>
  24.           <preferred_name>DYNAMAPID_1</preferred_name>
  25.           <preferred_name>DYNAMAPID_2</preferred_name>
  26.           <preferred_name>OBJECTID</preferred_name>
  27.           <preferred_name>OBJECT_ID</preferred_name>
  28.           <preferred_name>OBJECTID_1</preferred_name>
  29.           <preferred_name>OBJECTID_2</preferred_name>
  30.           <preferred_name>FID</preferred_name>
  31.           <preferred_name>FID_1</preferred_name>
  32.           <preferred_name>FID_2</preferred_name>
  33.           <preferred_name>AREAID</preferred_name>
  34.           <preferred_name>LINK_ID</preferred_name>
  35.           <preferred_name>AREA_ID</preferred_name>
  36.           <preferred_name>LINKID</preferred_name>
  37.           <preferred_name>TLID</preferred_name>
  38.         </field_role>
  39.         <field_role name="Primary.CityName">
  40.           <display_name>CityName</display_name>
  41.           <preferred_name>CityName</preferred_name>
  42.           <preferred_name>CityNameEng</preferred_name>
  43.           <preferred_name>CITY_NAME</preferred_name>
  44.           <preferred_name>CITY</preferred_name>
  45.           <preferred_name>City</preferred_name>
  46.           <preferred_name>CityCode</preferred_name>
  47.           <preferred_name>CITY_CODE</preferred_name>
  48.         </field_role>
  49.         <field_role name="Primary.StreetName">
  50.           <display_name>StreetName</display_name>
  51.           <preferred_name>StreetName</preferred_name>
  52.           <preferred_name>StreetNameEng</preferred_name>
  53.           <preferred_name>STREET_NAME</preferred_name>
  54.           <preferred_name>STREET</preferred_name>
  55.           <preferred_name>Street</preferred_name>
  56.           <preferred_name>StreetCode</preferred_name>
  57.           <preferred_name>STREET_CODE</preferred_name>
  58.         </field_role>
  59.         <field_role name="Primary.HouseNumber">
  60.           <display_name>HouseNumber</display_name>
  61.           <preferred_name>HouseNumber</preferred_name>
  62.           <preferred_name>HOUSE_NUMBER</preferred_name>
  63.           <preferred_name>House</preferred_name>
  64.           <preferred_name>HouseNum</preferred_name>
  65.           <preferred_name>HOUSE</preferred_name>
  66.         </field_role>
  67.         <field_role name="Primary.User_fld">
  68.           <display_name>Additional Field</display_name>
  69.         </field_role>
  70.       </field_roles>
  71.     </table_role>
  72.   </table_roles>
  73.   <data_source type="indexed">
  74.     <mapping_schema ref="REG_COUNTRY" />
  75.     <queries>
  76.       <query>
  77.         <tables>
  78.           <table role_ref="Primary" />
  79.         </tables>
  80.         <fields>
  81.           <field ref="Shape" field_role_ref="Primary.Shape" />
  82.           <field ref="ID" field_role_ref="Primary.ID" />
  83.           <field ref="CityName" field_role_ref="Primary.CityName" />
  84.           <field ref="StreetName" field_role_ref="Primary.StreetName" />
  85.           <field ref="HouseNumber" field_role_ref="Primary.HouseNumber" />
  86.           <field ref="User_fld" field_role_ref="Primary.User_fld" />
  87.         </fields>
  88.       </query>
  89.     </queries>
  90.   </data_source>

I haven’t touched <inputs> and <multiline_grammar> since I don’t know how they work. Testing this now will throw an exception…

2. Since in the previous step we did:

  1. <data_source type="indexed">
  2.   <mapping_schema ref="REG_COUNTRY" />
  3.   <queries>
  4.     <query>
  5.       <tables>
  6.         <table role_ref="Primary" />
  7.       </tables>
  8.       <fields>
  9.         <field ref="Shape" field_role_ref="Primary.Shape" />
  10.         <field ref="ID" field_role_ref="Primary.ID" />
  11.         <field ref="CityName" field_role_ref="Primary.CityName" />
  12.         <field ref="StreetName" field_role_ref="Primary.StreetName" />
  13.         <field ref="HouseNumber" field_role_ref="Primary.HouseNumber" />
  14.         <field ref="User_fld" field_role_ref="Primary.User_fld" />
  15.       </fields>
  16.     </query>
  17.   </queries>
  18. </data_source>

Then we need to create the REG_COUNTRY mapping_schema with those fields. Like ZIP:

  1. <field name="ZIP" grammar_ref="ZIP5">
  2.   <desc>ZIP code</desc>
  3.   <preferred_name>ZIP</preferred_name>
  4.   <preferred_name>ZIPCODE</preferred_name>
  5. </field>

But what is the grammar for CityName? Well inside grammar->Zones->ZIP5:

  1. <def name="ZIP5">
  2.   <alt>`[0-9][0-9][0-9][0-9][0-9]`</alt>
  3. </def>

(It defines ZIP5 as a string of 5 numeric characters)

Looking above it I found:

  1. <def name="City">
  2.   <alias_list_ref ref="CityAliases"/>
  3.   <alt ref="wordlist"/>
  4. </def>

(This defines City as a string of words (wordlist is word+wordlist (who loves recursive?)))

The good news is that House is defined but the bad news Street is not. But that is easily fixable we will just add below City:

  1. <def name="Street">
  2.   <alt ref="wordlist"/>
  3. </def>

(You can use City for that as well but I prefer creating this definition that later can be customized (for example street must start with “St.” can be defined here)

Later I found this definition for street:

  1. <def name="StName">
  2.   <alias_list_ref ref="StreetNameAliases"/>
  3.   <alt ref="name"/>
  4. </def>

Back to our mapping schema, well I started with a copy of USZIP and changed the name and descriptions:

  1. <mapping_schema name="REG_COUNTRY" geom_type="point">
  2.   <desc>Inner Country schema - city,street,house</desc>
  3.   <desc>Point features containing Inner Country schema - city,street,house.</desc>
  4.   <fields>

(Shape and Id I kept the same)

  1. <field name="CityName" grammar_ref="City">
  2.   <desc>City Name</desc>
  3.   <preferred_name>CityName</preferred_name>
  4.   <preferred_name>CITY_NAME</preferred_name>
  5. </field>
  6. <field name="StreetName" grammar_ref="Street">
  7.   <desc>Street Name</desc>
  8.   <preferred_name>StreetName</preferred_name>
  9.   <preferred_name>STREET_NAME</preferred_name>
  10. </field>
  11. <field name="HouseNumber" grammar_ref="House">
  12.   <desc>House Number</desc>
  13.   <preferred_name>HouseNumber</preferred_name>
  14.   <preferred_name>HOUSE_NUMBER</preferred_name>
  15. </field>

(I kept User_fld since it’s not required and I just don’t know what it does)

Next <index> this I decided to copy+change from SingleAddress, this defines how the index of the data is going to be built:

  1. <index>
  2.   <dictionary ref="House"/>
  3.   <dictionary ref="StreetName" search="true"/>
  4.   <dictionary ref="City" search="true"/>
  5.   <dictionary ref="ID" type="ids"/>
  6.   <relationship>
  7.     <field_ref ref="ZIP"/>
  8.   </relationship>
  9.   <reverse_relationship>
  10.     <field_ref ref="House"/>
  11.     <field_ref ref="StreetName"/>
  12.     <field_ref ref="City"/>
  13.     <field_ref ref="ID"/>
  14.     <field_ref ref="User_fld"/>
  15.   </reverse_relationship>
  16. </index>

Outputs, hope it works:

  1. <outputs>
  2.   <output ref="Shape" type="geometry"/>
  3.   <output component="Status" candidate_mode="false" length="1"/>
  4.   <output component="Score" type="float" decimal_digits="2"/>
  5.   <output name="Match_addr" length="100">
  6.     <format>
  7.       <field_value ref="House"/>
  8.       <field_value ref="StreetName"/>
  9.       <field_value ref="City"/>
  10.     </format>
  11.   </output>
  12.   <output name="Ref_ID" ref="ID" type="fromdata" selector="WriteReferenceIDField"/>
  13.   <output ref="User_fld" type="string" length="120" selector="WriteAdditionalOutputFields" />
  14.   <output component="Match_time" type="float" selector="ShowElapsedTime"/>
  15. </outputs>

Reverse GeoCoding, I just copy changed this to my needs:

  1. <reverse_geocoding>
  2.   <reverse_geocoding_method name="Address">
  3.     <outputs>
  4.       <output ref="Shape" type="geometry" />
  5.       <output ref="ZIP" length="5" />
  6.       <output component="Match_time" type="float" selector="ShowElapsedTime"/>
  7.     </outputs>
  8.   </reverse_geocoding_method>
  9. </reverse_geocoding>

Result (cross my fingers and hope it works):

  1. <reverse_geocoding>
  2.   <reverse_geocoding_method name="Address">
  3.     <outputs>
  4.       <output ref="Shape" type="geometry" />
  5.       <output ref="House" length="15" />
  6.       <output ref="StreetName" length="100" />
  7.       <output ref="City" length="100" />
  8.       <output component="Match_time" type="float" selector="ShowElapsedTime"/>
  9.     </outputs>
  10.   </reverse_geocoding_method>
  11. </reverse_geocoding>

I just commented standardization (hope it’s not needed)

Testing got me this Exception:

System.InvalidCastException was unhandled by user code
  Message=Unable to cast COM object of type 'System.__ComObject' to interface type 'ESRI.ArcGIS.Location.IReferenceDataTables'. This operation failed because the QueryInterface call on the COM component for the interface with IID '{600A5898-DDC1-11D3-9F74-00C04F8ED1C4}' failed due to the following error: No such interface supported (Exception from HRESULT: 0x80004002 (E_NOINTERFACE)).

 

 

Testing

Testing the changes: with ArcCatalog

TODO: I don’t really have ArcCatalog…

Testing the changes: with ArcObjects

I wrote a post about it and it can be found here.

 

TODO: add a link to the introduction

TODO: add a link to the arcObjects testing

TODO: Fix introduction post

Resources:

Customizing ArcGIS 10 locators (An Esri Geocoding Technical Paper)

Keywords: ESRI, ArcGis Server, geocode, geocoding, address locator