Reputation: 849
I am trying to grab the node value of an external document, but am nowhere near getting anything that works.
This is the products.xml
<TESTS>
<CHILD>
<KEY>111111</KEY>
<PRODUCT>Toy 1</PRODUCT>
</CHILD>
<CHILD>
<KEY>222222</KEY>
<PRODUCT>Toy 2</PRODUCT>
</CHILD>
</TESTS>
This is the file being transformed companys.xml
<INVENTORY>
<PRODUCTS>
<ITEMS>
<ITEM TYPE="Toys">111111</ITEM>
</ITEMS>
</PRODUCTS>
<PRODUCTS>
<ITEMS>
<ITEM TYPE="Toys">222222</ITEM>
</ITEMS>
</PRODUCTS>
<INVENTORY>
This is the xsl code I have
<xsl:variable name="lookupDoc" select="document('products.xml')" />
<xsl:key name="product-lookup" match="KEY" use="."/>
<xsl:template match="PRODUCT_HTML">
<xsl:value-of select="./@TYPE"/> <xsl:value-of select="."/> <xsl:value-of select="$lookupDoc/exam-lookup" />
</xsl:template>
What I am getting from this is
Toys 111111
What I would Like to get is
Toys 111111 Toy 1
Can you please help me out?
Thanks,
Alex
Upvotes: 0
Views: 404
Reputation: 43158
The xsl:key
element has to be used in conjunction with the key()
function.
Your key definition
<xsl:key name="product-lookup" match="KEY" use="."/>
is not quite what you want, I think. match
controls the element that you want to return, while use
tells what expression is being matched in the lookup. As written, it will return the KEY
element itself, and to get to the PRODUCT
you'd have to traverse laterally. It probably should be
<xsl:key name="product-lookup" match="CHILD" use="KEY"/>
This way, an expression like
<xsl:value-of select="key('product-lookup', '111111') />
will point to the first CHILD
node in the products.xml
file. Then you can traverse downward to the product name.
However, there's a wrinkle in XSLT 1.0 when using the key()
function on an external document: key()
operates on the "context document", so if the current node is in the input document companys.xml
, the lookup will not give the result you want.
To work around this, you can set the context to the target document, as follows:
<xsl:variable name="key" select="." />
<xsl:variable name="child">
<xsl:for-each select="$lookupDoc">
<xsl:value-of select="key('product-lookup', $key)/PRODUCT"/>
</xsl:for-each>
</xsl:variable>
Now $child
now contain the string value of the PRODUCT
element under the corresponding CHILD
. (See comments re variable binding.)
Note that an extra variable is needed to store the key so that .
doesn't change its meaning when you change the context. In other words, you have to save a binding to the key value from the original document first.
In XSLT 2.0, you can avoid some of that by using a third parameter that was added to the key()
function for setting the context document:
<xsl:variable name="child" select="key('product-lookup', ., $lookupDoc)" />
Makes this (common) problem much cleaner.
Upvotes: 1