Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > XML > How to Concat in XSLT

Reply
Thread Tools

How to Concat in XSLT

 
 
Hercules Dev.
Guest
Posts: n/a
 
      01-26-2007
Hi all,

I'm new in xslt and xpath, so my question might be simple but i'm
learning.

I have an XML document and need to transform it into another XML, I use
xslt and it works, but there is a case that i don't know how to solve,
I need to concat a string from multiple childs into a standard way, the
following is an example of the source and the target XML.

Source:

<Root>
<ParentElementX>
<ChildElement>
<Value>1</Value>
<Value>2</Value>
<Value>3</Value>
<ChildElement>
<ChildElement>
<Value>4</Value>
<Value>5</Value>
<Value>6</Value>
<ChildElement>

</ParentElementX>
<ParentElementX>
<ChildElement>
<Value>1</Value>
<Value>2</Value>
<Value>3</Value>
<ChildElement>
</ParentElementX>
</Root>

Destination:

<Root>
<ParentElementX>
<ChildElement>1/2/3</ChildElement>
<ChildElement>4/56<ChildElement>
</ParentElementX>
<ParentElementX>
<ChildElement>1/2/3<ChildElement>
</ParentElementX>
</Root>

Please tell me what is the xslt code I need to write to transform this?

Thanks,
Zaid H. Safadi

 
Reply With Quote
 
 
 
 
p.lepin@ctncorp.com
Guest
Posts: n/a
 
      01-26-2007

On Jan 26, 12:53 pm, "Hercules Dev." <zsaf...@hotmail.com>
wrote:
> Source:
>
> <Root>
> <ParentElementX>
> <ChildElement>
> <Value>1</Value>
> <Value>2</Value>
> <Value>3</Value>
> <ChildElement>
> <ChildElement>
> <Value>4</Value>
> <Value>5</Value>
> <Value>6</Value>
> <ChildElement>
>
> </ParentElementX>
> <ParentElementX>
> <ChildElement>
> <Value>1</Value>
> <Value>2</Value>
> <Value>3</Value>
> <ChildElement>
> </ParentElementX>
> </Root>
>
> Destination:
>
> <Root>
> <ParentElementX>
> <ChildElement>1/2/3</ChildElement>
> <ChildElement>4/56<ChildElement>
> </ParentElementX>
> <ParentElementX>
> <ChildElement>1/2/3<ChildElement>
> </ParentElementX>
> </Root>
>
> Please tell me what is the xslt code I need to write to
> transform this?


You can't, because the source you provided is not
well-formed XML. So unless you write your own parser that
would transform this proprietary document into XML DOM that
your XSLT would grok, it's simply impossible.

Even if you write your own parser, I'm not really certain
how did you get to '4/56' as content for the second
ChildElement element in your resulting document.

Now, if you were using well-formed XML, I suppose you could
do something like this:

<xsl:stylesheet version="1.0"
xmlnssl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template
match="Value[not(preceding-sibling::Value)]">
<xsl:apply-templates select="text()"/>
<xsl:apply-templates
select="following-sibling::*[self::Value]"
mode="append"/>
</xsl:template>
<xsl:template match="Value[preceding-sibling::Value]"/>
<xsl:template match="*" mode="append">
<xsl:text>/</xsl:text>
<xsl:apply-templates select="text()"/>
</xsl:template>
</xsl:stylesheet>

(Hint: posting sloppy examples is not a very good idea if
you're asking for help.)

--
Pavel Lepin

 
Reply With Quote
 
 
 
 
George Bina
Guest
Posts: n/a
 
      01-26-2007
As XSLT 2.0 has just been released a couple of days ago, here it an
XSLT 2.0 solution. To concatenate all the values separated with slashes
it just needs
<xsl:value-of select="Value" separator="/"/>


<xsl:stylesheet version="2.0"
xmlnssl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="ChildElement">
<xsl:copy>
<xsl:value-of select="Value" separator="/"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>

Regards,
George
---------------------------------------------------------------------
George Cristian Bina
<oXygen/> XML Editor, Schema Editor and XSLT Editor/Debugger
http://www.oxygenxml.com

On Jan 26, 1:56 pm, p.le...@ctncorp.com wrote:
> On Jan 26, 12:53 pm, "Hercules Dev." <zsaf...@hotmail.com>
> wrote:
>
>
>
> > Source:

>
> > <Root>
> > <ParentElementX>
> > <ChildElement>
> > <Value>1</Value>
> > <Value>2</Value>
> > <Value>3</Value>
> > <ChildElement>
> > <ChildElement>
> > <Value>4</Value>
> > <Value>5</Value>
> > <Value>6</Value>
> > <ChildElement>

>
> > </ParentElementX>
> > <ParentElementX>
> > <ChildElement>
> > <Value>1</Value>
> > <Value>2</Value>
> > <Value>3</Value>
> > <ChildElement>
> > </ParentElementX>
> > </Root>

>
> > Destination:

>
> > <Root>
> > <ParentElementX>
> > <ChildElement>1/2/3</ChildElement>
> > <ChildElement>4/56<ChildElement>
> > </ParentElementX>
> > <ParentElementX>
> > <ChildElement>1/2/3<ChildElement>
> > </ParentElementX>
> > </Root>

>
> > Please tell me what is the xslt code I need to write to
> > transform this?You can't, because the source you provided is not

> well-formed XML. So unless you write your own parser that
> would transform this proprietary document into XML DOM that
> your XSLT would grok, it's simply impossible.
>
> Even if you write your own parser, I'm not really certain
> how did you get to '4/56' as content for the second
> ChildElement element in your resulting document.
>
> Now, if you were using well-formed XML, I suppose you could
> do something like this:
>
> <xsl:stylesheet version="1.0"
> xmlnssl="http://www.w3.org/1999/XSL/Transform">
> <xsl:template match="@*|node()">
> <xsl:copy>
> <xsl:apply-templates select="@*|node()"/>
> </xsl:copy>
> </xsl:template>
> <xsl:template
> match="Value[not(preceding-sibling::Value)]">
> <xsl:apply-templates select="text()"/>
> <xsl:apply-templates
> select="following-sibling::*[self::Value]"
> mode="append"/>
> </xsl:template>
> <xsl:template match="Value[preceding-sibling::Value]"/>
> <xsl:template match="*" mode="append">
> <xsl:text>/</xsl:text>
> <xsl:apply-templates select="text()"/>
> </xsl:template>
> </xsl:stylesheet>
>
> (Hint: posting sloppy examples is not a very good idea if
> you're asking for help.)
>
> --
> Pavel Lepin


 
Reply With Quote
 
Hercules Dev.
Guest
Posts: n/a
 
      01-26-2007

Pavel Lepin,


Thanks for your reply, this is exactly what I wanted and sorry for my
bad source example I usually don't post such bad examples.

Your code worked well with my example but I didn't know how to
integrate it with my already existent XLST code, so I had to perform
two transformations for both using both XSLT, so to solve this I need
to understand your XSLT, is there any good reference you know that can
help me to understand this XSLT code?

Also if you can explain even if a little of it then it will be great.

Thanks anyway,
Zaid H. Safadi


On Jan 26, 1:56 pm, p.le...@ctncorp.com wrote:
> On Jan 26, 12:53 pm, "Hercules Dev." <zsaf...@hotmail.com>
> wrote:
>
>
>
>
>
> > Source:

>
> > <Root>
> > <ParentElementX>
> > <ChildElement>
> > <Value>1</Value>
> > <Value>2</Value>
> > <Value>3</Value>
> > <ChildElement>
> > <ChildElement>
> > <Value>4</Value>
> > <Value>5</Value>
> > <Value>6</Value>
> > <ChildElement>

>
> > </ParentElementX>
> > <ParentElementX>
> > <ChildElement>
> > <Value>1</Value>
> > <Value>2</Value>
> > <Value>3</Value>
> > <ChildElement>
> > </ParentElementX>
> > </Root>

>
> > Destination:

>
> > <Root>
> > <ParentElementX>
> > <ChildElement>1/2/3</ChildElement>
> > <ChildElement>4/56<ChildElement>
> > </ParentElementX>
> > <ParentElementX>
> > <ChildElement>1/2/3<ChildElement>
> > </ParentElementX>
> > </Root>

>
> > Please tell me what is the xslt code I need to write to
> > transform this?You can't, because the source you provided is not

> well-formed XML. So unless you write your own parser that
> would transform this proprietary document into XML DOM that
> your XSLT would grok, it's simply impossible.
>
> Even if you write your own parser, I'm not really certain
> how did you get to '4/56' as content for the second
> ChildElement element in your resulting document.
>
> Now, if you were using well-formed XML, I suppose you could
> do something like this:
>
> <xsl:stylesheet version="1.0"
> xmlnssl="http://www.w3.org/1999/XSL/Transform">
> <xsl:template match="@*|node()">
> <xsl:copy>
> <xsl:apply-templates select="@*|node()"/>
> </xsl:copy>
> </xsl:template>
> <xsl:template
> match="Value[not(preceding-sibling::Value)]">
> <xsl:apply-templates select="text()"/>
> <xsl:apply-templates
> select="following-sibling::*[self::Value]"
> mode="append"/>
> </xsl:template>
> <xsl:template match="Value[preceding-sibling::Value]"/>
> <xsl:template match="*" mode="append">
> <xsl:text>/</xsl:text>
> <xsl:apply-templates select="text()"/>
> </xsl:template>
> </xsl:stylesheet>
>
> (Hint: posting sloppy examples is not a very good idea if
> you're asking for help.)
>
> --
> Pavel Lepin- Hide quoted text -- Show quoted text -


 
Reply With Quote
 
Hercules Dev.
Guest
Posts: n/a
 
      01-26-2007
George,

Thanks for your reply, I'm using the .NET Framework 1.1 engine for XSLT
transformation so i don't think it support XSLT 2.0, I'm already
planning to convert my work to .NET 2.0 so maybe i can make use of the
new features of XSLT 2.0

Thanks,
Zaid H. Safadi

On Jan 26, 2:12 pm, "George Bina" <geo...@oxygenxml.com> wrote:
> As XSLT 2.0 has just been released a couple of days ago, here it an
> XSLT 2.0 solution. To concatenate all the values separated with slashes
> it just needs
> <xsl:value-of select="Value" separator="/"/>
>
> <xsl:stylesheet version="2.0"
> xmlnssl="http://www.w3.org/1999/XSL/Transform">
> <xsl:template match="@*|node()">
> <xsl:copy>
> <xsl:apply-templates select="@*|node()"/>
> </xsl:copy>
> </xsl:template>
> <xsl:template match="ChildElement">
> <xsl:copy>
> <xsl:value-of select="Value" separator="/"/>
> </xsl:copy>
> </xsl:template>
> </xsl:stylesheet>
>
> Regards,
> George
> ---------------------------------------------------------------------
> George Cristian Bina
> <oXygen/> XML Editor, Schema Editor and XSLT Editor/Debuggerhttp://www.oxygenxml.com
>
> On Jan 26, 1:56 pm, p.le...@ctncorp.com wrote:
>
>
>
> > On Jan 26, 12:53 pm, "Hercules Dev." <zsaf...@hotmail.com>
> > wrote:

>
> > > Source:

>
> > > <Root>
> > > <ParentElementX>
> > > <ChildElement>
> > > <Value>1</Value>
> > > <Value>2</Value>
> > > <Value>3</Value>
> > > <ChildElement>
> > > <ChildElement>
> > > <Value>4</Value>
> > > <Value>5</Value>
> > > <Value>6</Value>
> > > <ChildElement>

>
> > > </ParentElementX>
> > > <ParentElementX>
> > > <ChildElement>
> > > <Value>1</Value>
> > > <Value>2</Value>
> > > <Value>3</Value>
> > > <ChildElement>
> > > </ParentElementX>
> > > </Root>

>
> > > Destination:

>
> > > <Root>
> > > <ParentElementX>
> > > <ChildElement>1/2/3</ChildElement>
> > > <ChildElement>4/56<ChildElement>
> > > </ParentElementX>
> > > <ParentElementX>
> > > <ChildElement>1/2/3<ChildElement>
> > > </ParentElementX>
> > > </Root>

>
> > > Please tell me what is the xslt code I need to write to
> > > transform this?You can't, because the source you provided is not

> > well-formed XML. So unless you write your own parser that
> > would transform this proprietary document into XML DOM that
> > your XSLT would grok, it's simply impossible.

>
> > Even if you write your own parser, I'm not really certain
> > how did you get to '4/56' as content for the second
> > ChildElement element in your resulting document.

>
> > Now, if you were using well-formed XML, I suppose you could
> > do something like this:

>
> > <xsl:stylesheet version="1.0"
> > xmlnssl="http://www.w3.org/1999/XSL/Transform">
> > <xsl:template match="@*|node()">
> > <xsl:copy>
> > <xsl:apply-templates select="@*|node()"/>
> > </xsl:copy>
> > </xsl:template>
> > <xsl:template
> > match="Value[not(preceding-sibling::Value)]">
> > <xsl:apply-templates select="text()"/>
> > <xsl:apply-templates
> > select="following-sibling::*[self::Value]"
> > mode="append"/>
> > </xsl:template>
> > <xsl:template match="Value[preceding-sibling::Value]"/>
> > <xsl:template match="*" mode="append">
> > <xsl:text>/</xsl:text>
> > <xsl:apply-templates select="text()"/>
> > </xsl:template>
> > </xsl:stylesheet>

>
> > (Hint: posting sloppy examples is not a very good idea if
> > you're asking for help.)

>
> > --
> > Pavel Lepin- Hide quoted text -- Show quoted text -


 
Reply With Quote
 
Martin Honnen
Guest
Posts: n/a
 
      01-26-2007
Hercules Dev. wrote:

> I'm using the .NET Framework 1.1 engine for XSLT
> transformation so i don't think it support XSLT 2.0, I'm already
> planning to convert my work to .NET 2.0 so maybe i can make use of the
> new features of XSLT 2.0


Both System.Xml.Xsl.XslTransform in .NET 1.x and
System.Xml.Xsl.XslCompiledTransform in .NET 2.0 support XSLT 1.0.
If you want to use XSLT 2.0 with .NET then you need Saxon from
<http://www.saxonica.com/>.

--

Martin Honnen
http://JavaScript.FAQTs.com/
 
Reply With Quote
 
Joseph Kesselman
Guest
Posts: n/a
 
      01-26-2007
For basic educational material on XML and XSLT, I usually point folks to
the many articles/references at http://www.ibm.com/xml

For specific "how do I" questions about XSLT, always check whether what
you need is available as one of the examples at
http://www.dpawson.co.uk/xsl/sect2/sect21.html

It sounds like you're at a point where both of those resources will be
hugely useful to you.
 
Reply With Quote
 
Peter Flynn
Guest
Posts: n/a
 
      01-27-2007
Hercules Dev. wrote:
> Hi all,
>
> I'm new in xslt and xpath, so my question might be simple but i'm
> learning.
>
> I have an XML document and need to transform it into another XML, I use
> xslt and it works, but there is a case that i don't know how to solve,
> I need to concat a string from multiple childs into a standard way, the
> following is an example of the source and the target XML.
>
> Source:
>
> <Root>
> <ParentElementX>
> <ChildElement>
> <Value>1</Value>
> <Value>2</Value>
> <Value>3</Value>
> <ChildElement>
> <ChildElement>
> <Value>4</Value>
> <Value>5</Value>
> <Value>6</Value>
> <ChildElement>
>
> </ParentElementX>
> <ParentElementX>
> <ChildElement>
> <Value>1</Value>
> <Value>2</Value>
> <Value>3</Value>
> <ChildElement>
> </ParentElementX>
> </Root>


That's not XML. Assuming you just mistyped it and that the ChildElements
do actually have start-tags and end-tags, and that you also missed a
slash in the "4/5/6" output, then there are two ways:

1. Concatenation using a recursive named template:

<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet xmlnssl="http://www.w3.org/1999/XSL/Transform"
version="1.0">

<xslutput method="xml" indent="yes"/>

<xsl:template match="Root">
<Root>
<xsl:apply-templates/>
</Root>
</xsl:template>

<xsl:template match="ParentElementX">
<ParentElementX>
<xsl:apply-templates/>
</ParentElementX>
</xsl:template>

<xsl:template match="ChildElement">
<ChildElement>
<xsl:call-template name="join-with-slashes">
<xsl:with-param name="children" select="Value"/>
</xsl:call-template>
</ChildElement>
</xsl:template>

<xsl:template name="join-with-slashes">
<xslaram name="children"/>
<xslaram name="counter">
<xsl:text>1</xsl:text>
</xslaram>
<xsl:choose>
<xsl:when test="$counter>=count($children)">
<xsl:text>/</xsl:text>
<xsl:value-of select="$children[$counter]"/>
</xsl:when>
<xsltherwise>
<xsl:if test="$counter>1">
<xsl:text>/</xsl:text>
</xsl:if>
<xsl:value-of select="$children[$counter]"/>
<xsl:call-template name="join-with-slashes">
<xsl:with-param name="children" select="$children"/>
<xsl:with-param name="counter" select="$counter+1"/>
</xsl:call-template>
</xsltherwise>
</xsl:choose>
</xsl:template>

</xsl:stylesheet>

2. Concatenation using normal templates (much faster):

<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet xmlnssl="http://www.w3.org/1999/XSL/Transform"
version="1.0">

<xslutput method="xml" indent="yes"/>
<xsl:strip-space elements="ChildElement"/>

<xsl:template match="Root">
<Root>
<xsl:apply-templates/>
</Root>
</xsl:template>

<xsl:template match="ParentElementX">
<ParentElementX>
<xsl:apply-templates/>
</ParentElementX>
</xsl:template>

<xsl:template match="ChildElement">
<ChildElement>
<xsl:apply-templates/>
</ChildElement>
</xsl:template>

<xsl:template match="Value">
<xsl:value-of select="."/>
<xsl:if test="position()!=last()">
<xsl:text>/</xsl:text>
</xsl:if>
</xsl:template>

</xsl:stylesheet>

///Peter
--
XML FAQ: http://xml.silmaril.ie
 
Reply With Quote
 
Hercules Dev.
Guest
Posts: n/a
 
      01-28-2007
Thank you so much guys,

Yes my source example was bad and I meant to add en end tag for each
ChildElement and I forgot to include the slash to output 4/5/6.

But I read a book about XML, Xpath, Schema and XSLT "Addison Wesley -
Essential Xml Reference - Xpath, Xslt, Soap.pdf" and it's great, I am
able to understand your examples now and it worked with me and solved
my problems, so really thanks for all contributors.

Thanks,
Zaid H. Safadi



On Jan 27, 6:16 pm, Peter Flynn <peter.n...@m.silmaril.ie> wrote:
> Hercules Dev. wrote:
> > Hi all,

>
> > I'm new in xslt and xpath, so my question might be simple but i'm
> > learning.

>
> > I have an XML document and need to transform it into another XML, I use
> > xslt and it works, but there is a case that i don't know how to solve,
> > I need to concat a string from multiple childs into a standard way, the
> > following is an example of the source and the target XML.

>
> > Source:

>
> > <Root>
> > <ParentElementX>
> > <ChildElement>
> > <Value>1</Value>
> > <Value>2</Value>
> > <Value>3</Value>
> > <ChildElement>
> > <ChildElement>
> > <Value>4</Value>
> > <Value>5</Value>
> > <Value>6</Value>
> > <ChildElement>

>
> > </ParentElementX>
> > <ParentElementX>
> > <ChildElement>
> > <Value>1</Value>
> > <Value>2</Value>
> > <Value>3</Value>
> > <ChildElement>
> > </ParentElementX>
> > </Root>That's not XML. Assuming you just mistyped it and that the ChildElements

> do actually have start-tags and end-tags, and that you also missed a
> slash in the "4/5/6" output, then there are two ways:
>
> 1. Concatenation using a recursive named template:
>
> <?xml version="1.0" encoding="iso-8859-1"?>
> <xsl:stylesheet xmlnssl="http://www.w3.org/1999/XSL/Transform"
> version="1.0">
>
> <xslutput method="xml" indent="yes"/>
>
> <xsl:template match="Root">
> <Root>
> <xsl:apply-templates/>
> </Root>
> </xsl:template>
>
> <xsl:template match="ParentElementX">
> <ParentElementX>
> <xsl:apply-templates/>
> </ParentElementX>
> </xsl:template>
>
> <xsl:template match="ChildElement">
> <ChildElement>
> <xsl:call-template name="join-with-slashes">
> <xsl:with-param name="children" select="Value"/>
> </xsl:call-template>
> </ChildElement>
> </xsl:template>
>
> <xsl:template name="join-with-slashes">
> <xslaram name="children"/>
> <xslaram name="counter">
> <xsl:text>1</xsl:text>
> </xslaram>
> <xsl:choose>
> <xsl:when test="$counter>=count($children)">
> <xsl:text>/</xsl:text>
> <xsl:value-of select="$children[$counter]"/>
> </xsl:when>
> <xsltherwise>
> <xsl:if test="$counter>1">
> <xsl:text>/</xsl:text>
> </xsl:if>
> <xsl:value-of select="$children[$counter]"/>
> <xsl:call-template name="join-with-slashes">
> <xsl:with-param name="children" select="$children"/>
> <xsl:with-param name="counter" select="$counter+1"/>
> </xsl:call-template>
> </xsltherwise>
> </xsl:choose>
> </xsl:template>
>
> </xsl:stylesheet>
>
> 2. Concatenation using normal templates (much faster):
>
> <?xml version="1.0" encoding="iso-8859-1"?>
> <xsl:stylesheet xmlnssl="http://www.w3.org/1999/XSL/Transform"
> version="1.0">
>
> <xslutput method="xml" indent="yes"/>
> <xsl:strip-space elements="ChildElement"/>
>
> <xsl:template match="Root">
> <Root>
> <xsl:apply-templates/>
> </Root>
> </xsl:template>
>
> <xsl:template match="ParentElementX">
> <ParentElementX>
> <xsl:apply-templates/>
> </ParentElementX>
> </xsl:template>
>
> <xsl:template match="ChildElement">
> <ChildElement>
> <xsl:apply-templates/>
> </ChildElement>
> </xsl:template>
>
> <xsl:template match="Value">
> <xsl:value-of select="."/>
> <xsl:if test="position()!=last()">
> <xsl:text>/</xsl:text>
> </xsl:if>
> </xsl:template>
>
> </xsl:stylesheet>
>
> ///Peter
> --
> XML FAQ:http://xml.silmaril.ie- Hide quoted text -- Show quoted text -


 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Re: How include a large array? Edward A. Falk C Programming 1 04-04-2013 08:07 PM
xslt eval concat xpath webjay XML 1 10-26-2007 09:06 AM
concat a space on an HTML controls innerText property =?Utf-8?B?QW5nZWw=?= ASP .Net 10 09-01-2005 07:45 PM
XSLT: concat and quotes Gerald Aichholzer XML 4 05-27-2005 12:51 PM
dropdownlist-concat two fields-can it be done ctb ASP .Net 2 07-18-2003 04:20 PM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57