Fylke
Fylke

Reputation: 1836

Gluing together strings with delimiters in XSL

I have the following structure where I want to fish out the most relevant data and glue it together to make a headline.

<faults>
  <fault componentName="comp1">
    <introduceWhen>Time1</introduceWhen>
    <signals>
      <signal name="sig11" value="1"/>
      <signal name="sig22" value="1"/>
    </signals>
  </fault>
  <fault componentName="comp2">
    <introduceWhen>Time2</introduceWhen>
    <signals>
      <signal name="sig44" value="0"/>
    </signals>
  </fault>
</faults>

What I would like it to be is comp1 1 1 comp2 0, but so far, the best I've managed is comp1 1 1comp2 0, using this:

<xsl:template match="faults">
  <xsl:for-each select="fault">
    <xsl:variable name="compName" select="@componentName"/>
    <xsl:variable name="sigVals" select="string-join(signals/signal/@value, ' ')"/>
    <xsl:value-of select="concat(@compName, ' ', $sigVals)"/>
  </xsl:for-each>
</xsl:template>

The solution I have doesn't feel very elegant, so if you have alternate approaches, I would very much like to see them. I also have full control over the XML, so if there are any good solutions that changes the structure of the XML, that too would be of interest.

Upvotes: 0

Views: 72

Answers (2)

michael.hor257k
michael.hor257k

Reputation: 117102

As you seem to be using XSLT 2.0, you could make it simply:

<xsl:template match="/faults">
    <xsl:for-each select="fault">
        <xsl:value-of select="@componentName, signals/signal/@value"/>
        <xsl:text> </xsl:text>
    </xsl:for-each>
</xsl:template>

Or, if you want to be more meticulous:

<xsl:template match="/faults">
    <xsl:for-each select="fault">
        <xsl:value-of select="@componentName, signals/signal/@value"/>
        <xsl:if test="position()!=last()">
            <xsl:text> </xsl:text>
        </xsl:if>
    </xsl:for-each>
</xsl:template>

Or (taking a hint from Michael Kay's answer) even simpler:

<xsl:template match="/faults">
    <xsl:value-of select="fault/@componentName | fault/signals/signal/@value"/>
</xsl:template>

The xsl:value-of instruction already inserts a separator between individual values; there is no need to use string-join().

Upvotes: 3

Michael Kay
Michael Kay

Reputation: 163549

Isn't it just

string-join((//@componentName | //@value), ' ')

?

Upvotes: 2

Related Questions