[XSL-LIST Mailing List Archive Home] [By Thread] [By Date]

Re: [xsl] Column Heads and Column Data problem ??


Subject: Re: [xsl] Column Heads and Column Data problem ??
From: Dipesh Khakhkhar <dkhakhkh@xxxxxxxxxxxxxxx>
Date: Wed, 20 Aug 2003 16:37:38 -0400

Hi Wendell,

Thanks once again for giving me the hint.

For the last 2 days i am following your and David's approach to solve the 
problem:

Your appraoch:
=============
1) To get the column names which are there in the input file with attribute 
NAME only using @NAME not including the ones which are already written off. 
2) Then output the values of these columns.
3) Then going to each row and where the column name matches output the value 
for the corresponding data.

Problems which i am trying to fix in it:
---------------------------------------
Thiw will work will well for the sample data i gave for the first time.

With this approach I can get only column names with NAME attribute and order 
also won't be correct which is important in the output which i want.

No consideration of the inserting hard coded column names where generate id 
will be used to establish primary key, foreign key relationship.


David's approach:
=================
1) First getting the row with columns. 
2) Then getting the row with one column greater than the earlier one. 
3) Outputting that as the column header printing only the column names.
4) Then looping through all the rows and matching column name and getting the 
ouput accordingly.


Problems which i am trying to fix in it:
---------------------------------------
This also worked superbly for the sample input.

This is hardcoded for the given problem, if i insert one more column in the 
table two(in my earlier example) i need to manually change the xsl to get it 
worked.


My approach
============
1) For each table in the inputfile find the one with maximum number of rows. 
This approach involves finding count of columns for each table. For table A at 
which is present 3 times with columns 3,3,5 I have to get the one with 5 
columns in a variable. Prepend two hardcoded value into it. And output it.

 In other programming language it should be something like this:

 Variable colHeaderForTable1;
 Variable maxColNoForTable1=0;
 For each //Table1
   variable temp = count(no. of columns in this table);
   if (temp > maxColNoForTable1)
       colHeaderForTable1={"ParentID", "SelfID",Getting each column  name 
followed by seperator}
 End of For
 Output value of colHeaderForTable1


2) Similarly get the column header for each table1 having maximum columns in 
the whole document and outputting it in the first line.

3) Get the data for corresponding tables by matching the column names stored 
in the variable. If column name matches then output the value otherwise ouput 
seperator. (The way you guys have shown)


Problems which i am trying to solve in this approach
----------------------------------------------------
1) variable value can not be change. It is like constant in other languages. 
If someone can tell me how to do the first step using variable it would be of 
great help.


Yeah i agree with Mike Kay that solution should not be given. I am learning 
and wrestling with xsl to get the work done as you gurus have told that 
everything is possible in xsl which i also believe. From the two solutions i 
learned about the usage of xsl:key and predicate. My xsl which has not take 
care of the column header is written by me only but not as elegant as your 
solutions are.

Well i am trying and at the end of the day when i think something is going 
beyond my reach i post question to the list.

Anyway thanks for your time to look into the question.

Regards,
Dipesh



Dipesh,

I am afraid I don't have time at this point to dig into your problem.

I did, however, run your sample input through the stylesheet I offered a 
couple of days ago. After a bug fix (broken XPath) and adjustment for your 
element names, this is the output I got (line breaks added for legibility):

[start]
Computer,ALTIRISTEST_CPQ,Name,Domain,Altkey1,Altkey2,Client_Agent,Agent 
Name,Product Version,Build Number,Install Path,Inventory_Results,Collection 
Time,File Count,Total Size,Version

,,,,,,,Altiris eXpress NS Client,5.5.0.517,517,C:\Program 
Files\Altiris\eXpress\NS
Client,,,,,

,,,,,,,Altiris eXpress Inventory Solution,5.5.0.424,424,C:\Program 
Files\Altiris\eXpress\NS

Client\Software Delivery\Software 
Packages\{01B54EB5-3679-4C73-9E10-E169D5A5EC59},,,,,

,,,,,,,,,,,,1/9/2003 3:06:56 AM,3,139271,5: 5: 0: 423
[end]

This isn't the output you've asked for, of course (it answers the problem 
statement of a couple of days ago), *but* ... it is close enough to suggest to 
me the solution I offered is on the right track, and that you can modify its 
approach and get what you want out of it.

So ... what follows isn't an entire solution -- but if you figure how how it 
does what it does, you should have some hints on how to proceed. (Note on 
process: the XPath bug I had to fix to get this to work is an indication of 
the risks of trying to apply entire solutions provided on the list. Sometimes 
we do this, as the most expedient approach to our goal of addressing a posted 
problem, but as Mike Kay said yesterday, it's not really the best way to help 
you solve your problem. Rather, you have to dig in to what we provide -- 
whether it be code, or merely hints -- and *understand* how it applies, or why 
it's buggy.)

Briefly stated, what the stylesheet does is collect all unique values of @NAME 
attributes and output, for each record, the values corresponding to the entire 
set of NAMES, delimited by commas:

<xsl:output method="text"/>

<xsl:variable name="name-set" select="//@NAME[not(.=preceding::*/@NAME)]"/>

<xsl:template match="/">
<xsl:for-each select="$name-set">
<xsl:value-of select="."/>
<xsl:if test="not(position()=last())">,</xsl:if>
</xsl:for-each>
<xsl:text>&#xA;</xsl:text><!-- line feed for legibility -->

<xsl:apply-templates select="//OBJECT"/>
<!-- this apply-templates could be written to be more efficient,
but I'm too lazy -->
</xsl:template>

<xsl:template match="OBJECT">
<!-- we bind our context node to a variable so we can get
to it inside the for-each -->
<xsl:variable name="this-row" select="."/>
<!-- Now we put out whatever value we have for each node in our name set -->
<xsl:for-each select="$name-set">
<xsl:value-of select="$this-row/ATTRIBUTE[@NAME=current()]"/>
<xsl:if test="not(position()=last())">,</xsl:if>
</xsl:for-each>
<xsl:text>&#xA;</xsl:text><!-- line feed for legibility -->
</xsl:template>

Good luck,
Wendell


 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list



Current Thread
Keywords