Xml – XPATH / XSLT: Selecting a node where the parent node’s attribute matches the attribute of another node

xmlxpathxslt

I'm trying to apply a transformation to the below XML using XPath and XSLT.

<AuthorGroup>
  <Author AffiliationID="A1">
    <GivenName>John</GivenName>
    <Initials/>
    <FamilyName>Smith</FamilyName>
    <Degrees/>
    <Roles/>
  </Author>
    <Author AffiliationID="A2">
    <GivenName>Bill</GivenName>
    <Initials/>
    <FamilyName>Atkins</FamilyName>
    <Degrees/>
    <Roles/>
  </Author>
  <Affiliation AFFID="A1">
    <OrgDivision/>
    <OrgName>Some Org</OrgName>
    <OrgAddress/>
  </Affiliation>
  <Affiliation AFFID="A2">
    <OrgDivision/>
    <OrgName>Another Org</OrgName>
    <OrgAddress/>
  </Affiliation>
</AuthorGroup>

I'm trying to combine the author and affiliation names under one node so I'll end up with a structure like:

<AUG>
  <AU><NAME>John Smith</NAME><AUINFO>Some Org</AUINFO></AU>
  <AU><NAME>Bill Atkins</NAME><AUINFO>Another Org</AUINFO></AU>
</AUG>

I'm struggling to find a way of selecting the value of a node who's parent node's attribute matches the value of an attribute of an another node. For example, For the author John Smith I'd like to select the value of the node where the affiliation ID's match.

So far I have some code in my stylesheet like the below but I know the selection inside the node is not working.

<xsl:for-each select="AuthorGroup/Author">
  <AU>
  <NAME><xsl:value-of select="./FamilyName" /> <xsl:value-of select="./GivenName" /></NAME>
  <AUINFO><xsl:value-of select="../Affiliation[@AFFID='NEED TO MATCH AUTHOR AFFILIATIONID']/OrgName" /> </AUINFO>


  </AU>         
</xsl:for-each>

How should I select the value of the correct organisation name for the associated author?

Many thanks

Jim

Best Answer

As an alternative to using a variable, you can make use of the "current()" operator to get the current Author node you are on

<xsl:value-of select="../Affiliation[@AFFID=current()/@AffiliationID]/OrgName"/>

Thus, if you take the following stylesheet

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
   <xsl:template match="/">
      <AUG>
         <xsl:for-each select="AuthorGroup/Author">
            <AU>
               <NAME>
                  <xsl:value-of select="./FamilyName"/>
                  <xsl:value-of select="./GivenName"/>
               </NAME>
               <AUINFO>
                  <xsl:value-of select="../Affiliation[@AFFID=current()/@AffiliationID]/OrgName"/>
               </AUINFO>
            </AU>
         </xsl:for-each>
      </AUG>
   </xsl:template>
</xsl:stylesheet>

And apply it your given XML, the results should be like so

<AUG>
   <AU>
      <NAME>SmithJohn</NAME>
      <AUINFO>Some Org</AUINFO>
   </AU>
   <AU>
      <NAME>AtkinsBill</NAME>
      <AUINFO>Another Org</AUINFO>
   </AU>
</AUG>
Related Topic