Patrick
Patrick

Reputation: 478

Join Concatenation of Formatted XSLT node values

I have this block of XML code

         <itemContentList>
            <itemContent condition="sometype">
               <typeList1>
                  <type1 otherName="companion">other</type1>
               </typeList1>
               <typeList2 condition="anothertype" xlink:href="value1"/>
            </itemContent>
            <itemContent condition="sometype">
               <typeList1>
                  <type1 otherName="companion2">other</type1>
               </typeList1>
               <typeList2 condition="anothertype" xlink:href="value2"/>
            </itemContent>
            <itemContent condition="sometype">
               <typeList1>
                  <type1 otherName="companion3">other</type1>
               </typeList1>
               <typeList2 condition="anothertype" xlink:href="value3"/>
            </itemContent>          
         </itemContentList>

My desired output is a semi-colon separated values of a formatted string from the nodes.

(companion,value1);(companion2,value2);(companion3,value3)

I used this particular XSL transformation:

<xsl:variable name="desiredOutput">
      <xsl:for-each select="itemContentList">
        <xsl:variable name="param1"
            select="itemContent[@condition='sometype']/typeList1/type1/@otherName"/>
        <xsl:variable name="param2" 
            select="itemContent[@condition='sometype']/typeList2[@condition='anothertype']/@xlink:href"/>                               
        <xsl:value-of select="string-join((concat('(', string-join(($param1, $param2)[.!=''],','),')')),';')"/>         
      </xsl:for-each>
</xsl:variable>

But the output turns out differently:

(companion,companion2,companion3,value1,value2,value3)

I also extracted the string-join as a function but it renders the same. Any help with this?

EDIT 1:

Thank you for the help! Although my goal is to save the value of the concatenated string in a variable.

For both solutions, I tried using the template and assign a name to it. Both answers provide the string that I was trying to generate.

<xsl:template **name="concatvalue"** match="/itemContentList">
    <xsl:value-of select="for $i in itemContent return concat('(', $i/typeList1/type1/@otherName, ',', $i/typeList2/@xlink:href, ')')" separator=";"/>
</xsl:template>

Then I created a variable that performs:

  <xsl:variable name="concatvariable">
    <xsl:call-template name="concatvalue" />
  </xsl:variable>

However, "concatvariable" is empty.

Upvotes: 0

Views: 52

Answers (2)

Yitzhak Khabinsky
Yitzhak Khabinsky

Reputation: 22182

A very similar solution, just without the FLWOR.

I had to add a missing namespace.

XML

<?xml version="1.0"?>
<itemContentList xmlns:xlink="http://www.w3.org/1999/xlink">
    <itemContent condition="sometype">
        <typeList1>
            <type1 otherName="companion">other</type1>
        </typeList1>
        <typeList2 condition="anothertype" xlink:href="value1"/>
    </itemContent>
    <itemContent condition="sometype">
        <typeList1>
            <type1 otherName="companion2">other</type1>
        </typeList1>
        <typeList2 condition="anothertype" xlink:href="value2"/>
    </itemContent>
    <itemContent condition="sometype">
        <typeList1>
            <type1 otherName="companion3">other</type1>
        </typeList1>
        <typeList2 condition="anothertype" xlink:href="value3"/>
    </itemContent>
</itemContentList>

XSLT 2.0

<?xml version="1.0"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xlink="http://www.w3.org/1999/xlink">
    <xsl:output method="text"/>

    <xsl:template match="/itemContentList">
        <xsl:value-of select="itemContent/concat('(', typeList1/type1/@otherName, ',', typeList2/@xlink:href, ')')" separator=";"/>
    </xsl:template>
</xsl:stylesheet>

Output

(companion,value1);(companion2,value2);(companion3,value3)

XSLT 2.0 with a variable

<?xml version="1.0"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xlink="http://www.w3.org/1999/xlink">
    <xsl:output method="text"/>

  <xsl:variable name="concatvariable">
    <xsl:value-of select="/itemContentList/itemContent/concat('(', typeList1/type1/@otherName, ',', typeList2/@xlink:href, ')')" separator=";"/>
  </xsl:variable>

  <xsl:template match="/">
    <xsl:value-of select="$concatvariable"/>
  </xsl:template>
</xsl:stylesheet>

Upvotes: 1

michael.hor257k
michael.hor257k

Reputation: 116957

How about:

XSLT 2.0

<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xlink="http://www.w3.org/1999/xlink">
<xsl:output method="text"/>

<xsl:template match="/itemContentList">
    <xsl:value-of select="for $i in itemContent return concat('(', $i/typeList1/type1/@otherName, ',', $i/typeList2/@xlink:href, ')')" separator=";"/>
</xsl:template>

</xsl:stylesheet>

Demo: https://xsltfiddle.liberty-development.net/ei5R4ub

Upvotes: 1

Related Questions