Hi Dipesh ,
I have deviated from your solution and have produced
the following XSL. It illustrates the concept. I hope
you can take some ideas from it. And I also hope I
understood your problem correctly.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xalan="http://xml.apache.org/xalan">
<xsl:output method="text" version="1.0"
encoding="UTF-8" indent="yes"/>
<xsl:template match="/">
<xsl:variable name="treefrag1">
<tables>
<xsl:apply-templates select="//CLASS"/>
</tables>
</xsl:variable>
<xsl:variable name="treefrag2">
<tables>
<xsl:for-each
select="xalan:nodeset($treefrag1)/tables/table">
<xsl:sort select="no_of_columns" data-type="number"
order="descending"/>
<table>
<name>
<xsl:value-of select="name"/>
</name>
<no_of_columns>
<xsl:value-of select="no_of_columns"/>
</no_of_columns>
</table>
</xsl:for-each>
</tables>
</xsl:variable>
<xsl:value-of
select="xalan:nodeset($treefrag2)/tables/table[1]/name"
/><xsl:text> : </xsl:text><xsl:value-of
select="xalan:nodeset($treefrag2)/tables/table[1]/no_of_columns"
/>
</xsl:template>
<xsl:template match="//CLASS">
<table>
<name>
<xsl:value-of select="@NAME"/>
</name>
<no_of_columns>
<xsl:value-of
select="count(OBJECT[1]/ATTRIBUTE)"/>
</no_of_columns>
</table>
</xsl:template>
</xsl:stylesheet>
The ideas behind my solution are --
1. I iterate through all the CLASS elements using //
and store its *NAME attribute value* and the no. of
instances of ATTRIBUTE elements in 1st OBJECT
element(I am assuming that all OBJECT elements of a
particular CLASS will have same no. of ATTRIBUTE
elements). I store this result(tree fragment) in a
variable treefrag1.
2. I then iterate through treefrag1 (after converting
it to a nodeset, using Xalan nodeset extension
function) and *sort the records in descending order
based on no of columns*.
3. I then access the 1st row of this sorted result.
This way I am able to find the table with maximum no.
of columns.
Regards,
Mukul
--- Dipesh Khakhkhar <dkhakhkh(_at_)mailbox(_dot_)syr(_dot_)edu> wrote:
Hi,
I am having the following xml Document
Xml
====
<?xml version="1.0" encoding="UTF-8"?>
<AEXDATAEXTRACT DTD_VERSION="2.2"
EXTRACT_START_DATETIME="1/9/2003 4:49:39 PM"
EXTRACT_TYPE="FULL" EXTRACT_COLLECTION="">
<RESOURCE_TYPE
GUID="{493435f7-3b17-4c4c-b07f-c23e7ab7781f}"
NAME="Computer"
DESCRIPTION="Asset Type definition for Computer"
SOURCE="Asset"
CREATED_DATE="7/16/2002 5:22:23 PM"
MODIFIED_DATE="9/23/2002 2:17:48 PM"
DELETED="0">
<RESOURCE
GUID="{C116FCBF-5B94-4F15-BF95-5795DBD384CD}"
NAME="ALTIRISTEST_CPQ"
SOURCE="" SITE_CODE="756win" DOMAIN="FIDD"
SYSTEM_TYPE="Win32"
OS_NAME="Microsoft Windows XP"
OS_TYPE="Professional" OS_VERSION="5.1"
OS_REVISION="Service Pack 1" LAST_LOGON_USER=""
LAST_LOGON_DOMAIN="">
<INVENTORY>
<ASSET>
<IDENTIFICATION>
<ATTRIBUTE NAME="Name">ALTIRISTEST_CPQ</ATTRIBUTE>
<ATTRIBUTE NAME="Domain">FIDDOMRTLSLC</ATTRIBUTE>
<ATTRIBUTE NAME="Altkey1" NULL="FALSE" />
<ATTRIBUTE
NAME="Altkey2">00-02-A5-1A-67-A6</ATTRIBUTE>
</IDENTIFICATION>
<CLASS NAME="Client_Agent">
<OBJECT>
<ATTRIBUTE NAME="Agent Name">Altiris eXpress NS
Client</ATTRIBUTE>
<ATTRIBUTE NAME="Product
Version">5.5.0.517</ATTRIBUTE>
<ATTRIBUTE NAME="Build Number">517</ATTRIBUTE>
<ATTRIBUTE NAME="Install Path">C:\Program
Files\Altiris\eXpress\NS
Client</ATTRIBUTE>
</OBJECT>
<OBJECT>
<ATTRIBUTE NAME="Agent Name">Altiris eXpress
Inventory Solution</ATTRIBUTE>
<ATTRIBUTE NAME="Product
Version">5.5.0.424</ATTRIBUTE>
<ATTRIBUTE NAME="Build Number">424</ATTRIBUTE>
<ATTRIBUTE NAME="Install Path">C:\Program
Files\Altiris\eXpress\NS
Client\Software Delivery\Software
Packages\{01B54EB5-3679-4C73-9E10-E169D5A5EC59}</ATTRIBUTE>
</OBJECT>
</CLASS>
<CLASS NAME="Inventory_Results">
<OBJECT>
<ATTRIBUTE NAME="Collection Time">1/9/2003 3:06:56
AM</ATTRIBUTE>
<ATTRIBUTE NAME="File Count">3</ATTRIBUTE>
<ATTRIBUTE NAME="Total Size">139271</ATTRIBUTE>
<ATTRIBUTE NAME="Version">5: 5: 0: 423</ATTRIBUTE>
</OBJECT>
</CLASS>
</ASSET>
</INVENTORY>
</RESOURCE>
<RESOURCE
GUID="{C116FCBF-5B94-4F15-BF95-5795DBD384CD}"
NAME="ALTIRISTEST_CPQ"
SOURCE="" SITE_CODE="756win" DOMAIN="FIDD"
SYSTEM_TYPE="Win32"
OS_NAME="Microsoft Windows XP"
OS_TYPE="Professional" OS_VERSION="5.1"
OS_REVISION="Service Pack 1" LAST_LOGON_USER=""
LAST_LOGON_DOMAIN=""
AdditionalCol="Additional Col Value">
<INVENTORY>
<ASSET>
<CLASS NAME="Client_Agent">
<OBJECT>
<ATTRIBUTE NAME="Agent Name">Altiris eXpress NS
Client</ATTRIBUTE>
<ATTRIBUTE NAME="Product
Version">5.5.0.517</ATTRIBUTE>
<ATTRIBUTE NAME="Extra Column">Extra COlumn
Value1</ATTRIBUTE>
<ATTRIBUTE NAME="Build Number">517</ATTRIBUTE>
<ATTRIBUTE NAME="Install Path">C:\Program
Files\Altiris\eXpress\NS
Client</ATTRIBUTE>
</OBJECT>
<OBJECT>
<ATTRIBUTE NAME="Agent Name">Altiris eXpress
Inventory Solution</ATTRIBUTE>
<ATTRIBUTE NAME="Product
Version">5.5.0.424</ATTRIBUTE>
<ATTRIBUTE NAME="Extra Column">Extra COlumn
Value2</ATTRIBUTE>
<ATTRIBUTE NAME="Build Number">424</ATTRIBUTE>
<ATTRIBUTE NAME="Install Path">C:\Program
Files\Altiris\eXpress\NS
Client\Software Delivery\Software
Packages\{01B54EB5-3679-4C73-9E10-E169D5A5EC59}</ATTRIBUTE>
</OBJECT>
</CLASS>
</ASSET>
</INVENTORY>
</RESOURCE>
</RESOURCE_TYPE>
</AEXDATAEXTRACT>
---------------------------------------------------------------------
In the above xml document I CLASS node corresponds
to the table i the database
and OBJECTS are the records within that table.
ATTRIBUTE node contains the
names of the columns and their values.
As shown in the above example, in the input document
there can be same table
with unequal number of columns. I have to find the
table name with maximum
columns.
I have written the following xsl to do this. I have
got the node (CLASS
NODE)having a node (Row or Record) having maximum
column. To get this node
name i am storing the unique identifier for this
node i.e. I am storing
generate-id for this node. But I am getting generate
id for both the CLASS
node in the above example (I am using xml spy's
debugger to go step by step).
The same construct i am using to find a node with
maximum attributes in the
document. I got only one id for it.
Had i take wrong approach to do this or something
else is wrong ?
Second problem is printing the values for the
attribtues. I have written the
match template construct and there I need to print
value corresponding to the
column headers which are stored in the variable. I
am not able to write
suitable construct to do this. Please tell me how do
i do this. I have tried
to use name function to do this but it is giving me
invalid Xpath expression.
Xsl
====
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output method="text"/>
<xsl:variable name="mostattributes">
<xsl:for-each select="//RESOURCE">
<xsl:sort select="count(attribute::*)"
order="descending" data-type="number"/>
<xsl:if test="position()=1">
<xsl:value-of select="generate-id()"/><!-- this line
has changed! -->
</xsl:if>
</xsl:for-each>
</xsl:variable>
<xsl:variable name="mostattributes-node"
select="//node()[generate-id() =
$mostattributes]"/>
<xsl:variable name="maxattClientAgentTable">
<xsl:for-each select="//CLASS">
<xsl:choose>
<xsl:when
test="normalize-space(@NAME)='Client_Agent'">
<xsl:for-each select="OBJECT">
<xsl:sort select="count(ATTRIBUTE)"
order="descending"/>
<xsl:if test="position()=1">
<xsl:value-of
select="generate-id(..)"/><!--
this line has changed! -->
</xsl:if>
</xsl:for-each>
</xsl:when>
</xsl:choose>
</xsl:for-each>
</xsl:variable>
<xsl:variable name="mostChildattributes-node"
select="//node()[generate-id() =
$maxattClientAgentTable]"/>
<xsl:template match="/">
<xsl:text>RESOURCE_TYPE.GUID,RESOURCE.</xsl:text>
<xsl:for-each select="//node()[generate-id() =
$mostattributes]/@*">
<xsl:value-of select="name(.)" ></xsl:value-of>
<xsl:if test="position()!=last()">,</xsl:if>
</xsl:for-each>
<xsl:text>
</xsl:text>
<xsl:apply-templates select="//RESOURCE"/>
</xsl:template>
<xsl:template match="RESOURCE">
<xsl:variable name="r" select="."/>
<xsl:for-each select="//node()[generate-id() =
$mostattributes]/@*">
<!--Note: How do i get the values according to the
column names ? I mean I
will check if the name of the attribues are same
then print the value for it
otherwise print seperator. How do i do this
?<xsl:value-of
select="normalize-space($r/[name(@)=current()/name(@)])"/>
-->
<xsl:if test="position()!=last()">,</xsl:if>
</xsl:for-each>
<xsl:text>
</xsl:text>
</xsl:template>
</xsl:stylesheet>
---------------------------------------------------------------------
Thanks in advance for any help.
Waiting for reply.
Regards
Dipesh
XSL-List info and archive:
http://www.mulberrytech.com/xsl/xsl-list
__________________________________
Do you Yahoo!?
Yahoo! SiteBuilder - Free, easy-to-use web site design software
http://sitebuilder.yahoo.com
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list