15

The problem I'm facing seems simple, but being a novice in everything XSL - I'm yet to find a proper solution. What I want to do is build a string by concatenating the results of a foreach element loop, that I can later on use as a value for an attribute of a HTML element.

Given:

<?xml version="1.0" encoding="ISO-8859-1"?>
<catalog>
    <cd>
        <country>UK</country>
        <company>CBS Records</company>
    </cd>
    <cd>
        <country>USA</country>
        <company>RCA</company>
    </cd>
    <cd>
        <country>UK</country>
        <company>Virgin records</company>
    </cd>
</catalog>

Desired output: CBS;RCA;Virgin records

I need a valid portion of XSLT code that would perform this transformation in a way described above. I believe I need an xsl-variable that would hold the result of concatenating <company> and a separator character ;. How can this be done? Thank you.

3 Answers 3

21

I don't believe you can use XSL variables to concatenate, because once a variable value is set, it can't be changed. Instead, I think you want something like:

<xsl:for-each select="catalog/cd">
    <xsl:choose>
        <xsl:when test="position() = 1">
            <xsl:value-of select="country"/>
        </xsl:when>
        <xsl:otherwise>
            ;<xsl:value-of select="country"/>
        </xsl:otherwise>
    </xsl:choose>
</xsl:for-each>

Does that make sense to you?

Edit: Just realized I may have misread how you were intending to use the variable. The snippet I posted above can be wrapped in a variable element for later use, if that's what you meant:

<xsl:variable name="VariableName">
    <xsl:for-each select="catalog/cd">
        <xsl:choose>
            <xsl:when test="position() = 1">
                <xsl:value-of select="country"/>
            </xsl:when>
            <xsl:otherwise>
                ;<xsl:value-of select="country"/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:for-each>
</xsl:variable>
Sign up to request clarification or add additional context in comments.

1 Comment

@electroglow, could you do me the kindness of accepting my answer, then? There should be a green outline of a checkmark next to my answer that you can click to indicate that this is what worked for you and solved the question. It's considered good StackOverflow ettiquette to "accept" the right answer to each question you ask. Thanks in advance. :)
7

If you can use XSLT 2.0 then either of the following would work:

Use the string-join() function:

<xsl:variable name="companies" select="string-join(catalog/cd/company, ';')" />

Use @separator with xsl:value-of:

<xsl:variable name="companies" >
   <xsl:value-of select="catalog/cd/company" separator=";" />
</xsl:variable>

1 Comment

I wish i could use XSLT 2.0. I'm upvoting anyway
4

Here is one simple, true XSLT solution:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="text"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="company">
  <xsl:value-of select="."/>
  <xsl:if test="following::company">;</xsl:if>
 </xsl:template>
 <xsl:template match="text()"/>
</xsl:stylesheet>

When this transformation is applied on the provided XML document:

<catalog>
    <cd>
        <country>UK</country>
        <company>CBS Records</company>
    </cd>
    <cd>
        <country>USA</country>
        <company>RCA</company>
    </cd>
    <cd>
        <country>UK</country>
        <company>Virgin records</company>
    </cd>
</catalog>

the wanted, correct result (all companies concatenated together and delimited by a ;) is produced:

CBS Records;RCA;Virgin records

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.