user2093335
user2093335

Reputation: 219

XSLT: Pull value from cross-reference

I'm trying to pull values from an aff element that matches a cross-reference id, but not sure what XPath to get specific matched value.

XML:

<article>    
<contrib-group>
    <contrib contrib-type="author">
    <name><surname>Doe</surname><given-names>Jane</given-names></name><email>email here</email><xref ref-type="aff" rid="affa">a</xref><xref ref-type="corresp" rid="cor2">*</xref>
    </contrib>
    <contrib contrib-type="author">
    <name><surname>Done</surname><given-names>John</given-names></name><email>email here</email><xref ref-type="aff" rid="affb">b</xref>
    </contrib>
    <aff id="affa"><label>a</label>Department of Philosophy, <institution>University of XXX</institution>, <country>Germany</country></aff>
    <aff id="affb"><label>b</label>Institute of Logic, <institution>Univeristy of YYY</institution>, Virginia, <country>United States</country></aff>
    </contrib-group>
</article>

XSLT:

<xsl:template match="*">
        <article>
        <xsl:apply-templates select="//contrib-group/contrib"/>
        </article>
    </xsl:template>
    
    <xsl:template match="article/contrib-group/contrib">
        <contrib>
        <surname><xsl:value-of select="name/surname"/></surname>
        <given-names><xsl:value-of select="name/given-names"/></given-names>
        <email><xsl:value-of select="./email"/></email>
        <affiliation>
            <xsl:if test="xref/@rid = following-sibling::aff/@id">
                <xsl:value-of select="following-sibling::aff"/>
            </xsl:if>
        </affiliation>
        </contrib>
    </xsl:template>

I know the <xsl:value-of> is incorrect here - how to select the corresponding linked @id that matches the @rid?

The output gives me both affiliations for both contribs:

<article>
    <contrib>
        <surname>Doe</surname>
        <given-names>Jane</given-names>
        <email>email here</email>
        <affiliation>aDepartment of Philosophy, University of XXX, Germany bInstitute of Logic, Ohio, United States</affiliation>
    </contrib>
    <contrib>
        <surname>Done</surname>
        <given-names>John</given-names>
        <email>Email here</email>
        <affiliation>aDepartment of Philosophy, University of XXX, Germany bInstitute of Logic, Ohio, United States</affiliation>
    </contrib>
</article>

Upvotes: 0

Views: 39

Answers (1)

michael.hor257k
michael.hor257k

Reputation: 116959

XSLT has a built-in key mechanism for resolving cross-references.

XSLT 2.0

<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:key name="aff" match="aff" use="@id" />

<xsl:template match="/article">
    <xsl:copy>
        <xsl:apply-templates select="contrib-group/contrib"/>
    </xsl:copy>
</xsl:template>
    
<xsl:template match="contrib">
    <xsl:copy>
        <xsl:copy-of select="name/* | email"/>
        <affiliation>
            <xsl:value-of select="key('aff', xref[@ref-type='aff']/@rid)/(node() except label)" separator=""/>
        </affiliation>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

Applied to your input example, this will return:

Result

<?xml version="1.0" encoding="UTF-8"?>
<article>
   <contrib>
      <surname>Doe</surname>
      <given-names>Jane</given-names>
      <email>email here</email>
      <affiliation>Department of Philosophy, University of XXX, Germany</affiliation>
   </contrib>
   <contrib>
      <surname>Done</surname>
      <given-names>John</given-names>
      <email>email here</email>
      <affiliation>Institute of Logic, Univeristy of YYY, Virginia, United States</affiliation>
   </contrib>
</article>

Upvotes: 1

Related Questions