Render the search result using (opensearch/atom) xml format.

This commit is contained in:
Matthieu Gautier 2022-05-04 18:39:54 +02:00
parent c4f706863c
commit e5df5e936f
5 changed files with 66 additions and 3 deletions

View File

@ -102,11 +102,19 @@ class SearchRenderer
this->pageLength = pageLength;
}
std::string renderTemplate(const std::string& tmpl_str);
/**
* Generate the html page with the resutls of the search.
*/
std::string getHtml();
/**
* Generate the xml page with the resutls of the search.
*/
std::string getXml();
protected:
std::string beautifyInteger(const unsigned int number);
zim::SearchResultSet m_srs;

View File

@ -162,7 +162,7 @@ kainjow::mustache::data buildPagination(
return pagination;
}
std::string SearchRenderer::getHtml()
std::string SearchRenderer::renderTemplate(const std::string& tmpl_str)
{
// Build the results list
kainjow::mustache::data items{kainjow::mustache::data::type::list};
@ -201,14 +201,15 @@ std::string SearchRenderer::getHtml()
searchBookQuery
);
std::string template_str = RESOURCE::templates::search_result_html;
kainjow::mustache::mustache tmpl(template_str);
kainjow::mustache::data allData;
allData.set("protocolPrefix", protocolPrefix);
allData.set("results", results);
allData.set("pagination", pagination);
allData.set("query", query);
kainjow::mustache::mustache tmpl(tmpl_str);
std::stringstream ss;
tmpl.render(allData, [&ss](const std::string& str) { ss << str; });
if (!tmpl.is_valid()) {
@ -217,4 +218,15 @@ std::string SearchRenderer::getHtml()
return ss.str();
}
std::string SearchRenderer::getHtml()
{
return renderTemplate(RESOURCE::templates::search_result_html);
}
std::string SearchRenderer::getXml()
{
return renderTemplate(RESOURCE::templates::search_result_xml);
}
}

View File

@ -769,6 +769,11 @@ std::unique_ptr<Response> InternalServer::handle_search(const RequestContext& re
renderer.setProtocolPrefix(m_root + "/");
renderer.setSearchProtocolPrefix(m_root + "/search");
renderer.setPageLength(pageLength);
if (request.get_optional_param<std::string>("format", "") == "xml") {
return ContentResponse::build(*this, renderer.getXml(), "application/rss+xml; charset=utf-8",
/*isHomePage =*/false,
/*raw =*/true);
}
auto response = ContentResponse::build(*this, renderer.getHtml(), "text/html; charset=utf-8");
if(bookIds.size() == 1) {
auto bookId = *bookIds.begin();

View File

@ -34,6 +34,7 @@ skin/fonts/Roboto.ttf
skin/block_external.js
skin/search_results.css
templates/search_result.html
templates/search_result.xml
templates/error.html
templates/index.html
templates/suggestion.json

View File

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
xmlns:opensearch="http://a9.com/-/spec/opensearch/1.1/"
xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>Search: {{query.pattern}}</title>
<link>{{query.unpaginatedQuery}}&amp;format=xml&amp;start={{results.start}}&amp;pageLength={{pagination.itemsPerPage}}</link>
<description>Search result for {{query.pattern}}</description>
<opensearch:totalResults>{{results.count}}</opensearch:totalResults>
<opensearch:startIndex>{{results.start}}</opensearch:startIndex>
<opensearch:itemsPerPage>{{pagination.itemsPerPage}}</opensearch:itemsPerPage>
<atom:link rel="search" type="application/opensearchdescription+xml" href="{{protocolPrefix}}search/searchdescription.xml"/>
<opensearch:Query role="request"
searchTerms="{{query.pattern}}"{{#query.lang}}
language="{{query.lang}}"{{/query.lang}}
startIndex="{{results.start}}"
count="{{pagination.itemsPerPage}}"
/>
{{#results.items}}
<item>
<title>{{title}}</title>
<link>{{absolutePath}}</link>
{{#snippet}}
<description>{{>snippet}}...</description>
{{/snippet}}
{{#bookTitle}}
<book>
<title>{{bookTitle}}</title>
</book>
{{/bookTitle}}
{{#wordCount}}
<wordCount>{{wordCount}}</wordCount>
{{/wordCount}}
</item>
{{/results.items}}
</channel>
</rss>