0
votes

How to move 'affiliation' element into 'contrib' element which is in 'for-each' context in XSLT?

Input XML:

<article>
    <authors>Amrendra, Kumar; Mohan, Kumar</authors>
    <affiliation id="Amrendra, Kumar">Amrendra, Kumar</affiliation>
    <affiliation id="Mohan, Kumar">Mohan, Kumar</affiliation>
</article>

Current output:

<contrib-group>
  <contrib>
    <string-name>Amrendra, Kumar</string-name>
  </contrib>
  <contrib>
    <string-name>Mohan, Kumar</string-name>
  </contrib>
  <aff id="Amrendra, Kumar">Amrendra, Kumar</aff>
  <aff id="Mohan, Kumar">Mohan, Kumar</aff>
</contrib-group>

XSLT Code:

<xsl:template match="authors">
    <xsl:choose>
        <xsl:when test="not(node())"/>
        <xsl:otherwise>
            <contrib-group>
                <xsl:for-each select="tokenize(., ';')">
                <contrib>
                    <string-name>
                        <xsl:value-of select="normalize-space(.)"/>
                    </string-name>
                </contrib>
                </xsl:for-each>
                <xsl:apply-templates select="../affiliation"/>
            </contrib-group>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

Required Output: (Matching with aff/@id and contrib/#pcdata)

<contrib-group>
  <contrib>
    <string-name>Amrendra, Kumar</string-name>
    <aff id="Amrendra, Kumar">Amrendra, Kumar</aff>
  </contrib>
  <contrib>
    <string-name>Mohan, Kumar</string-name>
    <aff id="Mohan, Kumar">Mohan, Kumar</aff>
  </contrib>
</contrib-group>

when i try to apply 'affiliation' element inside contrib then it is showing below error:

[Saxon-PE 9.5.1.7] XPTY0020: Cannot select the parent of the context node: the context item is not a node
2
Can you show a complete XSLT that demonstrates your problem please? I don't think the template shown results in the error given, not unless your actual XSLT has the <xsl:apply-templates select="../affiliation"/> within the xsl:for-each structure, not after it. Thank you.Tim C
What exactly links between an author and the corresponding affiliation? You have identical values in 3 places, it's hard to tell which pair to use.michael.hor257k

2 Answers

0
votes

Assuming that the authors string contains tokens identical to the values of affiliation/@id, you could do:

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="affiliation" use="@id" />

<xsl:template match="article">
    <xsl:variable name="current-article" select="." />
    <contrib-group>
        <xsl:for-each select="tokenize(authors, '; ')">
            <contrib>
                <string-name>
                    <xsl:value-of select="."/>
                </string-name>
                <xsl:apply-templates select="key('aff', ., $current-article)[node()]"/>
            </contrib>
        </xsl:for-each>
    </contrib-group>
</xsl:template>

<xsl:template match="affiliation">
    <aff>
        <xsl:copy-of select="@* | node()" />
    </aff>
</xsl:template>

 </xsl:stylesheet>

to get the required output.

0
votes
<aff id="{.}">
    <xsl:value-of select="key('aff', ., $current-article)" />
</aff>

should be change with for avoiding spaces and missing values

<aff id="{normalize-space(.)}">
    <xsl:value-of select="key('aff', normalize-space(.), $current-article)" />
</aff>