Help with XSL to make HTML table

  • Thread starter Virginia Kirkendall
  • Start date
V

Virginia Kirkendall

Hi: I'm new with this & need help creating a XSL table that looks
like the following:


---------------------------------------------------------
| | | | | |
|Title |CrossCut |Institution |START |END |
| | | | | |
| | |PI | | |
| | | | | |
|Project| | | | |
|Summary| | | | |
---------------------------------------------------------

XML :

<Programs>
<Title>DETECTING AND BLOCKING</Title>
<CrossCut>BASE</CrossCut>
<PI>John Jones</PI>
<Institution>INSTITUTE</Institution>
<Project_Summary>build an effective</Project_Summary>
<Start>2004-09-15T00:00:00</Start>
<End>2006-09-14T00:00:00</End>
</Programs>
<Programs>
<Title>NETWORKS</Title>
<CrossCut>BASE</CrossCut>
<PI>Mary QuiteContrary</PI>
<Institution>BOSTON UNIVERSITY</Institution>
<Project_Summary>This application describes an
important</Project_Summary>
<Start>2004-08-15T00:00:00</Start>
<End>2007-08-14T00:00:00</End>
</Programs>
<Programs>
<Title>NETWORKS</Title>
<CrossCut>BASE</CrossCut>
<PI>Harry Pit</PI>
<Institution>University</Institution>
<Project_Summary>This application describes an
important</Project_Summary>
<Start>2004-08-15T00:00:00</Start>
<End>2007-08-14T00:00:00</End>
</Programs>


The desired effect will be to sorta group by Title (see that two
titles are same) with subsequent details spanning the row.

Thanks very much for any help I could really use it-- Ginger
 
W

William Park

Virginia Kirkendall said:
Hi: I'm new with this & need help creating a XSL table that looks
like the following:


---------------------------------------------------------
| | | | | |
|Title |CrossCut |Institution |START |END |
| | | | | |
| | |PI | | |
| | | | | |
|Project| | | | |
|Summary| | | | |
---------------------------------------------------------

XML :

<Programs>
<Title>DETECTING AND BLOCKING</Title>
<CrossCut>BASE</CrossCut>
<PI>John Jones</PI>
<Institution>INSTITUTE</Institution>
<Project_Summary>build an effective</Project_Summary>
<Start>2004-09-15T00:00:00</Start>
<End>2006-09-14T00:00:00</End>
</Programs>
<Programs>
<Title>NETWORKS</Title>
<CrossCut>BASE</CrossCut>
<PI>Mary QuiteContrary</PI>
<Institution>BOSTON UNIVERSITY</Institution>
<Project_Summary>This application describes an
important</Project_Summary>
<Start>2004-08-15T00:00:00</Start>
<End>2007-08-14T00:00:00</End>
</Programs>
<Programs>
<Title>NETWORKS</Title>
<CrossCut>BASE</CrossCut>
<PI>Harry Pit</PI>
<Institution>University</Institution>
<Project_Summary>This application describes an
important</Project_Summary>
<Start>2004-08-15T00:00:00</Start>
<End>2007-08-14T00:00:00</End>
</Programs>


The desired effect will be to sorta group by Title (see that two
titles are same) with subsequent details spanning the row.

Thanks very much for any help I could really use it-- Ginger


Get a patched Bash shell with Expat XML parser interface,
http://freshmeat.net/projects/bashdiff/
help xml
help basp

First, parsing of your XML text would go something like

start () {
if [[ ${XML_ELEMENT_STACK[1]} == Programs ]]; then
unset Title Crosscut Pi Institution Project_Summary Start End
fi
}
data () {
case ${XML_ELEMENT_STACK[1]} in
Title|CrossCut|PI|Institution|Project_Summary|Start|End)
strcat ${XML_ELEMENT_STACK[1]} "$1" ;;
esac
}
end () {
if [[ ${XML_ELEMENT_STACK[1]} == Programs ]]; then
cat <<+ EOF
Title={$Title}
CrossCut={$CrossCut}
PI={$PI}
Institution={$Institution}
Project_Summary={$Project_Summary}
Start={$Start}
End={$End}
EOF
fi
}
xml -s start -d data -e end "`< file.xml`"

You should get

Title={DETECTING AND BLOCKING}
CrossCut={BASE}
PI={John Jones}
Institution={INSTITUTE}
Project_Summary={build an effective}
Start={2004-09-15T00:00:00}
End={2006-09-14T00:00:00}

for the first <Programs>...</Programs> section. Now, if you consider

cat <<+ EOF
...
EOF

as HTML template, with '...' replaced by your table template, then your
solution becomes self-evident. If you have HTML code in a file, then
you can use my BASP (Bash Server Pages) engine.

For that, your template would go something like

<table> ...
<td><% echo -n $Title %></td>
<td><% echo -n $CrossCut %></td>
...
</table>

and you would print it, like

basp "`< template.html`"
 
W

William Park

William Park said:
start () {
if [[ ${XML_ELEMENT_STACK[1]} == Programs ]]; then
unset Title Crosscut Pi Institution Project_Summary Start End

Typo... should be 'CrossCut' and 'PI'.
fi
}

For that, your template would go something like

<table> ...
<td><% echo -n $Title %></td>
<td><% echo -n $CrossCut %></td>

You can use shortcut, ala ASP,
<td><%=$Title%></td>
...
 
J

Joris Gillis

The desired effect will be to sorta group by Title (see that two
titles are same) with subsequent details spanning the row.

Hi,

This is an XSLT solution to your problem ,or at least, what I understand
of it.

<?xml version="1.0" ?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:eek:utput method="html"/>

<xsl:key name="title" match="Title" use="."/>
<xsl:template match="/">
<html>
<head>
</head>
<body>
<table>
<xsl:for-each
select="//Title[generate-id(.)=generate-id(key('title',.))]">
<!-- Loop through all titles (no duplicates) -->
<xsl:sort select="current()"/>
<tr>
<th>Title</th>
<th>Crosscut</th>
<th>PI</th>
<th>Institution</th>
<th>Project_Summary</th>
<th>Start</th>
<th>End</th>
</tr>
<xsl:apply-templates select="//Programs[Title= current() ]"/>
</xsl:for-each>
</table>
</body></html>
</xsl:template>

<xsl:template match="Programs">
<tr>
<td><xsl:value-of select="Title"/></td>
<td><xsl:value-of select="CrossCut"/></td>
<td><xsl:value-of select="PI"/></td>
<td><xsl:value-of select="Institution"/></td>
<td><xsl:value-of select="Project_Summary"/></td>
<td><xsl:value-of select="Start"/></td>
<td><xsl:value-of select="End"/></td>
</tr>
</xsl:template>

</xsl:stylesheet>

regards,
 
V

Virginia Kirkendall

Thanks so much for your reply. This is getting very close!
Unfortunately, it's not quite there. The row headers do not repeat
for each duplicate title, which is good, but the records do repeat.
I am trying to understand your code & which elements are trying to
group the records, but I am new to this & haven't quite figured it
out. Again, thanks very much for posting your code.

Joris Gillis said:
The desired effect will be to sorta group by Title (see that two
titles are same) with subsequent details spanning the row.

Hi,

This is an XSLT solution to your problem ,or at least, what I understand
of it.

<?xml version="1.0" ?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:eek:utput method="html"/>

<xsl:key name="title" match="Title" use="."/>
<xsl:template match="/">
<html>
<head>
</head>
<body>
<table>
<xsl:for-each
select="//Title[generate-id(.)=generate-id(key('title',.))]">
<!-- Loop through all titles (no duplicates) -->
<xsl:sort select="current()"/>
<tr>
<th>Title</th>
<th>Crosscut</th>
<th>PI</th>
<th>Institution</th>
<th>Project_Summary</th>
<th>Start</th>
<th>End</th>
</tr>
<xsl:apply-templates select="//Programs[Title= current() ]"/>
</xsl:for-each>
</table>
</body></html>
</xsl:template>

<xsl:template match="Programs">
<tr>
<td><xsl:value-of select="Title"/></td>
<td><xsl:value-of select="CrossCut"/></td>
<td><xsl:value-of select="PI"/></td>
<td><xsl:value-of select="Institution"/></td>
<td><xsl:value-of select="Project_Summary"/></td>
<td><xsl:value-of select="Start"/></td>
<td><xsl:value-of select="End"/></td>
</tr>
</xsl:template>

</xsl:stylesheet>

regards,
 
J

Joris Gillis

Hi,

Perhaps this could get you closer to your goal:

<xsl:key name="title" match="Title" use="."/>
<xsl:template match="/">
<html>
<head>
</head>
<body>
<table>
<xsl:for-each select="//Title[generate-id(.)=generate-id(key('title',.))]">
<!-- Loop through all titles (no duplicates) -->
<!-- sort on title -->
<xsl:sort select="current()"/>
<!-- print table headers -->
<tr>
<th>Title</th>
<th>Crosscut</th>
<th>PI</th>
<th>Institution</th>
<th>Project_Summary</th>
<th>Start</th>
<th>End</th>
</tr>
<!-- evaluate all 'Programs' nodes that have a 'Title' child equal to the Title of this iteration of the for-each loop -->
<xsl:apply-templates select="//Programs[Title=current()]"/>
</xsl:for-each>
</table>
</body></html>
</xsl:template>

<xsl:template match="Programs">
<!-- print a new table row and evaluate the children of the 'Programs' node -->
<tr>
<td><xsl:apply-templates select="Title"/></td>
<td><xsl:apply-templates select="CrossCut"/></td>
<td><xsl:apply-templates select="PI"/></td>
<td><xsl:apply-templates select="Institution"/></td>
<td><xsl:apply-templates select="Project_Summary"/></td>
<td><xsl:apply-templates select="Start"/></td>
<td><xsl:apply-templates select="End"/></td>
</tr>
</xsl:template>

<xsl:template match="*">
<!-- select the text value of a node unless it's a duplicate of a previous text value-->
<!-- in other words, only unique text values will be returned-->
<xsl:if test="generate-id(//*[.=current()][../Title = current()/../Title ])=generate-id(.)">
<xsl:value-of select="."/>
</xsl:if>
</xsl:template>

regards,
 
V

Virginia Kirkendall

Joris! Thank you. Thank you.

This is great & you've helped me to begin to understand. Many, many thanks,

Ginger
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,535
Members
45,007
Latest member
obedient dusk

Latest Threads

Top