Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Westi on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

XSLT – Concatnate xml node text

Status
Not open for further replies.

Need2Program

Programmer
Nov 12, 2007
1
US
Thank you for reading. I am new at this.

Question: How can I create a component node where the text is coming from multiple nodes in the source xml document?

I have an xml doc …

Code:
<?xml version="1.0" encoding="Windows-1252"?>
<PackData xmlns:xsi="[URL unfurl="true"]http://www.w3.org/2001/XMLSchema-instance"[/URL] xmlns:xsd="[URL unfurl="true"]http://www.w3.org/2001/XMLSchema">[/URL]
  <Id>131</Id>
  <Placement>STANDARD</Placement>
  <MessageList>
    <Message>
      <Id>4</Id>
      <Tag>HEADER</Tag>
      <Text>Learn XSLT </Text>
      <Language>en</Language>
    </Message>
    <Message>
      <Id>5</Id>
      <Tag>INTRO</Tag>
      <Text>We will learn how to use xslt. For additional help and tips </Text>
      <Language>en</Language>
    </Message>
    <Message>
      <Id>6</Id>
      <Tag>INTRO</Tag>
      <Text>Click Here </Text>
      <Url>[URL unfurl="true"]http://www.tek-tips.com/</Url>[/URL]
      <Language>en</Language>
    </Message>
    <Message>
      <Id>7</Id>
      <Tag>FOOTER</Tag>
      <Text>Thank you for your help </Text>
      <Language>en</Language>
    </Message>
   </MessageList>
</PackData>

When I run the transform...
Code:
xslt.Transform("C:/Code/Pack.xml", xmlw);

I want to produce 1 XML node that have Messages 5 and 6 (Intro) text to be concatenated with the link.

Code:
<Component>
 <Tag>INTRO</Tag>
 <Text></Text>
 <Html>
   We will learn how to use xslt. For additional help and tips<a href=[URL unfurl="true"]http://www.tek-tips.com/>Click[/URL] Here </a>
</Html>
</Component>

Here is what I am doing so far...
(Creates the above type xml nodes for each message)

Code:
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="[URL unfurl="true"]http://www.w3.org/1999/XSL/Transform">[/URL]
<xsl:output method="xml" indent="yes" version="1.0" />

<xsl:template match="PackData">
   <Components>
     <xsl:apply-templates select="MessageList"/>
   </Components>
</xsl:template>
	
<xsl:template  match="MessageList">
  <xsl:apply-templates select="Message" />
</xsl:template>

<xsl:template match="Message">
   <Component>
      <Tag>
         <xsl:value-of select="Tag"/>
      </Tag>

    <xsl:choose>
      <xsl:when test="Tag='HEADER'">
       <Text>
         <xsl:value-of select="Text"></xsl:value-of>
       </Text>
      </xsl:when>
     <xsl:otherwise>
        <Text/>
     </xsl:choose>
	
     <xsl:choose>
      <xsl:when test="Tag !='HEADER'">
        <Html>
	   <xsl:choose>
	     <xsl:when test="Url">
	        <xsl:choose >
		   <xsl:when test="Url[normalize-space(.)!= ']">
		      <a target="_blank">
			<xsl:attribute name="href">
			   <xsl:value-of select="Url"/>
			</xsl:attribute>
		      	<xsl:value-of select="Text"/>
		      </a>
		  </xsl:when>
		<xsl:otherwise>
		   <xsl:value-of select="Text"/>
		</xsl:otherwise>
	   </xsl:choose>
	</xsl:when>
        <xsl:otherwise>
	   <xsl:value-of select="Text"/>
	</xsl:otherwise>
     </xsl:choose>
       </Html>
   </xsl:when>
   <xsl:otherwise>
   <Html/>
  </xsl:otherwise>
 </xsl:choose>
</Component>

</xsl:template>
</xsl:stylesheet>

I have successfully created a variable... however I just get the Text not the url link.
<!--testing Concatenating data-->
<!--<xsl:variable name="elements">-->
<!--<xsl:value-of select="Text"/>-->
<!--also tried the above code added here-->
<!--Test Concatenating INTRO Data:<xsl:value-of select="$elements"/> End of Intro Data-->

Thank you so much for your time

-Charlotte
 
Since treatment of one Message might depend on its sibling's contents, you might require some grouping. Without using xsl:key, one that reflect Message being an ensemble to consider as a whole is to use xsl:for-each. This latter approach might be more intuitive and easier to construct as they are close to each other and not kind of long-range correlation.

This is how you can get it done within the template of MessageList, much expanded whereas eliminating the template for individual Message.
[tt]
<xsl:template match="MessageList">
<xsl:for-each select="Message">
<xsl:choose>
<xsl:when test="Tag/text() = 'INTRO'">
<xsl:choose>
<xsl:when test="count(preceding-sibling::*[Tag = 'INTRO'])=0">
<Component>
<Tag><xsl:value-of select="Tag" /></Tag>
<Text> </Text>
<Html>
<xsl:for-each select="self::*|following-sibling::*[Tag = 'INTRO']">
<xsl:choose>
<xsl:when test="count(Url) &gt; 0">
<a href="{Url}">
<xsl:value-of select="Text" />
</a>
</xsl:when>
<xsl:eek:therwise>
<xsl:value-of select="Text" />
</xsl:eek:therwise>
</xsl:choose>
</xsl:for-each>
</Html>
</Component>
</xsl:when>
<xsl:eek:therwise></xsl:eek:therwise>
</xsl:choose>
</xsl:when>
<xsl:when test="Tag/text() = 'HEADER'">
<Component>
<Tag><xsl:value-of select="Tag" /></Tag>
<Text> </Text>
<Text>
<xsl:value-of select="Text" />
</Text>
</Component>
</xsl:when>
<xsl:when test="Tag/text() = 'FOOTER'">
<Component>
<Tag><xsl:value-of select="Tag" /></Tag>
<Text> </Text>
<Text>
<xsl:value-of select="Text" />
</Text>
</Component>
</xsl:when>
<xsl:eek:therwise></xsl:eek:therwise>
</xsl:choose>
</xsl:for-each>
</xsl:template>
[/tt]
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top