PDA

View Full Version : Using Search on an XML page with XSLT


tcadieux
04-30-2007, 05:21 PM
I have an XML page used in conjunction with an XSLT. I've never used this before, but I've been making good headway until this morning.

The XML sheet will be the entire listing of, for this example, a jobs page. Now, I have been unable to find examples that would allow me to add a Search textbox at the top of the page, which would then allow users to search through different fields, ie. the posting dates, job titles, locations.

Any pointer would be appreciated. Thank you

david_kw
05-01-2007, 12:25 AM
Just so I understand, you want a user to browser to an XML file that is then converted by an XSL file and displayed to the browser. Then, you want a search input box at the top of the page that lets you search the XML file data?

david_kw

tcadieux
05-01-2007, 01:54 PM
Essentially, the same as having an SQL call to the db, displaying all records with a search feature at the top.
When the user does a search, the XML would be queried the way an SQL would be queried using a queryString, then displaying only those records?

david_kw
05-01-2007, 05:43 PM
I'm still not sure I understand completely how you are trying to set this up. What I might do, from what I understand of your design, is to use XSL to create the XHTML file which has embedded in it the data you want to search on. Then I'd probably put the actual search routine in javascript which could then just set the display:block for any data that matches the search criteria.

So the xml file plus the xsl would create something like


<div id="data1" class="job" style="display:none">
<span class="job_name">Job 1</span>
<span class="job_desc">Description 1</span>
</div>
<div id="data2" class="job" style="display:none">
<span...


So the XSL just sets up the data in the format you want and hides it all. JavaScript is then used to search and display it.


function doSearch(query) {
var data = document.getElementsByTagName("div");
for (var i = 0; i < data.length; i++) {
if (data[i].className == "job" && matchesSearch(query, data[i])) {
data[i].style.display = "block";
}
}
}


Something like that is one way to do it.

david_kw

tcadieux
05-01-2007, 07:47 PM
Ok, let me start from the beginning. Another group is posting an XML file with all the job listing for our company. I already have the XSLT creating the HTML page.

The only issue is that this page will have say, 25 job listings. If I want to allow my user to trim down that list by say, picking only jobs on the East Coast, how would you folkz normally handle something like that?

thanx in advance.

david_kw
05-01-2007, 09:03 PM
I afraid I'm still not sure how the flow of pages is structured. It sounds now like you have one page with a "Find Jobs" button on it (in HTML or whatever). When that button loads an XML file which is then run transformed to a XHTML document with XSL. And you are wondering how to effect the transformation with the search query?

If that's right, I don't know how to do it in XSL alone. I don't know of any way for XSL to get information about what was typed in to the browser.

So the way I would do it is what I said before. I'd use XSL to build the table in some way where JavaScript could be used to do the searching. In JavaScript, I can get the search information from a previous page (or use a cookie or whatever).

Do you have a copy of an example XML file you are using? I think I might have time to put some sample code together of what I'm thinking if you believe that would be useful.

david_kw

david_kw
05-01-2007, 10:01 PM
So here is a really basic version of what I was thinking. Hopefully it will be of some use.

http://www.exfer.net/test/searchxml.xml

As you can see in the code, javascript is doing all the searching work with DHTML used to display it without hitting the server again. If you wanted to check a search query from the previous post you'd have to look at the window.location.search and parse that for the query. This way works nice as long as there aren't tons of results. But XSL wouldn't be any better since it also only runs on the client. If you want to limit the searches actually sent to the client you'd have to do that in the backend.

searchxml.xml

<?xml version="1.0" encoding="ISO-8859-1"?>
<?xml-stylesheet href="searchxml.xsl" type="text/xsl" ?>
<jobs>
<job>
<name>Shoe Sales</name>
<desc>Selling shoes</desc>
<coast>East</coast>
</job>
<job>
<name>Food Taster</name>
<desc>Taste food</desc>
<coast>East</coast>
</job>
<job>
<name>Computer Programmer</name>
<desc>Program computers</desc>
<coast>West</coast>
</job>
<job>
<name>Teacher</name>
<desc>Teach students</desc>
<coast>East</coast>
</job>
<job>
<name>Kite Flyer</name>
<desc>Fly kites</desc>
<coast>West</coast>
</job>
</jobs>


searchxml.xsl

<?xml version="1.0" encoding="UTF-8" ?>

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" omit-xml-declaration="yes" indent="yes" />
<xsl:template match="/">
<xsl:apply-templates />
</xsl:template>

<xsl:template match="jobs">
<html>
<head>
<title>Search Jobs</title>
<script type="text/javascript">
//<![CDATA[

function doSearch() {
var rb = document.getElementsByName("whichCoast");
var v;

for (var i = 0; i < rb.length; i++) {
if (rb[i].checked) {
v = rb[i].value;
break;
}
}

var jobs = document.getElementsByTagName("li");
for (var j = 0; j < jobs.length; j++) {
if (jobs[j].className == "job") {
var li = jobs[j].getElementsByTagName("li");
for (var k = 0; k < li.length; k++) {
if (li[k].className == "coast") {
if (v == "Either" || li[k].firstChild.nodeValue.match(v)) {
jobs[j].style.display = "";
} else {
jobs[j].style.display = "none";
}
}
}
}
}
}

//]]>
</script>
</head>
<body>
<form action="#" onsubmit="return(false);">
<label>East <input type="radio" name="whichCoast" value="East" onclick="doSearch();"/></label>
<label>West <input type="radio" name="whichCoast" value="West" onclick="doSearch();"/></label>
<label>Either <input type="radio" name="whichCoast" value="Either" onclick="doSearch();" checked="checked"/></label>
</form>
<ul>
<xsl:for-each select="job">
<li class="job">
<ul>
<li class="name"><xsl:value-of select="name"/></li>
<li class="desc"><xsl:value-of select="desc"/></li>
<li class="coast"><xsl:value-of select="coast"/></li>
</ul>
</li>
</xsl:for-each>
</ul>
</body>
</html>
</xsl:template>
</xsl:stylesheet>

tcadieux
05-02-2007, 03:02 PM
Thank you both, I believe that this should get me started!