开发者

XPATH / XSLT: Selecting a node where the parent node's attribute matches the attribute of another node

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 ins开发者_StackOverflowide 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


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>


Keys are the right tool for cross references. This stylesheet:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:strip-space elements="*"/>
    <xsl:key name="kAffiliationByAFFID" match="Affiliation" use="@AFFID"/>
    <xsl:template match="AuthorGroup">
        <AUG>
            <xsl:apply-templates/>
        </AUG>
    </xsl:template>
    <xsl:template match="Author">
        <AU>
            <NAME>
                <xsl:value-of select="concat(GivenName,' ',FamilyName)"/>
            </NAME>
            <xsl:apply-templates
                 select="key('kAffiliationByAFFID',@AffiliationID)"
                 mode="out"/>
        </AU>
    </xsl:template>
    <xsl:template match="Affiliation"/>
    <xsl:template match="Affiliation" mode="out">
        <AUINFO>
            <xsl:apply-templates/>
        </AUINFO>
    </xsl:template>
</xsl:stylesheet>

Output:

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


Just a quick answer ... hope this helps, can't run it myself for the moment :-S you can put the ID in a variable like:

<xsl:for-each select="AuthorGroup/Author">
  <xsl:variable name="affID" select="@AFFID" />
  <AU>
    <NAME><xsl:value-of select="./FamilyName" /> <xsl:value-of select="./GivenName" /></NAME>
    <AUINFO><xsl:value-of select="../Affiliation[@AFFID=$affID]/OrgName" /> </AUINFO>
  </AU>         
</xsl:for-each>


<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=./@AffiliationID]/OrgName" /> 
     </AUINFO>


0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜