Leigh Ann Martin
Leigh Ann Martin

Reputation: 3

How to Omit Elements in a Separated Concat List Without Extra Separators

I am trying to create a transformation for the MODS metadata schema and could use some help.

The base xml for this section looks like this:

  <subject authority="lcsh">
     <name type="corporate">
        <namePart>Hypothetical College (Hypothesis, NJ.)</namePart>
     </name>
     <titleInfo>
        <title/>
     </titleInfo>
     <topic>Students</topic>
     <genre>Periodicals</genre>
  </subject>

The desire is for this to render as Hypothetical College (Hypothesis, NJ.) -- Students -- Periodicals

My results look more like this: Hypothetical College (Hypothesis, NJ.) -- -- Students -- Periodicals

My section of code dealing with this is as follows:

<xsl:template match="mods:mods/mods:subject">
    <tr>
        <td class="standardFieldName">Subject(s)</td>
        <td class="standardFieldValue">                                    
                <xsl:call-template name="join">                        
                    <xsl:with-param name="valueList" select="*"/>                        
                    <xsl:with-param name="separator" select="' -- '"/>                        
                </xsl:call-template>                    
                <xsl:text>&#xa;&#xd;</xsl:text>                                    
            </td>
    </tr>        
</xsl:template>

<xsl:template name="join" >        
    <xsl:param name="valueList" select="''"/>        
    <xsl:param name="separator" select="','"/>        
    <xsl:for-each select="$valueList">            
        <xsl:choose>                
            <xsl:when test="position() = 1">                    
                <xsl:value-of select="."/>                    
            </xsl:when>                
            <xsl:otherwise>                    
                <xsl:value-of select="concat($separator, .) "/>                    
            </xsl:otherwise>                
        </xsl:choose>            
    </xsl:for-each>        
</xsl:template>

There are two problems here. One, the insertion of the empty elements and associated separators. Two, that this works correctly if something is in the "name" element, but if the first non-empty element is any of the others, I also get -- beforehand. I have surmised that "position() = 1" just takes into account the element's placement in the xml file, so is there a way to apply that to the first non-empty element?

Thanks in advance.

Upvotes: 0

Views: 25

Answers (1)

Tim C
Tim C

Reputation: 70648

I think you just need to make use of normalize-space() here to ignore the empty elements....

<xsl:template match="subject">
    <tr>
        <td class="standardFieldName">Subject(s)</td>
        <td class="standardFieldValue">                                    
                <xsl:call-template name="join">                        
                    <xsl:with-param name="valueList" select="*[normalize-space()]"/>                        
                    <xsl:with-param name="separator" select="' -- '"/>                        
                </xsl:call-template>                    
                <xsl:text>&#xa;&#xd;</xsl:text>                                    
            </td>
    </tr>        
</xsl:template>

<xsl:template name="join">        
    <xsl:param name="valueList" select="''"/>        
    <xsl:param name="separator" select="','"/>        
    <xsl:for-each select="$valueList">    
        <xsl:if test="position() > 1">
            <xsl:value-of select="$separator" />
        </xsl:if>
        <xsl:value-of select="normalize-space()"/>           
    </xsl:for-each>        
</xsl:template>

Note I have simplified the "join" template to reduce the amount of code needed.

Upvotes: 1

Related Questions