Simon Price
Simon Price

Reputation: 3261

xslt select a node value based on the value of another node

I am being tasked with creating a csv file using XSLT to produce the information. So far I have almost everything that I need however, there is one bit that i am struggling to get as per the example below.

<issuesExport xmlns="http://www.mynamesapce.co.uk/import">
<materials>
<material>
  <code>WB821</code>
  <name>CONCENTRATE</name>
</material>
<material>
  <code>WB820</code>
  <name>ADDITIVE</name>
</material>
</materials>
<issues>
 <issue>
  <formulaCode>TEST</formulaCode>
  <materialBatch>
    <materialCode>WB821</materialCode>
    <batchNumber>sdfsd</batchNumber>
    <isManualAddBatch>false</isManualAddBatch>
    <isFinished>true</isFinished>
    <weight>0</weight>
    <cost>0</cost>
  </materialBatch>
  <issueBatchNumber>df34323</issueBatchNumber>
</issue>

What I need to do is to grab the name from //material/name where issue/materialBatch/materialCode = material/code.

my current XSLT looks like this

<xsl:if test="i:materialBatch/i:materialCode=//i:material/i:code">
  <xsl:value-of select="//i:materials/i:material/i:name"/>
</xsl:if>

Which is always evaluating to true and giving my a result of CONCENTRATE.

I would be grateful if someone could tell me where I am going wrong

Thank you

Upvotes: 1

Views: 2613

Answers (2)

michael.hor257k
michael.hor257k

Reputation: 116959

Your test always returns true, because you are comparing two node-sets - and such test returns true if one of the nodes in set A matches a node in set B.

The result is always "CONCENTRATE" because

<xsl:value-of select="//i:materials/i:material/i:name"/>

returns the value of the first node of the set matching the select expression.

XSLT has a build-in mechanism for looking up referenced values. In order to use it, start by defining a key at the top-level of your stylesheet:

<xsl:key name="material-bycode" match="i:material" use="i:code" />  

Then, from the context of issue you can use:

<xsl:value-of select="key('material-by-code', i:materialBatch/i:materialCode)/i:name"/>

to retrieve the corresponding name.

Upvotes: 2

Mark Veenstra
Mark Veenstra

Reputation: 4739

Change:

<xsl:if test="i:materialBatch/i:materialCode=//i:material/i:code">
  <xsl:value-of select="//i:materials/i:material/i:name"/>
</xsl:if>

To:

<xsl:value-of select="/i:issuesExport/i:materials/i:material[i:code = i:materialBatch/i:materialCode]/i:name"/>

Also note that // searches the complete XML document. Please try to avoid using // where ever you can to speed things up.

Upvotes: 0

Related Questions