Let's clear up a couple small items at first. The proposed key declaration is:
<xsl:key name="keyCodeLists" match="//odm:CodeList" use="concat(ancestor::odm:Study/@OID, ancestor::odm:MetaDataVersion/@OID, @OID)"/> That looks good, except that match patterns don't need the leading //, as they will match all occurrences throughout the tree anyway. However, you need the // in a select expression like count(//odm:CodeList) if you were trying to find out how many "rows" the key table ought to have. The proposed lookup is: key('items', concat($a, $b, $c)) but you probably meant key('keyCodeLists', concat($a, $b, $c)) because the names need to match. Also, check that uppercase/lowercase is correct everywhere. After checking all that, tell us if you still have a problem. .................David Marston