My Portal with XSLT
Tommi Komulainen <[email protected]>
| Newsgroups | gmane.comp.web.galeon.devel |
|---|---|
| Message-ID | <[email protected]> |
Hi all, I've been playing around with XSLT attempting to generate the My Portal page with it, instead of doing silly things like hardcoding the portal structure in code. IMHO, XSLT is just the right tool for the job. If you look at what XSLT does, you should be convinced too ;) Please find attached a stylesheet I've got almost finished. The page the stylesheet generates should be identical (within reason) to the new My Portal in 1.3.2. See the attached XHTML file for yourself, it's generated from the default-bookmarks.xbel (you should have galeon installed in /usr/local or the CSS and icons can't be found and the page will look rather dull) You can still customize basically every aspect of My Portal by modifying the XSLT stylesheet, but I bet it'll be much easier than editing the code. XSLT will also enable you to generate the My Portal page without running galeon. You can use the following command to try the stylesheet on your own bookmarks and see if anything breaks: xsltproc myportal.xsl bookmarks.xbel >myportal.html (add '--stringparam prefix /opt/gnome' if you've installed galeon in /opt/gnome instead of the default /usr/local) Now, what's really going to rock your socks off is that if you add <?xml-stylesheet href="myportal.xsl" type="text/xsl"?> in the beginning of the bookmarks.xbel file, you can simply open the bookmarks file itself in the browser and see My Portal. Well, almost, smart bookmarks text entries seem to disappear somewhere, but anyway... What do you think? Could this be used as new My Portal? -- Tommi Komulainen [email protected] GPG 1024D/68388EE6 6FD6 DD79 EB38 BF6F 3533 09C0 04A8 9871 6838 8EE6
myportal.xsl
(text/plain, 5 KB)
<?xml version="1.0"?> <!-- myportal.xsl - XSL stylesheet for converting (Galeon) XBEL bookmarks file - into Galeon My Portal. - - Copyright (C) 2003 Tommi Komulainen <[email protected]> - Available under the terms of the GNU General Public License version 2. --> <xsl:stylesheet version="1.0" xmlns="http://www.w3.org/1999/xhtml" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:str="http://exslt.org/strings" exclude-result-prefixes="str" extension-element-prefixes="str"> <xsl:output method="xml" indent="yes" encoding="utf-8" media-type="text/html" omit-xml-declaration="no" doctype-public="-//W3C//DTD XHTML Transitional 1.0//EN" doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" /> <!-- default installation prefix, can be overridden with for example - xsltproc -\-stringparam prefix /opt/gnome --> <xsl:param name="prefix" select="'/usr/local'" /> <!-- other helpful variables, don't touch --> <xsl:variable name="datadir" select="concat('file:',$prefix,'/share/galeon')"/> <xsl:variable name="galeon">http://galeon.sourceforge.net/</xsl:variable> <!-- My Portal --> <xsl:template match="/"> <html xmlns="http://www.w3.org/1999/xhtml" lang="en"> <head> <link rel="stylesheet" type="text/css" href="{concat($datadir,'/myportal.css')}"/> <title>My Portal</title> </head> <body> <!-- header --> <div class="top_bar"> <table cellpadding="2" cellspacing="0" width="100%" border="0"> <tbody> <tr> <td><img alt="" src="{concat($datadir,'/galeon.png')}" />myportal:</td> </tr> </tbody> </table> </div> <div class="top2"> <a href="http://galeon.sourceforge.net/"> <img class="logo" alt="Galeon logo" src="{concat($datadir,'/logo.png')}" /> </a> </div> <p><br /></p> <!-- add all bookmarks here --> <xsl:apply-templates select="xbel"/> <!-- or we could also use this to show only particular folder --> <!-- <xsl:apply-templates select="//folder[title = $path]"/> --> <!-- footer --> <div class="bottom_bar"><center><b>Galeon</b> : <i>the web, only the web</i></center></div> </body></html> </xsl:template> <!-- /My Portal --> <!-- xbel --> <xsl:template match="xbel"> <blockquote> <a class="heading"><strong>Bookmarks</strong></a> <xsl:apply-templates select="folder|bookmark|separator|alias"/> </blockquote> </xsl:template> <!-- /xbel --> <!-- folder --> <xsl:template match="folder"> <blockquote> <a class="heading"> <strong> <xsl:value-of select="title"/> </strong> </a> <br /> <xsl:apply-templates select="folder|bookmark|separator|alias"/> </blockquote> </xsl:template> <!-- /folder --> <!-- separator --> <xsl:template match="separator"> <br /> </xsl:template> <!-- /separator --> <!-- alias --> <xsl:template match="alias"> <xsl:variable name="ref"><xsl:value-of select="@ref"/></xsl:variable> <!-- get the bookmark or folder the alias is referring to - - TODO currently this is limited to just bookmarks, because I just - can't figure out how to avoid infinite recursion that happens - with folders... --> <!-- <xsl:apply-templates select="//*[@id = $ref]"/> --> <i> <xsl:apply-templates select="//bookmark[@id = $ref]"/> </i> </xsl:template> <!-- /alias --> <!-- bookmark --> <xsl:template match="bookmark"> <a href="{@href}"> <xsl:value-of select="title"/> </a> </xsl:template> <!-- /bookmark --> <!-- smart bookmark --> <xsl:template match="bookmark[info/metadata[@owner = $galeon]/smarturl]"> <xsl:variable name="smarturl" select="info/metadata[@owner = $galeon]/smarturl" /> <xsl:variable name="pixmap" select="info/metadata[@owner = $galeon]/pixmap" /> <!-- submit url is the part before the query string - XXX why are we using GET? --> <form method="get" action="{substring-before($smarturl, '?')}"> <xsl:variable name="query" select="substring-after($smarturl, '?')" /> <!-- parameters are separated by ampersands '&' --> <xsl:for-each select="str:tokenize($query, '&')"> <!-- param := name [ '=' value ] --> <xsl:variable name="name" select="substring-before(., '=')"/> <xsl:variable name="value" select="substring-after(., '=')"/> <xsl:choose> <!-- parameter with variable value --> <xsl:when test="$value = '%s'"> <input type="text" name="{$name}" value="" size="30" /> </xsl:when> <!-- parameter without a value (I think) --> <xsl:when test="$name = $value"> <input type="hidden" name="{$name}" />> </xsl:when> <!-- parameter with fixed value --> <xsl:otherwise> <input type="hidden" name="{$name}" value="{$value}" /> </xsl:otherwise> </xsl:choose> </xsl:for-each> <!-- use image for submit if we have one, ordinary button otherwise --> <xsl:choose> <xsl:when test="$pixmap"> <input type="image" value="{title}" src="{$pixmap}" /> </xsl:when> <xsl:otherwise> <input type="submit" value="{title}" /> </xsl:otherwise> </xsl:choose> </form> </xsl:template> <!-- /smart bookmark --> </xsl:stylesheet> <!-- vim: set sts=2 sw=2: -->
myportal.html
(text/html, 13.4 KB)
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Transitional 1.0//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link rel="stylesheet" type="text/css" href="file:/usr/local/share/galeon/myportal.css" />
<title>My Portal</title>
</head>
<body>
<div class="top_bar">
<table cellpadding="2" cellspacing="0" width="100%" border="0">
<tbody>
<tr>
<td><img alt="" src="file:/usr/local/share/galeon/galeon.png" />myportal:</td>
</tr>
</tbody>
</table>
</div>
<div class="top2">
<a href="http://galeon.sourceforge.net/">
<img class="logo" alt="Galeon logo" src="file:/usr/local/share/galeon/logo.png" />
</a>
</div>
<p>
<br />
</p>
<blockquote>
<a class="heading">
<strong>Bookmarks</strong>
</a>
<blockquote>
<a class="heading">
<strong>New bookmarks</strong>
</a>
<br />
</blockquote>
<blockquote>
<a class="heading">
<strong>GNU / Linux</strong>
</a>
<br />
<a href="http://www.fsf.org">Free Software Foundation (FSF)</a>
<blockquote>
<a class="heading">
<strong>Gnome</strong>
</a>
<br />
<a href="http://www.gnome.org/">Gnome.org</a>
<a href="http://www.gnomedesktop.org">Footnotes - Gnome News Portal</a>
<a href="http://es.gnome.org/">GNOME Hispano</a>
<a href="http://www.gnomesupport.org/forums">Gnome User's Support Forum</a>
<a href="http://www.gnomesupport.org">Gnome Support.org</a>
<i>
<a href="http://galeon.sourceforge.net/">Galeon: the web, only the web</a>
</i>
<blockquote>
<a class="heading">
<strong>Development</strong>
</a>
<br />
<a href="http://developer.gnome.org/">The GNOME Developer Site</a>
<a href="http://mail.gnome.org">Gnome Mailing Lists</a>
<a href="http://bugzilla.gnome.org">Gnome Bugzilla</a>
<a href="http://lidn.sourceforge.net">Api Documentation</a>
</blockquote>
</blockquote>
<blockquote>
<a class="heading">
<strong>News</strong>
</a>
<br />
<a href="http://www.desktoplinux.com">Desktop Linux</a>
<a href="http://www.osnews.com">OSNews</a>
<a href="http://www.pclinuxonline.com">Pclinuxonline</a>
<a href="http://www.slashdot.org">Slashdot</a>
</blockquote>
</blockquote>
<blockquote>
<a class="heading">
<strong>Internet</strong>
</a>
<br />
<a href="http://www.w3.org/">The World Wide Web Consortium</a>
<a href="http://galeon.sourceforge.net/">Galeon: the web, only the web</a>
</blockquote>
<br />
<blockquote>
<a class="heading">
<strong>Toolbar</strong>
</a>
<br />
<i></i>
<form method="get" action="http://www.google.com/search">
<input type="text" name="q" value="" size="30" />
<input type="image" value="Google" src="/usr/local/share/galeon/google.png" />
</form>
<form method="get" action="http://groups.google.com/groups">
<input type="text" name="q" value="" size="30" />
<input type="hidden" name="meta" value="site%3Dgroups" />
<input type="image" value="Usenet" src="/usr/local/share/galeon/google_groups.png" />
</form>
<form method="get" action="http://images.google.com/images">
<input type="text" name="q" value="" size="30" />
<input type="image" value="Images" src="/usr/local/share/galeon/google_images.png" />
</form>
<form method="get" action="http://www.wikipedia.org/w/wiki.phtml">
<input type="text" name="search" value="" size="30" />
<input type="submit" value="Dictionary" />
</form>
<blockquote>
<a class="heading">
<strong>Bookmarklets</strong>
</a>
<br />
<a href="http://www.bookmarklets.com/">More Bookmarklets</a>
<br />
<a href="javascript:location.href=%22http://web.archive.org/web/*/%22+location.href">Old versions of this page</a>
<a href="javascript:if(frames.length%3E0){F=' (Open frame in new window first.)'}else{F=''}Q=document.getSelection();if(!Q){void(Q=prompt('No text selected on page.'+F+'\n\nKeywords...?',''))};if(Q)location.href='http://bookmarklets.com/moreinfo.phtml?q='+escape(Q)">More Info About...</a>
<br />
<a href="javascript:if(document.images.length%3C1){alert('No image!')}else{D0iB=document.images[0];sZ2T=prompt('Resize by..','1.5');if(sZ2T){with(document){write('%3Cimg src='+D0iB.src+' width='+sZ2T*D0iB.width+' height='+sZ2T*D0iB.height+'%3E');close()}}}void(null)">Zoom on First Image...</a>
<a href="javascript:if(frames.length%3C1){var c0l=prompt('Change to which background color?','');if (c0l != null) void(document.bgColor=c0l)}else{alert('Page has frames. Use the version of this bookmarklet for frames. (bookmarklets.com)')}">Page Color...</a>
<br />
<a href="javascript:var wN2sc8Rl;Sa5gNA9k=new Function('clearTimeout(wN2sc8Rl)');document.onkeydown=Sa5gNA9k;Sa5gNA9k();void(wN2sc8Rl=setInterval('if(pageYOffset%3Cdocument.height-innerHeight){window.scrollBy(0,1)}else{Sa5gNA9k()}',150))">Scroll Page (very slow)</a>
<a href="javascript:var wN2scRl;Sa5gNA9k=new Function('clearTimeout(wN2scRl)');document.onkeydown=Sa5gNA9k;Sa5gNA9k();void(wN2scRl=setInterval('if(pageYOffset%3Cdocument.height-innerHeight){window.scrollBy(0,1)}else{Sa5gNA9k()}',50))">Scroll Page (slow)</a>
<a href="javascript:var wN2scRl;Sa5gNA9k=new Function('clearTimeout(wN2scRl)');document.onkeydown=Sa5gNA9k;Sa5gNA9k();void(wN2scRl=setInterval('if(pageYOffset%3Cdocument.height-innerHeight){window.scrollBy(0,2)}else{Sa5gNA9k()}',50))">Scroll Page (fast)</a>
<a href="javascript:var wN2scRl;Sa5gNA9k=new Function('clearTimeout(wN2scRl)');document.onkeydown=Sa5gNA9k;Sa5gNA9k();void(wN2scRl=setInterval('if(pageYOffset%3Cdocument.height-innerHeight){window.scrollBy(0,10)}else{Sa5gNA9k()}',50))">Scroll Page (very fast)</a>
<a href="javascript:var wN2scRl;S3g=new Function('clearTimeout(wN2scRl)');document.onkeydown=S3g;a7T=prompt('Rate...','');if(a7T!=null){S3g();void(wN2scRl=setInterval('if(pageYOffset%3Cdocument.height-innerHeight){scrollBy(0,a7T)}else{S3g()}',50))}else{void(null)}">Scroll Page... (variable)</a>
<br />
<a href="javascript:if(frames.length%3C1){alert('The server indicates that the page was last modified: ' + window.document.lastModified)}else{alert('Page is framed. Use version of bookmarklet for frames. (bookmarklets.com)')}">Page Freshness?</a>
<a href="javascript:if(frames.length%3E0){alert('Frames!')}else{ulBV3pQy=document.getSelection();if(ulBV3pQy!=''){location.href=ulBV3pQy.replace(/\042/g,'').replace(/\047/g,'').replace(/\s/g,'')}else{alert('Select text on page like:\n http://www.domain.com...')}}">Go To Selected URL</a>
<a href="javascript:dT30FfN3b=new Date();void(window.open(location.href,'w'+dT30FfN3b.getTime()))">Duplicate Page</a>
<a href="javascript:void(InPageBookmark=pageYOffset)">Set In-Page Bookmark</a>
<a href="javascript:if (typeof InPageBookmark=='undefined'){alert('No in-page bookmark. Use Set In-Page Bookmark tool. (bookmarklets.com)')}else{scrollBy(0,InPageBookmark-pageYOffset)}">Go To In-Page Bookmark</a>
<br />
<a href="javascript:if(document.cookie.length%3C1){alert('No cookie for this site.')}else{alert('Cookie for this site: '+document.cookie)}">Read Cookie for Site</a>
<a href="javascript:function ROIoiW(){var i=0,j,A='anonymous',D,E,F=document.forms;while(i%3CF.length){E=F[i].elements;for(j=0;j%3CE.length;j++){D=E[j];if(D.type=='text'){D.value=(D.name.toUpperCase().indexOf('MAIL')!=-1)?A+'@example.com':A}}i++}}ROIoiW();void(null)">AutoFill Anonymous</a>
<a href="javascript:void(location.href='http://translate.google.com/translate?hl=en%26u='+location.href)">Translate to English</a>
</blockquote>
</blockquote>
<blockquote>
<a class="heading">
<strong>Sample Smart Bookmarks</strong>
</a>
<br />
<form method="get" action="http://www.google.com/search">
<input type="text" name="q" value="" size="30" />
<input type="image" value="Google" src="/usr/local/share/galeon/google.png" />
</form>
<form method="get" action="http://groups.google.com/groups">
<input type="text" name="q" value="" size="30" />
<input type="hidden" name="meta" value="site%3Dgroups" />
<input type="image" value="Usenet" src="/usr/local/share/galeon/google_groups.png" />
</form>
<form method="get" action="http://images.google.com/images">
<input type="text" name="q" value="" size="30" />
<input type="image" value="Images" src="/usr/local/share/galeon/google_images.png" />
</form>
<form method="get" action="http://www.m-w.com/cgi-bin/dictionary">
<input type="text" name="va" value="" size="30" />
<input type="submit" value="Dictionary" />
</form>
<form method="get" action="http://search.yahoo.com/bin/search">
<input type="text" name="p" value="" size="30" />
<input type="submit" value="Yahoo!" />
</form>
<form method="get" action="http://search.dogpile.com/texis/search">
<input type="text" name="q" value="" size="30" />
<input type="hidden" name="geo" value="no" />
<input type="hidden" name="fs" value="web" />
<input type="hidden" name="av" value="custom" />
<input type="hidden" name="engines" value="goto" />
<input type="hidden" name="engines" value="looksmart" />
<input type="hidden" name="engines" value="thunderstone" />
<input type="hidden" name="engines" value="findwhat" />
<input type="hidden" name="engines" value="sprinks" />
<input type="hidden" name="engines" value="directhit" />
<input type="hidden" name="engines" value="google" />
<input type="hidden" name="engines" value="infoseek" />
<input type="hidden" name="engines" value="lycos" />
<input type="hidden" name="engines" value="kanoodle" />
<input type="hidden" name="engines" value="opendir" />
<input type="hidden" name="engines" value="realnames" />
<input type="hidden" name="engines" value="altavista" />
<input type="hidden" name="engines" value="yahoo" />
<input type="submit" value="Dogpile" />
</form>
<form method="get" action="http://www.linuxpackages.net/search_view.php">
<input type="hidden" name="by" value="name" />
<input type="hidden" name="what_cat" value="" />
<input type="hidden" name="subcat" value="" />
<input type="hidden" name="ver" value="8" />
<input type="text" name="name" value="" size="30" />
<input type="image" value="LinuxPackages" src="/usr/local/share/galeon/slack.png" />
</form>
<form method="get" action="http://finance.yahoo.com/q">
<input type="text" name="s" value="" size="30" />
<input type="hidden" name="d" value="c" />
<input type="hidden" name="k" value="c4" />
<input type="hidden" name="t" value="1d" />
<input type="image" value="Stocks" src="/usr/local/share/galeon/stocks.png" />
</form>
<form method="get" action="http://bugzilla.gnome.org/show_bug.cgi">
<input type="text" name="id" value="" size="30" />
<input type="image" value="Bug #" src="/usr/local/share/galeon/bug.png" />
</form>
<form method="get" action="http://freshmeat.net/search">
<input type="text" name="q" value="" size="30" />
<input type="image" value="Freshmeat" src="/usr/local/share/galeon/freshmeat.png" />
</form>
<form method="get" action="http://www.gnu.org/search/fsd-search.py">
<input type="text" name="q" value="" size="30" />
<input type="image" value="GNU Free Software Directory" src="/usr/local/share/galeon/gnu.png" />
</form>
<form method="get" action="http://rpmfind.net/fux/rpm2html/search.php">
<input type="text" name="query" value="" size="30" />
<input type="image" value="RPMFind" src="/usr/local/share/galeon/rpm.png" />
</form>
<form method="get" action="http://packages.debian.org/cgi-bin/search_packages.pl">
<input type="text" name="keywords" value="" size="30" />
<input type="hidden" name="searchon" value="names" />
<input type="hidden" name="subword" value="1" />
<input type="hidden" name="version" value="all" />
<input type="hidden" name="release" value="all" />
<input type="image" value="Debian" src="/usr/local/share/galeon/debian.png" />
</form>
</blockquote>
</blockquote>
<div class="bottom_bar">
<center><b>Galeon</b> : <i>the web, only the web</i></center>
</div>
</body>
</html>
signature.asc
(application/pgp-signature, 189 B)
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1.2.1 (GNU/Linux) iD8DBQA+YLtiBKiYcWg4juYRAsgoAJwNoxvVpI8ZdvvLL2Fk8NpdmmFjTACeOo/B 1l0cjJSZvzg+sIbR2dDhvH8= =akJv -----END PGP SIGNATURE-----