saxon:index

Indexes a sequence as a map.

index($sequence as item(), $function as xs:integer) ➔ xs:double

Arguments

 

$sequence

item()

The sequence to be indexed

 

$function

xs:integer

Computes the value on which the sequence is indexed

Result

xs:double

Details

Namespace: http://saxon.sf.net/

The first argument is any sequence. Usually it will be a sequence of nodes, but this is not essential. This is the sequence being indexed.

The second argument is a function used to compute a key. This function is called once for each item in the sequence being indexed, with that item as the argument. The result of the function is atomized. Each value in the atomized result represents a key value: the item in the indexed sequence can be efficiently found using any of these key values.

If a key value is of type xs:untypedAtomic, it is treated as a string. If you want to treat the value as numeric, say, then perform a conversion within the expression.

The result is a map, that can be supplied as input to the saxon:find() function, or to any map functions such as map:get() or map:size().

For example, consider a source document of the form:

<doc> <town name="Amherst" state="NH"/> <town name="Amherst" state="MA"/> <town name="Auburn" state="MA"/> <town name="Auburn" state="NH"/> <town name="Auburn" state="ME"/> <town name="Bristol" state="RI"/> <town name="Bristol" state="ME"/> <town name="Bristol" state="CT"/> <town name="Bristol" state="NH"/> <town name="Bristol" state="VT"/> <town name="Cambridge" state="ME"/> </doc>

and suppose there is a requirement to find town elements efficiently given the abbreviation for the state. You can do this by first setting up an indexed sequence. In XQuery you can write:

declare namespace saxon="http://saxon.sf.net/"; declare namespace java="http://saxon.sf.net/java-type"; declare variable $indexedTowns as map(*) := saxon:index(//town, function($t){$t/@state});

This could be a local variable (declared in a let clause) rather than a global variable. The XSLT equivalent is:

<xsl:variable name="indexedTowns" select="saxon:index(//town, function($t){$t/@state})" as="map(*)"/>

You can then find all the towns in New Hampshire using the expression:

map:get($indexedTowns, "NH")

Indexed sequences were introduced primarily for use in XQuery, where they provide functionality equivalent to the standard xsl:key mechanism in XSLT. From Saxon 9.5 the data structure used for an indexed sequence is a map, and with the introduction of maps the function could now be implemented simply as:

declare function saxon:index($seq as item()*, $f as function(item()) as xs:anyAtomicValue) { map:new( for $item in $seq for $key in $f($item) group by $key return map:entry($key, $item) ) };

For information about maps and the functions available to process them, see the XSLT 3.0 specification. Saxon implements maps in XSLT, XQuery, and XPath, provided 3.0 is enabled.

Notes on the Saxon implementation

Changed in Saxon 9.5 to take a function as the second argument (rather than a PreparedExpression), and to return a map as the result. The 3-argument form of the function, which took a collation as the third argument, is dropped. Requires Saxon-PE or Saxon-EE.