Subject: Re: [xsl] How to get node with maximum child nodes?? From: Mukul Gandhi <mukulw3@xxxxxxxxx> Date: Tue, 26 Aug 2003 01:02:41 -0700 (PDT) |
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@xxxxxxxxxxxxxxx> 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
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
[xsl] How to get node with maximum , Dipesh Khakhkhar | Thread | [xsl] [ANNOUNCE] MoreMotion .., John Eadie |
[xsl] Re: addParameter method and M, Dimitre Novatchev | Date | RE: [xsl] addParameter method and M, Jennifer Phillips |
Month |