Attribute Element (Handling Multiple Values)

The xfMap <attribute> element provides two different ways to handle attributes that contain multiple values; these reflect the way in which an FME feature interpret all of its attributes, as (name, value) pairs with the name being the attribute’s identifier. An FME feature can also store a collection of attributes by using an attribute list. Attribute lists behave like primitive attributes, i.e, (name, value) pairs, except that they contain indices enclosed in braces {} in its attribute name.

When we want to get information from the XML document stream into an attribute of the FME feature, and that information maps to an attribute with multiple values, then we can either:

  1. use a “primitive attribute” and append, with a separator character, the multiple values into one string, or
  2. use the FME attribute list, or
  3. retain one attribute value out of the multiple values.

The <attribute> element has an optional type attribute that specifies how an attribute is to be mapped into an FME feature. The valid values for the type attribute are: multi-value, list, and single-value, which correspond to the a), b) and c) options above, respectively.

Multi-value Option

When the value of the type attribute is multi-value, then the <attribute> element can carry an additional optional delim attribute that specifies the separator to be used for the appended string of values. The delim attribute defaults to a comma when it is not specified.

The following example sets the separator for the appended values to be the pipe character:

<attribute type=”multi-value” delim=”|”/>
...
</attribute>

An extra attribute on the FME feature may also be created counting the number of values in the multi-value attribute. The create-count-attribute is an optional attribute that can be used when the type attribute is set to multi-value; its valid values are yes and no, with no being its default value.

The name of the count attribute is based on the same name specified in the expression sequence of the <attribute>’s <name> element augmented by an optional prefix and a mandatory suffix.

The count attribute’s prefix and suffix may be specified through the count-attribute-name-prefix and count-attribute-name-suffix attributes, respectively.

Both count-attribute-name-prefix and count-attribute-name-suffix are optional attributes. The default value for the count-attribute-name-prefix is the empty string, while the default value for the count-attribute-name-suffix is Count. The count-attribute-name-suffix must not be the empty string when it is present.

List Option

When the value of the type attribute is list, then a multiple value attribute in the input XML document stream will be converted into an attribute list for the FME feature that is under construction.

Single-value Option

This is the default value for the type attribute. An attribute with a particular name can only have one value in the FME feature.

The <attribute> element can carry an additional optional use attribute that specifies if the first, last or any of the values in between the first or last value out of the multiple values should be used. The legal values for this attribute are: first-value, last-value, or any natural number in 0...(last-value - 1). When it is not specified, the use attribute defaults to the last-value. If the natural numbers are used instead and if they overspecified the number of multi-value attributes from the input XML stream, then the last-value will be assumed.

Example

The following example illustrates multiple value handling. Consider the following input XML and xfMap document:

purchase.xml

<?xml version="1.0"?>
<purchase date="1999-10-20">
	<items>
		<item>Radio</item>
		<item>Toothbrush</item>
		<item>Towel</item>
		<item>Soap</item>
		<item>Bottled Water</item>
	</items>
</purchase>

purchase.xmp

<?xml version="1.0"?>
<!DOCTYPE xfMap SYSTEM "xfMap.dtd">
<xfMap>

<feature-map>
	<mapping match="purchase">
		<feature-type>
			<literal expr="purchase-"/> <extract expr="@date"/>
		</feature-type>
	</mapping>
</feature-map>

<feature-content-map>
	<!-- This mapping rule matching the ‘item’ element will be activated
		5 times (the number of ‘item’ elements). -->
	<mapping match="item">
		<attributes>
			<!-- Gather all of the items into the multiple value
				attribute ‘items1’, since the attribute element
				does not have a delim attribute, the default separator,
				i.e., the comma, is used as the delimeter for the appended
				string of values. -->
			<attribute type="multi-value">
				<name> <literal expr="items1"/> </name>
				<value> <extract expr="."/> </value>
			</attribute>
			<!-- Same as above except that we name the attribute ‘items2’ 
				and we specify the delimiter to be the colon character. -->
			<attribute type="multi-value" delim=":">
				<name> <literal expr="items2"/> </name>
				<value> <extract expr="."/> </value>
			</attribute>
			<!-- Make an FME attribute list named ‘list’ out of the items. -->
			<attribute type="list">
				<name> <literal expr="list-attr"/> </name>
				<value> <extract expr="."/> </value>
			</attribute>
			<!-- Use the first value of the items. -->
			<attribute type="single-value" use="first-value">
				<name> <literal expr="first-item"/> </name>
				<value> <extract expr="."/> </value>
			</attribute>
			<!-- Use the last value of the items. -->	
			<attribute type="single-value">
				<name> <literal expr="last-item"/> </name>
				<value> <extract expr="."/> </value>
			</attribute>
			<!-- Use the 4th item. -->		
			<attribute type="single-value" use=”3”>
				<name> <literal expr="item-at-3-(4th item)"/> </name>
				<value> <extract expr="."/> </value>
			</attribute>
		</attributes>
	</mapping>
</feature-content-map>

</xfMap>

The following shows a log of the FME feature constructed when the purchase.xml and purchase.xmp documents are fed into the XML Reader:

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Feature Type: purchase-1999-10-20'
Attribute: first-item' has value Radio'
Attribute: item-at-3-(4th item)' has value Soap'
Attribute: items1' has value Radio,Toothbrush,Towel,Soap,Bottled Water'
Attribute: items2' has value Radio:Toothbrush:Towel:Soap:Bottled Water'
Attribute: last-item' has value Bottled Water'
Attribute: list-attr{0}' has value Radio'
Attribute: list-attr{1}' has value Toothbrush'
Attribute: list-attr{2}' has value Towel'
Attribute: list-attr{3}' has value Soap'
Attribute: list-attr{4}' has value Bottled Water'
Attribute: xml_type' has value xml_no_geom'
Attribute: list-attr{0}' is sequenced
Attribute: list-attr{1}' is sequenced
Attribute: list-attr{2}' is sequenced
Attribute: list-attr{3}' is sequenced
Attribute: list-attr{4}' is sequenced
Geometry Type: Unknown (0)
+========================================================================