473,232 Members | 1,636 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,232 software developers and data experts.

How to Concat in XSLT

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

Jan 26 '07 #1
8 15857

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"
xmlns:xsl="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

Jan 26 '07 #2
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"
xmlns:xsl="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"
xmlns:xsl="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
Jan 26 '07 #3

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"
xmlns:xsl="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 -
Jan 26 '07 #4
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.comwrote:
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"
xmlns:xsl="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"
xmlns:xsl="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 -
Jan 26 '07 #5
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/
Jan 26 '07 #6
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.
Jan 26 '07 #7
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 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">

<xsl:output 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">
<xsl:param name="children"/>
<xsl:param name="counter">
<xsl:text>1</xsl:text>
</xsl:param>
<xsl:choose>
<xsl:when test="$counter>=count($children)">
<xsl:text>/</xsl:text>
<xsl:value-of select="$children[$counter]"/>
</xsl:when>
<xsl:otherwise>
<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>
</xsl:otherwise>
</xsl:choose>
</xsl:template>

</xsl:stylesheet>

2. Concatenation using normal templates (much faster):

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

<xsl:output 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
Jan 27 '07 #8
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.iewrote:
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 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">

<xsl:output 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">
<xsl:param name="children"/>
<xsl:param name="counter">
<xsl:text>1</xsl:text>
</xsl:param>
<xsl:choose>
<xsl:when test="$counter>=count($children)">
<xsl:text>/</xsl:text>
<xsl:value-of select="$children[$counter]"/>
</xsl:when>
<xsl:otherwise>
<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>
</xsl:otherwise>
</xsl:choose>
</xsl:template>

</xsl:stylesheet>

2. Concatenation using normal templates (much faster):

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

<xsl:output 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 -
Jan 28 '07 #9

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

13
by: Martin | last post by:
I have 5 days of experince with XSLT and I am sure my problem is pretty much as basic as they come but I cannot work it out, so I hope someone will take pity on me - please! I have inherited an...
1
by: Patrick Reilly | last post by:
I am trying to implement a better method than I already have to document database schemas with XML, and use XSLT to both generate database DDL statements (CREATE TABLE, etc) and to transform to...
3
by: Son KwonNam | last post by:
The title is quite ambiguos. Any way let me explain. In java, the following is possible. ---- String str = ""; for (int i=0; i < 10; i++) { str = str + i; } ----
4
by: Frederik Sørensen | last post by:
I include a xslt stylesheet with variables for all the error messages in my system. <xsl:variable name="Banner_error_1"> errormessage 1 for banner </xsl:variable> <xsl:variable...
3
by: shaun roe | last post by:
I have a document about 4 levels deep and in my XSLT I want to generate a unique string ID for each basic element based on its path through the hierarchy. If I use recursion, I am continually...
0
by: david.paik | last post by:
Given the data: <?xml version="1.0" encoding="UTF-8"?> <?xml-stylesheet type="text/xsl" href="C:\junk\830new.xslt"?> <SC830> <SC830_3 bano="S67777" cuno="002620" year="2007" week="38"...
2
by: Scott Sauyet | last post by:
I'm trying to select a subset of a WSDL document using XSLT and a simple text document describing the high-level elements to include. I have it working fine for selecting the services, bindings,...
1
by: n.phelge | last post by:
I'm using XSLT and .NET Framework 1.1 to try to transform XML to group by multiple values, and I'm not succeeding. I have source XML that looks like the following: <Data> <Flavor>...
1
by: CAM123 | last post by:
I have added: <br><xsl:value-of select="Line" /></br> to my XSLT stylesheet to get a line per repeating block. When I view the output as XML it looks perfect - one line per block. However...
1
by: Sandeep Singh | last post by:
Hi, How to do group by in XSLT ? I tried on the following codes: <files> <file name="swablr.eps" size="4313" project="mars"/> <file name="batboy.wks" size="424" ...
3
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 3 Jan 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). For other local times, please check World Time Buddy In...
0
by: abbasky | last post by:
### Vandf component communication method one: data sharing ​ Vandf components can achieve data exchange through data sharing, state sharing, events, and other methods. Vandf's data exchange method...
0
Git
by: egorbl4 | last post by:
Скачал я git, хотел начать настройку, а там вылезло вот это Что это? Что мне с этим делать? ...
1
by: davi5007 | last post by:
Hi, Basically, I am trying to automate a field named TraceabilityNo into a web page from an access form. I've got the serial held in the variable strSearchString. How can I get this into the...
0
by: MeoLessi9 | last post by:
I have VirtualBox installed on Windows 11 and now I would like to install Kali on a virtual machine. However, on the official website, I see two options: "Installer images" and "Virtual machines"....
0
by: DolphinDB | last post by:
The formulas of 101 quantitative trading alphas used by WorldQuant were presented in the paper 101 Formulaic Alphas. However, some formulas are complex, leading to challenges in calculation. Take...
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
0
by: Aftab Ahmad | last post by:
So, I have written a code for a cmd called "Send WhatsApp Message" to open and send WhatsApp messaage. The code is given below. Dim IE As Object Set IE =...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.