Wrox Programmer Forums
Go Back   Wrox Programmer Forums > XML > XSLT
|
XSLT General questions and answers about XSLT. For issues strictly specific to the book XSLT 1.1 Programmers Reference, please post to that forum instead.
Welcome to the p2p.wrox.com Forums.

You are currently viewing the XSLT section of the Wrox Programmer to Programmer discussions. This is a community of software programmers and website developers including Wrox book authors and readers. New member registration was closed in 2019. New posts were shut off and the site was archived into this static format as of October 1, 2020. If you require technical support for a Wrox book please contact http://hub.wiley.com
 
Old July 4th, 2013, 06:59 PM
Authorized User
 
Join Date: Jun 2013
Posts: 21
Thanks: 2
Thanked 0 Times in 0 Posts
Default XSLT-displaying the number followed by alphabets

<PassengerList>
<SeatNumber>1A</SeatNumber>
<SeatNumber>1B</SeatNumber>
<SeatNumber>1D</SeatNumber>
<SeatNumber>1E</SeatNumber>
<SeatNumber>1F</SeatNumber>
<SeatNumber>1G</SeatNumber>
<SeatNumber>2B</SeatNumber>
<SeatNumber>2D</SeatNumber>
<SeatNumber>3A</SeatNumber>
<SeatNumber>3B</SeatNumber>
<SeatNumber>3D</SeatNumber>
<SeatNumber>3E</SeatNumber>
<SeatNumber>4A</SeatNumber>
<SeatNumber>4B</SeatNumber>
<SeatNumber>4E</SeatNumber>
<SeatNumber>4F</SeatNumber>
<SeatNumber>4G</SeatNumber>
<SeatNumber>4J</SeatNumber>
</PassengerList>

I need the output to be:

1ABDEFG2BD3ABDE4ABEFGJ

I tried to implement using array ,but i can able display element only, not in the specified format.
<xsl:variable name="array" as="element()*"/>
<xsl:variable name="arrayCount">
<xsl:value-of select="count(//FlightLeg/FlightSummary/CabinSummary[1]/VacantSeatNumberList/SeatNumber)" />
</xsl:variable>
<xsl:value-of select="$parray"/>
<!--
<xsl:if test="$arrayCount > 0">
<xsl:value-of select="$parray[position()]" />
<xsl:call-template name="for-loop">
<xsl:with-param name="arrCount" select="$arrCount - 1"/>
</xsl:call-template>
</xsl:if> -->

Note: Outputtype = "text"
I am strugglling for the last 2 days for this required output. Can you please help me in displaying like above with numbers followed by alphabets.

Last edited by sen1953; July 5th, 2013 at 02:09 AM..
 
Old July 5th, 2013, 11:46 AM
samjudson's Avatar
Friend of Wrox
 
Join Date: Aug 2007
Posts: 2,128
Thanks: 1
Thanked 189 Times in 188 Posts
Default

I can think of at least 3 different ways. Recursion (parse the first item, pass the initial character into another call etc), use the preceding-sibling::*[1] to get the previous element and test that, or in XSLT 2.0 use the xsl:for-each-group instruction with the group-adjacent attribute to group by the starting letter.

Can you show us what you have tried and we can probably help you.
__________________
/- Sam Judson : Wrox Technical Editor -/

Think before you post: What have you tried?
 
Old July 5th, 2013, 12:55 PM
Friend of Wrox
 
Join Date: Nov 2007
Posts: 1,243
Thanks: 0
Thanked 245 Times in 244 Posts
Default

Your posted code sample suggest you can use XSLT 2.0 so assuming an XSLT 2.0 processor you can easily group:
Code:
<xsl:stylesheet
  version="2.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  exclude-result-prefixes="xs">
  
<xsl:output method="text"/>

<xsl:template match="PassengerList">
  <xsl:for-each-group select="SeatNumber" group-by="replace(., '[^0-9]+', '')">
    <xsl:value-of select="current-grouping-key(), current-group()/replace(., '[0-9]+', '')" separator=""/>
  </xsl:for-each-group>
</xsl:template>

</xsl:stylesheet>
That transforms
Code:
<PassengerList>
<SeatNumber>1A</SeatNumber>
<SeatNumber>1B</SeatNumber>
<SeatNumber>1D</SeatNumber>
<SeatNumber>1E</SeatNumber>
<SeatNumber>1F</SeatNumber>
<SeatNumber>1G</SeatNumber>
<SeatNumber>2B</SeatNumber>
<SeatNumber>2D</SeatNumber>
<SeatNumber>3A</SeatNumber>
<SeatNumber>3B</SeatNumber>
<SeatNumber>3D</SeatNumber>
<SeatNumber>3E</SeatNumber>
<SeatNumber>4A</SeatNumber>
<SeatNumber>4B</SeatNumber>
<SeatNumber>4E</SeatNumber>
<SeatNumber>4F</SeatNumber>
<SeatNumber>4G</SeatNumber>
<SeatNumber>4J</SeatNumber>
</PassengerList>
into
Code:
1ABDEFG2BD3ABDE4ABEFGJ
__________________
Martin Honnen
Microsoft MVP (XML, Data Platform Development) 2005/04 - 2013/03
My blog
 
Old July 7th, 2013, 03:55 AM
Authorized User
 
Join Date: Jun 2013
Posts: 21
Thanks: 2
Thanked 0 Times in 0 Posts
Default

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL
<?xml version="1.0" encoding="UTF-8"?>
<seatgroups>
<abcd>firstelement</abcd>
<abc>secondelement</abc>
<PassengerList>
<SeatNumber>1A</SeatNumber>
<SeatNumber>1B</SeatNumber>
<SeatNumber>1D</SeatNumber>
<SeatNumber>1E</SeatNumber>
<SeatNumber>1F</SeatNumber>
<SeatNumber>1G</SeatNumber>
<SeatNumber>2B</SeatNumber>
<SeatNumber>2D</SeatNumber>
<SeatNumber>3A</SeatNumber>
<SeatNumber>3B</SeatNumber>
<SeatNumber>3D</SeatNumber>
<SeatNumber>3E</SeatNumber>
<SeatNumber>4A</SeatNumber>
<SeatNumber>4B</SeatNumber>
<SeatNumber>4E</SeatNumber>
<SeatNumber>4F</SeatNumber>
<SeatNumber>4G</SeatNumber>
<SeatNumber>4J</SeatNumber>
</PassengerList>
<next>Antony</next>
<next>Britto</next>
</seatgroups>


Actual output now:firstelementsecondelement1ABDEFG2BD3ABDE4ABEFG JAntonyBritto

The problem is I need seat number alone. but its printing all the elements
in the xml.But the expected output is 1ABDEFG2BD3ABDE4ABEFGJ. I tried many xpath for the actual result. But I need seat number from the xml.
Why its printing all the elements from the xml even though given correct xml...Please clarify it please.

Thanks in advance

XSL file:

/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions">

<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="PassengerList">
<!--<xsl:apply-templates select="PassengerList/SeatNumber"/>-->
<xsl:for-each-group select="SeatNumber" group-by="replace(., '[^0-9]+', '')">
<xsl:value-of select="current-grouping-key(), current-group()/replace(., '[0-9]+', '')" separator=""/>
</xsl:for-each-group>
</xsl:template>

</xsl:stylesheet>

Last edited by sen1953; July 7th, 2013 at 04:22 AM.. Reason: correct format
 
Old July 7th, 2013, 04:20 AM
mhkay's Avatar
Wrox Author
 
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

The rest of the code you need is completely bog-standard XSLT. If you don't know how to write it, there are some good Wrox books to learn from.
__________________
Michael Kay
http://www.saxonica.com/
Author, XSLT 2.0 and XPath 2.0 Programmer\'s Reference
 
Old July 7th, 2013, 06:54 AM
Authorized User
 
Join Date: Jun 2013
Posts: 21
Thanks: 2
Thanked 0 Times in 0 Posts
Default Thanks mckay and Martin

Its perfectly working for me now. But am not going to use as template ,instead of that i written code like this its works fine. it wont bring the all nodes as well.. But i dont know the reason why its brings all nodes when it apply through template match.
Thanks KAY and Martin...

This is the xsl code

<xsl:template match="/">
<xsl:for-each-group select="//seatgroups/PassengerList/SeatNumber" group-by="replace(., '[^0-9]+', '')">
<xsl:value-of select="current-grouping-key(), current-group()/replace(., '[0-9]+', '')" separator=""/>
</xsl:for-each-group>
</xsl:template>

output is : 1A1B1D1E1F1G2B2D3A3B3D3E4A4B4E4F4G4J
Thanks I solved it Martin...
 
Old July 7th, 2013, 07:06 AM
Friend of Wrox
 
Join Date: Nov 2007
Posts: 1,243
Thanks: 0
Thanked 245 Times in 244 Posts
Default

It is good that you managed to adapt the code to your needs. If you want to go with a template based solution then you simply need to be aware that there a built-in templates (see http://www.w3.org/TR/xslt#built-in-rule) that by default output values. Thus if all you write is a template
Code:
<xsl:template match="PassengerList">
  <xsl:for-each-group select="SeatNumber" group-by="replace(., '[^0-9]+', '')">
    <xsl:value-of select="current-grouping-key(), current-group()/replace(., '[0-9]+', '')" separator=""/>
  </xsl:for-each-group>
</xsl:template>
then the default templates kick in for the nodes (and ensure the above template is used at all) but you need to ensure that unwanted output is suppressed.

There are basically two ways to ensure that, either explicitly ensure that certain elements don't output anything with e.g.
Code:
<xsl:template match="next | abc | abcd"/>
or ensure that only the elements are processed you want to be processed with
Code:
<xsl:template match="/">
  <xsl:apply-templates select="//PassengerList"/>
</xsl:template>
__________________
Martin Honnen
Microsoft MVP (XML, Data Platform Development) 2005/04 - 2013/03
My blog
 
Old July 12th, 2013, 07:47 AM
Authorized User
 
Join Date: Jun 2013
Posts: 21
Thanks: 2
Thanked 0 Times in 0 Posts
Default getting value from for-each group

Code:
<xsl:template match="PassengerList">
  <xsl:for-each-group select="SeatNumber" group-by="replace(., '[^0-9]+', '')">
    <xsl:value-of select="current-grouping-key(), current-group()/replace(., '[0-9]+', '')" separator=""/>
  </xsl:for-each-group>
</xsl:template>
This is the output
1ABDEFG2BD3ABDE4ABEFG
Required format

1ABDEFG 2BD 3ABDE 4ABEFG

Need to separate with single space between new seats as well..
I tried this code by below
Code:
<xsl:template match="PassengerList">
<xsl:variable name="seatgroup">
  <xsl:for-each-group select="SeatNumber" group-by="replace(., '[^0-9]+', '')">
    <xsl:value-of select="current-grouping-key(), current-group()/replace(., '[0-9]+', '')" separator=""/>
  </xsl:for-each-group>
</xsl:variable>
<xsl:value-of select="$seatgroup"/>
</xsl:template>
But am not able to get this variable value. How to get this value from the for-each group? So that I can do string functions or replace for my requirement.
Additionaly I want to know that , any chance to get the required output by modifying the code as well. why my variable is not populating with output?
Please clarify me. thanks in advance
 
Old July 12th, 2013, 07:53 AM
Friend of Wrox
 
Join Date: Nov 2007
Posts: 1,243
Thanks: 0
Thanked 245 Times in 244 Posts
Default

Use
Code:
  <xsl:for-each-group select="SeatNumber" group-by="replace(., '[^0-9]+', '')">
    <xsl:if test="position() gt 1"><xsl:text> </xsl:text></xsl:if>
    <xsl:value-of select="current-grouping-key(), current-group()/replace(., '[0-9]+', '')" separator=""/>
  </xsl:for-each-group>
__________________
Martin Honnen
Microsoft MVP (XML, Data Platform Development) 2005/04 - 2013/03
My blog
The Following User Says Thank You to Martin Honnen For This Useful Post:
santhakumar (July 12th, 2013)
 
Old July 12th, 2013, 09:25 AM
Friend of Wrox
 
Join Date: Nov 2007
Posts: 1,243
Thanks: 0
Thanked 245 Times in 244 Posts
Default

XSLT and XPath 2.0 operate on sequences of nodes or atomic values like strings or numbers or dates. In the case of your sample the variable named "seatgroup" is a document node with a single text child node containing the string "1ABDEFG2BD3ABDE4ABEFG" so you can't access any particular items, unless you use string processing (substring($seatgroup, 2, 4)). If you want to create structured data use XML e.g.

Code:
<xsl:template match="PassengerList">
<xsl:variable name="seatgroup">
  <xsl:for-each-group select="SeatNumber" group-by="replace(., '[^0-9]+', '')">
    <group seat="{current-grouping-key()}">
      <xsl:for-each select="current-group()/replace(., '[0-9]+', '')">
        <item><xsl:value-of select="."/></item>
      <xsl:for-each>
    </group>
  </xsl:for-each-group>
</xsl:variable>
<xsl:value-of select="$seatgroup/group/@seat"/> <!-- outputs '1 2 3 4' -->
<xsl:value-of select="$seatgroup/group[2]/item"/> <!-- outputs 'B D' -->
</xsl:template>
I hope that helps. Consider to start a new question with all details (input you want, output you want to create) if you need more help. And there are introductory books like Beginning XSLT that should help: http://www.wrox.com/WileyCDA/WroxTit...470477253.html
__________________
Martin Honnen
Microsoft MVP (XML, Data Platform Development) 2005/04 - 2013/03
My blog





Similar Threads
Thread Thread Starter Forum Replies Last Post
xslt number count sunnykeerthi XSLT 1 April 15th, 2013 12:14 PM
Sorting and Paging GridView using Alphabets yukijocelyn ASP.NET 2.0 Basics 9 August 29th, 2007 04:05 PM
Displaying a number of results fogofogo XSLT 2 November 22nd, 2005 12:18 PM
Can XSLT tell if there is a number as a value. insanek XSLT 4 September 14th, 2005 03:35 AM





Powered by vBulletin®
Copyright ©2000 - 2020, Jelsoft Enterprises Ltd.
Copyright (c) 2020 John Wiley & Sons, Inc.