Search code examples
xpathtalend

xpath - matching value of child in current node with value of element in parent


Edit: I think I found the answer but I'll leave the open for a bit to see if someone has a correction/improvement.

I'm using xpath in Talend's etl tool. I have xml like this:

<root>  
 <employee>
  <benefits>
    <benefit>
      <benefitname>CDE</benefitname>
      <benefit_start>2/3/2004</benefit_start>
    </benefit>
    <benefit>
     <benefitname>ABC</benefitname>
     <benefit_start>1/1/2001</benefit_start>
    </benefit>
  </benefits>
<dependent> 
  <benefits>
    <benefit>
  <benefitname>ABC</benefitname>
 </benefit>
</dependent>

When parsing benefits for dependents, I want to get elements present in the employee's benefit element. So in the example above, I want to get 1/1/2001 for the dependent's start date. I want 1/1/2001, not 2/3/2004, because the dependent's benefit has benefitname ABC, matching the employee's benefit with the same benefitname.

What xpath, relative to /root/employee/dependent/benefits/benefit, will yield the value of benefit_start for the benefit under parent employee that has the same benefit name as the dependent benefit name? (Note I don't know ahead of time what the literal value will be, I can't just look for 'ABC', I have to match whatever value is in the dependent's benefitname element.

I'm trying:

../../../benefits/benefit[benefitname=??what??]/benefit_start

I don't know how to refer to the current node's ancestor in the middle of the xpath (since I think "." at the point I have ??what?? will refer to the benefit node of the employee/benefits.

EDIT: I think what I want is "current()/benefitname" where the ??what?? is. Seems to work with saxon, I haven't tried it in the etl tool yet.


Solution

  • Your XML is malformed, and I don't think you've described your siduation very well (the XPath you're trying has a bunch of ../../s at the beginning, but you haven't said what the context node is, whether you're iterating through certain nodes, or what.

    Supposing the current context node were an employee element, you could select benefit_starts that match dependent benefits with

    benefits/benefit[benefitname = ../../dependent/benefits/benefit/benefitname]
                                                                           /benefit_start
    

    If the current context node is a benefit element in a dependents section, and you want to get the corresponding benefit_start for just the current benefit element, you can do:

    ../../../benefits/benefit[benefitname = current()/benefitname]/benefit_start
    

    Which is what I think you've already discovered.