Reputation: 11971
I have an .xml
file which has an accompanying .xsl
file. The output of which can be found here.
I am attempting to have a html webpage where the user will be able to type into a search box, for example 'Year < 2009'
. And it will show the table found above but only where the Year is less than 2009.
I don't really have much idea where to start, or what I need to look into to create this functionality.
For reference, here's an XML snippet:
<?xml-stylesheet type="text/xsl" href="podcatalog.xsl"?>
<pods-papers>
<inproceedings key="AbbadiSC85">
<crossref>conf/pods/85</crossref>
<author>Amr El Abbadi</author>,
<author>Dale Skeen</author>,
<author>Flaviu Cristian</author>,
<title>An Efficient, Fault-Tolerant Protocol for Replicated Data Management.</title>,
<pages>215-229</pages>,
<year>1985</year>,
<booktitle>PODS</booktitle>,
</inproceedings>
<inproceedings key="AbbadiT86">
<crossref>conf/pods/86</crossref>
<author>Amr El Abbadi</author>,
<author>Sam Toueg</author>,
<title>Availability in Partitioned Replicated Databases.</title>,
<pages>240-251</pages>,
<year>1986</year>,
<booktitle>PODS</booktitle>,
</inproceedings>
<inproceedings key="Abdel-GhaffarA90">
<crossref>conf/pods/90</crossref>
<author>Khaled A. S. Abdel-Ghaffar</author>,
<author>Amr El Abbadi</author>,
<title>On the Optimality of Disk Allocation for Cartesian Product Files.</title>,
<pages>258-264</pages>,
<year>1990</year>,
<booktitle>PODS</booktitle>,
</inproceedings>
<inproceedings key="Abiteboul83">
<crossref>conf/pods/83</crossref>
<author>Serge Abiteboul</author>,
<title>Disaggregations in Databases.</title>,
<pages>384-388</pages>,
<year>1983</year>,
<booktitle>PODS</booktitle>,
</inproceedings>
</pods-papers>
and here's the XSLT ("podcatalog.xsl"
):
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<h2>Pods Papers</h2>
<table border="1">
<tr bgcolor="#9ACD32">
<th>Author</th>
<th>Title</th>
<th>Pages</th>
<th>Year</th>
</tr>
<xsl:for-each select="pods-papers/inproceedings">
<xsl:sort select="author"/>
<tr>
<td><xsl:value-of select="author"/></td>
<td><xsl:value-of select="title"/></td>
<td><xsl:value-of select="pages"/></td>
<td><xsl:value-of select="year"/></td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
Please note: I am not necessarily looking for the code, or what to write, but, for example, a web page that shows me how to implement all or parts of this
Upvotes: 1
Views: 619
Reputation: 338128
You could do this:
Add two script elements to your XSLT that will show up in the resulting HTML. The first will be jQuery (the Google-hosted version, for convenience):
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
and the second manipulates your result table:
<script type="text/javascript"><![CDATA[
$(function () {
var filters = {};
filters.run = function () {
var i, $th = $("th"), $td, value;
$("table tr:not(:visible)").show(); // clear any previously hidden rows
for (var i=0; i<$th.length; i++) { // for each filter string...
if (this[i] > "") {
$td = $th.eq(i).closest("table").find("tr:visible td:nth-child(" + (i+1) + ")");
switch (this[i].slice(0,1)) { // first character is the operator
case "<":
value = $.trim( this[i].slice(1).toLowerCase() );
$td.filter(function () {
return $.trim( $(this).text().toLowerCase() ) >= value;
}).closest("tr:visible").hide();
break;
case ">":
value = $.trim( this[i].slice(1).toLowerCase() );
$td.filter(function () {
return $.trim( $(this).text().toLowerCase() ) <= value;
}).closest("tr:visible").hide();
break;
case "/":
value = new RegExp( this[i].slice(1) );
$td.filter(function () {
return !value.test( $.trim( $(this).text() ) );
}).closest("tr:visible").hide();
break;
case "=":
value = $.trim( this[i].slice(1).toLowerCase() );
$td.filter(function () {
return $.trim( $(this).text().toLowerCase() ) != value;
}).closest("tr:visible").hide();
break;
default:
value = $.trim( this[i].toLowerCase() );
$td.filter(function () {
return $.trim( $(this).text().toLowerCase() ).indexOf(value) == -1;
}).closest("tr:visible").hide();
break;
}
}
}
}
$("th").each(function () {
$(this).append("<input type='text'>");
});
$("th input").change(function () {
var index = $(this).closest("th").prevAll("th").length;
filters[index] = $.trim( $(this).val() );
filters.run();
});
});
]]></script>
Here's what this does:
<input>
element to each <th>
. This input serves as a filter box for that column.filters
, one for each column index.<td>
elements in the affected column and compares them to the filter value. <tr>
is hidden.This process results in additive filters, i.e. you can narrow down your search, filtering each column individually.
The first character of the filter string is supposed to be the operator.
Supported operators are
<
(less than), >
(greater than)=
(exact equality) /
(regular expression).All comparisons except regular expression are case-insensitive.
See it in action on jsFiddle: http://jsfiddle.net/Tomalak/wjDrr/1/embedded/result/
P.S.:
I know this basically solves your entire problem. You said you have no idea where to start, so I suppose you'll have a hard-enough time figuring out the code and further adapting it to your needs. :)
The above code lacks some elegance, it breaks as soon as there is more then one table on the page and it certainly can be optimized for speed. If you care, you can improve these things.
Upvotes: 1