Given this XML:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE pm [
]>
<pm>
<content>
<pmEntry>
<dmRef>
<dmRefIdent>
<dmCode modelIdentCode="S1000DBIKE"
systemDiffCode="AAA"
systemCode="D00"
subSystemCode="0"
subSubSystemCode="0"
assyCode="00"
disassyCode="00"
disassyCodeVariant="AA"
infoCode="001"
infoCodeVariant="A"
itemLocationCode="A"/>
<issueInfo issueNumber="001" inWork="00"/>
<language countryIsoCode="US" languageIsoCode="en"/>
</dmRefIdent>
<dmRefAddressItems>
<dmTitle>
<infoName>Title page</infoName>
</dmTitle>
<issueDate day="31" month="12" year="2012"/>
</dmRefAddressItems>
</dmRef>
</pmEntry>
<pmEntry>
<dmRef>
<dmRefIdent>
<dmCode assyCode="00" disassyCode="00" disassyCodeVariant="E01" infoCode="130"
infoCodeVariant="D" itemLocationCode="A" modelIdentCode="555"
subSubSystemCode="0" subSystemCode="3" systemCode="15" systemDiffCode="A"/>
</dmRefIdent>
<dmRefAddressItems>
<dmTitle>
<infoName>Pre-Flight</infoName>
</dmTitle>
</dmRefAddressItems>
</dmRef>
<dmRef>
<dmRefIdent>
<dmCode assyCode="00" disassyCode="00" disassyCodeVariant="E02" infoCode="130"
infoCodeVariant="D" itemLocationCode="A" modelIdentCode="525"
subSubSystemCode="0" subSystemCode="3" systemCode="15" systemDiffCode="A"/>
</dmRefIdent>
<dmRefAddressItems>
<dmTitle>
<infoName>Post-Flight</infoName>
</dmTitle>
</dmRefAddressItems>
</dmRef>
<dmRef>
<dmRefIdent>
<dmCode modelIdentCode="FLRA" systemDiffCode="A" systemCode="00" subSystemCode="0" subSubSystemCode="0"
assyCode="00" disassyCode="00" disassyCodeVariant="E01" infoCode="131" infoCodeVariant="T" itemLocationCode="A"/>
</dmRefIdent>
<dmRefAddressItems>
<dmTitle>
<infoName>Through-Flight Checklist</infoName>
</dmTitle>
</dmRefAddressItems>
</dmRef>
</pmEntry>
<pmEntry>
<dmRef>
<dmRefIdent>
<dmCode assyCode="00" disassyCode="11" disassyCodeVariant="A01" infoCode="141"
infoCodeVariant="A" itemLocationCode="A" modelIdentCode="555"
subSubSystemCode="0" subSystemCode="3" systemCode="15" systemDiffCode="A"/>
</dmRefIdent>
<dmRefAddressItems>
<dmTitle>
<infoName>First Advisory</infoName>
</dmTitle>
</dmRefAddressItems>
</dmRef>
<dmRef>
<dmRefIdent>
<dmCode assyCode="00" disassyCode="15" disassyCodeVariant="A03" infoCode="141"
infoCodeVariant="A" itemLocationCode="A" modelIdentCode="555"
subSubSystemCode="9" subSystemCode="4" systemCode="15" systemDiffCode="A"/>
</dmRefIdent>
<dmRefAddressItems>
<dmTitle>
<infoName>Status Messages</infoName>
</dmTitle>
</dmRefAddressItems>
</dmRef>
<dmRef>
<dmRefIdent>
<dmCode assyCode="00" disassyCode="20" disassyCodeVariant="A99" infoCode="141"
infoCodeVariant="A" itemLocationCode="A" modelIdentCode="555"
subSubSystemCode="0" subSystemCode="3" systemCode="15" systemDiffCode="A"/>
</dmRefIdent>
<dmRefAddressItems>
<dmTitle>
<infoName>Last Advisory</infoName>
</dmTitle>
</dmRefAddressItems>
</dmRef>
</pmEntry>
<pmEntry>
<dmRef>
<dmRefIdent>
<dmCode assyCode="00" disassyCode="01" disassyCodeVariant="C99" infoCode="141" infoCodeVariant="A"
itemLocationCode="A" modelIdentCode="555" subSubSystemCode="0" subSystemCode="4"
systemCode="15" systemDiffCode="A"/>
</dmRefIdent>
<dmRefAddressItems>
<dmTitle>
<infoName>Cautions</infoName>
</dmTitle>
</dmRefAddressItems>
</dmRef>
<dmRef>
<dmRefIdent>
<dmCode assyCode="00" disassyCode="10" disassyCodeVariant="C99" infoCode="141"
infoCodeVariant="A" itemLocationCode="A" modelIdentCode="555" subSubSystemCode="0"
subSystemCode="4" systemCode="15" systemDiffCode="A"/>
</dmRefIdent>
<dmRefAddressItems>
<dmTitle>
<infoName>Cautions End</infoName>
</dmTitle>
</dmRefAddressItems>
</dmRef>
</pmEntry>
</content>
</pm>
I wanted to rewrite the following with a key (this does work):
<xsl:variable name="advisory-DMs" as="item()*">
<xsl:copy-of select="pmEntry//dmRef/dmRefIdent/dmCode[@infoCode=('141') and @infoCodeVariant='A' and starts-with(@disassyCodeVariant,'A')]"/>
</xsl:variable>
So I tried variations of:
<xsl:key name="kICV" match="dmCode" use="concat(@infoCode, @infoCodeVariant)" />
<xsl:variable name="advisory-DMs" as="item()*">
<xsl:copy-of select="pmEntry//dmRef/dmRefIdent/dmCode[key('kICV','141A') and starts-with(@disassyCodeVariant,'A')]"/>
</xsl:variable>
But the variable contains the first dmCode
where infoCode="001"
so it's returning all dmCodes
where @disassyCodeVariant
starts with 'A' and ignoring @infoCode='141'
. I'm looking for a more efficient way of writing this, maybe I need two keys? If I want to search on @disassyCode
as well would I need three keys?
First of all, in XSLT 3, you don't need the concat
of several key values, you can just ensure the key value is a sequence of several values with composite
e.g.
<xsl:key name="kICV" match="dmCode" composite="yes" use="@infoCode, @infoCodeVariant" />
Then I think you just want
<xsl:variable name="advisory-DMs" select="key('kICV', ('141', 'A'))[starts-with(@disassyCodeVariant,'A')]"/>
Note that the key
function in XSLT 2 and higher allows an optional third argument to provide the document node or subtree to search. It is not clear from your description whether you work with a single document or more so that you would need to pass in the third argument to determine the document or whether you want the key search to be restricted to a certain subtree you would also need to pass in (e.g. <xsl:variable name="advisory-DMs" select="key('kICV', ('141', 'A'), pmEntry)[starts-with(@disassyCodeVariant,'A')]"/>
).