Ureader.com  
Microsoft software help and Community
   home   |   control panel login   |   archive   |  
 
XML
data.xmlanalysis
mappoint.webservice
msf
msxml-webrelease
netmyservices.sdk
passport.sdk
soap
soapsdk
uddi.general
uddi.programming
uddi.specification
xml
xmlsqlwebrelease
xsl
  
 
date: Sat, 19 Apr 2008 15:41:01 -0700,    group: microsoft.public.xsl        back       


Table XSL Question - Martin Honnen?   
I saw the post by Julie Smith and it appears that I'm trying to do something 
similar.

I have a variable number of elements in my XML...  I want to display them in 
a table with no more than 4 columns.  So if I have 6 elements, I'll have two 
rows of cells, 4 cells across with only 6 populated.

I'm working with the example that martin provided, but it is only generating 
a single row and displaying my fourth list item.

Here is what I have.

<xsl:variable name="rColumns" select="4"/>
<xsl:for-each select="TestDetail/TestRqmts/RqmtID[position() mod $rColumns = 
0]">
<tr style='height:13.75pt'>
<xsl:for-each select=". | 
following-sibling::TestDetail/TestRqmts/RqmtID[position() < $rColumns]">
<td width="160" valign="top" style='width:117.9pt;border:solid windowtext 
1.0pt;border-top:none;padding:0in 5.4pt 0in 5.4pt;height:13.75pt'>
<p class="RequirementTableCells"><xsl:value-of select="."/></p>
</td>
</xsl:for-each>					
</tr>
</xsl:for-each>

columns was already used so I used rColumns for my variable.

Let me say that I am a complete noob to XSLT.
Thanks for any help...
date: Sat, 19 Apr 2008 15:41:01 -0700   author:   Brian

Re: Table XSL Question - Martin Honnen?   
Brian wrote:

> I have a variable number of elements in my XML...  I want to display them in 
> a table with no more than 4 columns.  So if I have 6 elements, I'll have two 
> rows of cells, 4 cells across with only 6 populated.

Assuming you have the following input XML:

<root>
   <foo>1, 1</foo>
   <foo>1, 2</foo>
   <foo>1, 3</foo>
   <foo>1, 4</foo>
   <foo>2, 1</foo>
   <foo>2, 2</foo>
   <foo>2, 3</foo>
   <foo>2, 4</foo>
   <foo>3, 1</foo>
   <foo>3, 2</foo>
</root>

then this XSLT 1.0 stylesheet

<xsl:stylesheet
   xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
   version="1.0">

   <xsl:param name="cols" select="4"/>

   <xsl:output method="html" indent="yes"/>

   <xsl:template match="/">
     <html lang="en">
       <head>
         <title>Table example</title>
       </head>
       <body>
         <xsl:apply-templates select="root"/>
       </body>
     </html>
   </xsl:template>

   <xsl:template match="root">
     <table border="1">
       <tbody>
         <xsl:apply-templates select="foo[position() mod $cols = 1]" 
mode="row"/>
       </tbody>
     </table>
   </xsl:template>

   <xsl:template match="foo" mode="row">
     <tr>
       <xsl:variable name="siblings" 
select="following-sibling::foo[position() < $cols]"/>
       <xsl:apply-templates select=". | $siblings" mode="cell"/>
       <xsl:if test="count($siblings) < ($cols - 1)">
         <xsl:call-template name="make-empty-cells">
           <xsl:with-param name="n" select="$cols - 1 - count($siblings)"/>
         </xsl:call-template>
       </xsl:if>
     </tr>
   </xsl:template>

   <xsl:template match="foo" mode="cell">
     <td>
       <xsl:apply-templates/>
     </td>
   </xsl:template>

   <xsl:template name="make-empty-cells">
     <xsl:param name="n"/>
     <xsl:if test="$n > 0">
       <td></td>
       <xsl:call-template name="make-empty-cells">
         <xsl:with-param name="n" select="$n - 1"/>
       </xsl:call-template>
     </xsl:if>
   </xsl:template>

</xsl:stylesheet>

produces this HTML output:

<html lang="en">
    <head>
       <meta http-equiv="Content-Type" content="text/html; charset=utf-8">

       <title>Table example</title>
    </head>
    <body>
       <table border="1">
          <tbody>
             <tr>
                <td>1, 1</td>
                <td>1, 2</td>
                <td>1, 3</td>
                <td>1, 4</td>
             </tr>
             <tr>
                <td>2, 1</td>
                <td>2, 2</td>
                <td>2, 3</td>
                <td>2, 4</td>
             </tr>
             <tr>
                <td>3, 1</td>
                <td>3, 2</td>
                <td></td>
                <td></td>
             </tr>
          </tbody>
       </table>
    </body>
</html>


With XSLT 2.0 it is easier:

<xsl:stylesheet
   xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
   version="2.0">

   <xsl:param name="cols" select="4"/>

   <xsl:output method="html" indent="yes"/>

   <xsl:template match="/">
     <html lang="en">
       <head>
         <title>Table example</title>
       </head>
       <body>
         <xsl:apply-templates select="root"/>
       </body>
     </html>
   </xsl:template>

   <xsl:template match="root">
     <table border="1">
       <tbody>
         <xsl:for-each-group select="foo" group-by="(position() - 1) 
idiv $cols">
           <tr>
             <xsl:apply-templates select="current-group()" mode="cell"/>
             <xsl:for-each select="1 to ($cols - count(current-group()))">
               <td></td>
             </xsl:for-each>
           </tr>
         </xsl:for-each-group>
       </tbody>
     </table>
   </xsl:template>

   <xsl:template match="foo" mode="cell">
     <td>
       <xsl:apply-templates/>
     </td>
   </xsl:template>

</xsl:stylesheet>


-- 

	Martin Honnen --- MVP XML
	http://JavaScript.FAQTs.com/
date: Sun, 20 Apr 2008 14:30:07 +0200   author:   Martin Honnen

Re: Table XSL Question - Martin Honnen?   
Thanks for the input...  my xml isn't quite that simple...  but I'm tryin to 
make your transform apply.  But I'm stuck...  


I keep getting the error "Unexpected Child".  I'm using XML Spy (2006 Pro) 
to perform the transform.  

The list of nodes is in the position shown here:

<root>
<Element></Element>
<Element2>
<listparent>
<ListItem1/>
<ListItem2/>
<ListItem3/>
.
.
.
</listparent>



</Element2>
<Element3>
.....

</Element3>


Thanks for your guidance.





"Martin Honnen" wrote:

> Brian wrote:
> 
> > I have a variable number of elements in my XML...  I want to display them in 
> > a table with no more than 4 columns.  So if I have 6 elements, I'll have two 
> > rows of cells, 4 cells across with only 6 populated.
> 
> Assuming you have the following input XML:
> 
> <root>
>    <foo>1, 1</foo>
>    <foo>1, 2</foo>
>    <foo>1, 3</foo>
>    <foo>1, 4</foo>
>    <foo>2, 1</foo>
>    <foo>2, 2</foo>
>    <foo>2, 3</foo>
>    <foo>2, 4</foo>
>    <foo>3, 1</foo>
>    <foo>3, 2</foo>
> </root>
> 
> then this XSLT 1.0 stylesheet
> 
> <xsl:stylesheet
>    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>    version="1.0">
> 
>    <xsl:param name="cols" select="4"/>
> 
>    <xsl:output method="html" indent="yes"/>
> 
>    <xsl:template match="/">
>      <html lang="en">
>        <head>
>          <title>Table example</title>
>        </head>
>        <body>
>          <xsl:apply-templates select="root"/>
>        </body>
>      </html>
>    </xsl:template>
> 
>    <xsl:template match="root">
>      <table border="1">
>        <tbody>
>          <xsl:apply-templates select="foo[position() mod $cols = 1]" 
> mode="row"/>
>        </tbody>
>      </table>
>    </xsl:template>
> 
>    <xsl:template match="foo" mode="row">
>      <tr>
>        <xsl:variable name="siblings" 
> select="following-sibling::foo[position() < $cols]"/>
>        <xsl:apply-templates select=". | $siblings" mode="cell"/>
>        <xsl:if test="count($siblings) < ($cols - 1)">
>          <xsl:call-template name="make-empty-cells">
>            <xsl:with-param name="n" select="$cols - 1 - count($siblings)"/>
>          </xsl:call-template>
>        </xsl:if>
>      </tr>
>    </xsl:template>
> 
>    <xsl:template match="foo" mode="cell">
>      <td>
>        <xsl:apply-templates/>
>      </td>
>    </xsl:template>
> 
>    <xsl:template name="make-empty-cells">
>      <xsl:param name="n"/>
>      <xsl:if test="$n > 0">
>        <td></td>
>        <xsl:call-template name="make-empty-cells">
>          <xsl:with-param name="n" select="$n - 1"/>
>        </xsl:call-template>
>      </xsl:if>
>    </xsl:template>
> 
> </xsl:stylesheet>
> 
> produces this HTML output:
> 
> <html lang="en">
>     <head>
>        <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
> 
>        <title>Table example</title>
>     </head>
>     <body>
>        <table border="1">
>           <tbody>
>              <tr>
>                 <td>1, 1</td>
>                 <td>1, 2</td>
>                 <td>1, 3</td>
>                 <td>1, 4</td>
>              </tr>
>              <tr>
>                 <td>2, 1</td>
>                 <td>2, 2</td>
>                 <td>2, 3</td>
>                 <td>2, 4</td>
>              </tr>
>              <tr>
>                 <td>3, 1</td>
>                 <td>3, 2</td>
>                 <td></td>
>                 <td></td>
>              </tr>
>           </tbody>
>        </table>
>     </body>
> </html>
> 
> 
> With XSLT 2.0 it is easier:
> 
> <xsl:stylesheet
>    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>    version="2.0">
> 
>    <xsl:param name="cols" select="4"/>
> 
>    <xsl:output method="html" indent="yes"/>
> 
>    <xsl:template match="/">
>      <html lang="en">
>        <head>
>          <title>Table example</title>
>        </head>
>        <body>
>          <xsl:apply-templates select="root"/>
>        </body>
>      </html>
>    </xsl:template>
> 
>    <xsl:template match="root">
>      <table border="1">
>        <tbody>
>          <xsl:for-each-group select="foo" group-by="(position() - 1) 
> idiv $cols">
>            <tr>
>              <xsl:apply-templates select="current-group()" mode="cell"/>
>              <xsl:for-each select="1 to ($cols - count(current-group()))">
>                <td></td>
>              </xsl:for-each>
>            </tr>
>          </xsl:for-each-group>
>        </tbody>
>      </table>
>    </xsl:template>
> 
>    <xsl:template match="foo" mode="cell">
>      <td>
>        <xsl:apply-templates/>
>      </td>
>    </xsl:template>
> 
> </xsl:stylesheet>
> 
> 
> -- 
> 
> 	Martin Honnen --- MVP XML
> 	http://JavaScript.FAQTs.com/
>
date: Sun, 20 Apr 2008 09:06:00 -0700   author:   Brian

Re: Table XSL Question - Martin Honnen?   
Brian wrote:

> I keep getting the error "Unexpected Child".  I'm using XML Spy (2006 Pro) 
> to perform the transform.  
> 
> The list of nodes is in the position shown here:
> 
> <root>
> <Element></Element>
> <Element2>
> <listparent>
> <ListItem1/>
> <ListItem2/>
> <ListItem3/>
> .
> .
> .
> </listparent>
> 
> 
> 
> </Element2>
> <Element3>
> .....
> 
> </Element3>

Please post a well-formed minimal but complete sample document and also 
show us the HTML you want to create from that sample.

The above snippet does not tell me at all which elements you want to 
transform into table rows and cells.

-- 

	Martin Honnen --- MVP XML
	http://JavaScript.FAQTs.com/
date: Sun, 20 Apr 2008 18:35:29 +0200   author:   Martin Honnen

Re: Table XSL Question - Martin Honnen?   
I tried to post  with attachments but it doesn't appear to be coming through. 
 Is there something I need to do to get attachments included?

Thanks

"Martin Honnen" wrote:

> Brian wrote:
> 
> > I keep getting the error "Unexpected Child".  I'm using XML Spy (2006 Pro) 
> > to perform the transform.  
> > 
> > The list of nodes is in the position shown here:
> > 
> > <root>
> > <Element></Element>
> > <Element2>
> > <listparent>
> > <ListItem1/>
> > <ListItem2/>
> > <ListItem3/>
> > .
> > .
> > .
> > </listparent>
> > 
> > 
> > 
> > </Element2>
> > <Element3>
> > .....
> > 
> > </Element3>
> 
> Please post a well-formed minimal but complete sample document and also 
> show us the HTML you want to create from that sample.
> 
> The above snippet does not tell me at all which elements you want to 
> transform into table rows and cells.
> 
> -- 
> 
> 	Martin Honnen --- MVP XML
> 	http://JavaScript.FAQTs.com/
>
date: Sun, 20 Apr 2008 15:04:01 -0700   author:   Brian

Re: Table XSL Question - Martin Honnen?   
Maybe this will work...

Attached in my set of files I'm working with.  I will have numerous XML 
files that will need to be transformed.  I was hoping to use the table 
constructed for the requirements as a baseline for the other tables.  The 
html included has more items in it than what is in the xml doc.  Eventually 
the XML will grow to include more information.

Thanks for all the help.

"Martin Honnen"  wrote in message 
news:%23p2GOSwoIHA.2208@TK2MSFTNGP04.phx.gbl...
> Brian wrote:
>
>> I keep getting the error "Unexpected Child".  I'm using XML Spy (2006 
>> Pro)
>> to perform the transform.
>>
>> The list of nodes is in the position shown here:
>>
>> <root>
>> <Element></Element>
>> <Element2>
>> <listparent>
>> <ListItem1/>
>> <ListItem2/>
>> <ListItem3/>
>> .
>> .
>> .
>> </listparent>
>>
>>
>>
>> </Element2>
>> <Element3>
>> .....
>>
>> </Element3>
>
> Please post a well-formed minimal but complete sample document and also
> show us the HTML you want to create from that sample.
>
> The above snippet does not tell me at all which elements you want to
> transform into table rows and cells.
>
> -- 
>
> Martin Honnen --- MVP XML
> http://JavaScript.FAQTs.com/
date: Sun, 20 Apr 2008 17:04:59 -0700   author:   news.microsoft.com

Re: Table XSL Question - Martin Honnen?   
news.microsoft.com wrote:
> Maybe this will work...
> 
> Attached in my set of files I'm working with.  I will have numerous XML 
> files that will need to be transformed.  I was hoping to use the table 
> constructed for the requirements as a baseline for the other tables.  The 
> html included has more items in it than what is in the xml doc.  Eventually 
> the XML will grow to include more information.

You get the unexpected child error as your stylesheet has xsl:template 
elements at the wrong level. You can't nest xsl:template elements, 
instead you need to put them all as children of the xsl:stylesheet 
element. Then make sure you use proper xsl:apply-templates to "call" the 
defined templates.

So assuming you want to transform those RqmtID elements into table cells 
you would do e.g.

<xsl:stylesheet
   xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
   version="1.0">

   <xsl:param name="cols" select="4"/>

   <xsl:template match="/TestProc">
     <html>
       <head>
         ...
       </head>
       <body>
         ...
         <xsl:apply-templates select="TestDetail/TestRqmts"/>
       </body>
     </html>
   </xsl:template>

   <xsl:template match="TestRqmts">
     <table border="1">
       <tbody>
          <xsl:apply-templates select="RqmtID[position() mod $cols = 1]"
mode="row"/>
       </tbody>
     </table>
   </xsl:template>

    <xsl:template match="RqmtID" mode="row">
      <tr>
        <xsl:variable name="siblings" 
select="following-sibling::RqmtID[position() < $cols]"/>
        <xsl:apply-templates select=". | $siblings" mode="cell"/>
        <xsl:if test="count($siblings) < ($cols - 1)">
          <xsl:call-template name="make-empty-cells">
            <xsl:with-param name="n" select="$cols - 1 - count($siblings)"/>
          </xsl:call-template>
        </xsl:if>
      </tr>
    </xsl:template>

    <xsl:template match="RqmtID" mode="cell">
      <td>
        <xsl:apply-templates/>
      </td>
    </xsl:template>
-- 

	Martin Honnen --- MVP XML
	http://JavaScript.FAQTs.com/
date: Mon, 21 Apr 2008 14:32:03 +0200   author:   Martin Honnen

Re: Table XSL Question - Martin Honnen?   
Thanks Martin..

I tried it out this morning and got the following error:

"Undefined Template"  ...on this line in the XML Spy debugger...
<xsl:with-param name="n" select="$cols - 1 - count($siblings)"/>

I added a param identifier line and it that corrected it.

Thanks for your help.

B


"Martin Honnen" wrote:

> news.microsoft.com wrote:
> > Maybe this will work...
> > 
> > Attached in my set of files I'm working with.  I will have numerous XML 
> > files that will need to be transformed.  I was hoping to use the table 
> > constructed for the requirements as a baseline for the other tables.  The 
> > html included has more items in it than what is in the xml doc.  Eventually 
> > the XML will grow to include more information.
> 
> You get the unexpected child error as your stylesheet has xsl:template 
> elements at the wrong level. You can't nest xsl:template elements, 
> instead you need to put them all as children of the xsl:stylesheet 
> element. Then make sure you use proper xsl:apply-templates to "call" the 
> defined templates.
> 
> So assuming you want to transform those RqmtID elements into table cells 
> you would do e.g.
> 
> <xsl:stylesheet
>    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>    version="1.0">
> 
>    <xsl:param name="cols" select="4"/>
> 
>    <xsl:template match="/TestProc">
>      <html>
>        <head>
>          ...
>        </head>
>        <body>
>          ...
>          <xsl:apply-templates select="TestDetail/TestRqmts"/>
>        </body>
>      </html>
>    </xsl:template>
> 
>    <xsl:template match="TestRqmts">
>      <table border="1">
>        <tbody>
>           <xsl:apply-templates select="RqmtID[position() mod $cols = 1]"
> mode="row"/>
>        </tbody>
>      </table>
>    </xsl:template>
> 
>     <xsl:template match="RqmtID" mode="row">
>       <tr>
>         <xsl:variable name="siblings" 
> select="following-sibling::RqmtID[position() < $cols]"/>
>         <xsl:apply-templates select=". | $siblings" mode="cell"/>
>         <xsl:if test="count($siblings) < ($cols - 1)">
>           <xsl:call-template name="make-empty-cells">
>             <xsl:with-param name="n" select="$cols - 1 - count($siblings)"/>
>           </xsl:call-template>
>         </xsl:if>
>       </tr>
>     </xsl:template>
> 
>     <xsl:template match="RqmtID" mode="cell">
>       <td>
>         <xsl:apply-templates/>
>       </td>
>     </xsl:template>
> -- 
> 
> 	Martin Honnen --- MVP XML
> 	http://JavaScript.FAQTs.com/
>
date: Mon, 21 Apr 2008 09:54:01 -0700   author:   Brian

Re: Table XSL Question - Martin Honnen?   
Actually...  needed to add the make-empty-cells template back into the 
transform.  It is working as hoped now.  Thanks again for the details.

"Martin Honnen" wrote:

> news.microsoft.com wrote:
> > Maybe this will work...
> > 
> > Attached in my set of files I'm working with.  I will have numerous XML 
> > files that will need to be transformed.  I was hoping to use the table 
> > constructed for the requirements as a baseline for the other tables.  The 
> > html included has more items in it than what is in the xml doc.  Eventually 
> > the XML will grow to include more information.
> 
> You get the unexpected child error as your stylesheet has xsl:template 
> elements at the wrong level. You can't nest xsl:template elements, 
> instead you need to put them all as children of the xsl:stylesheet 
> element. Then make sure you use proper xsl:apply-templates to "call" the 
> defined templates.
> 
> So assuming you want to transform those RqmtID elements into table cells 
> you would do e.g.
> 
> <xsl:stylesheet
>    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>    version="1.0">
> 
>    <xsl:param name="cols" select="4"/>
> 
>    <xsl:template match="/TestProc">
>      <html>
>        <head>
>          ...
>        </head>
>        <body>
>          ...
>          <xsl:apply-templates select="TestDetail/TestRqmts"/>
>        </body>
>      </html>
>    </xsl:template>
> 
>    <xsl:template match="TestRqmts">
>      <table border="1">
>        <tbody>
>           <xsl:apply-templates select="RqmtID[position() mod $cols = 1]"
> mode="row"/>
>        </tbody>
>      </table>
>    </xsl:template>
> 
>     <xsl:template match="RqmtID" mode="row">
>       <tr>
>         <xsl:variable name="siblings" 
> select="following-sibling::RqmtID[position() < $cols]"/>
>         <xsl:apply-templates select=". | $siblings" mode="cell"/>
>         <xsl:if test="count($siblings) < ($cols - 1)">
>           <xsl:call-template name="make-empty-cells">
>             <xsl:with-param name="n" select="$cols - 1 - count($siblings)"/>
>           </xsl:call-template>
>         </xsl:if>
>       </tr>
>     </xsl:template>
> 
>     <xsl:template match="RqmtID" mode="cell">
>       <td>
>         <xsl:apply-templates/>
>       </td>
>     </xsl:template>
> -- 
> 
> 	Martin Honnen --- MVP XML
> 	http://JavaScript.FAQTs.com/
>
date: Mon, 21 Apr 2008 10:13:01 -0700   author:   Brian

Re: Table XSL Question - Martin Honnen?   
Brian wrote:
> Actually...  needed to add the make-empty-cells template back into the 
> transform.  

Yes, I only posted a snippet with changes, the make-empty-cells template 
stays as it is.

-- 

	Martin Honnen --- MVP XML
	http://JavaScript.FAQTs.com/
date: Mon, 21 Apr 2008 19:44:22 +0200   author:   Martin Honnen

Google
 
Web ureader.com


    COPYRIGHT 2007, YARDI TECHNOLOGY LIMITED, ALL RIGHT RESERVE  |   contact us