Pages

Showing posts with label xslt. Show all posts
Showing posts with label xslt. Show all posts

Thursday, 25 July 2013

Solr XSLT alternative with live links

The XSLT files that Solr has standard are pretty good and cover a wide variety of different transforms however they didnt give me exactly what I wanted.  I use Nutch as a filesystem crawler and therefore wanted the XSLT transform to make all the ur'ls(uri's) to the crawled files to be hyperlinks, so that when I clicked on them it would either download that file or allow me to view it in my browser.  I therefore decided that I would make my own XSLT file even though I had no previous experience using XSLT before so I have adapted the example.xsl file that comes standard with Solr and this is the final version:

<?xml version='1.0' encoding='UTF-8'?>
 
<xsl:stylesheet version='1.0'
    xmlns:xsl='http://www.w3.org/1999/XSL/Transform'
>
 
  <xsl:output media-type="text/html" encoding="UTF-8"/> 
 
  <xsl:variable name="title" select="concat('Solr search results (',response/result/@numFound,' documents)')"/>
 
  <xsl:template match='/'>
    <html>
      <head>
        <title><xsl:value-of select="$title"/></title>
        <xsl:call-template name="css"/>
      </head>
      <body>
        <h1><xsl:value-of select="$title"/></h1>
        <div class="note">
          ******* Author: Allan Macmillan ******** Blog:amac4.blogspot.com ********* allan2.xls
        </div>
        <xsl:apply-templates select="response/result/doc"/>
      </body>
    </html>
  </xsl:template>
 
  <xsl:template match="doc">
    <xsl:variable name="pos" select="position()"/>
    <div class="doc">
      <table width="100%">
        <xsl:apply-templates>
          <xsl:with-param name="pos"><xsl:value-of select="$pos"/></xsl:with-param>
        </xsl:apply-templates>
      </table>
    </div>
  </xsl:template>
 
  <xsl:template match="doc/*[@name='score']" priority="100">
    <xsl:param name="pos"></xsl:param>
    <tr>
      <td class="name">
        <xsl:value-of select="@name"/>
      </td>
      <td class="value">
        <xsl:value-of select="."/>
 
        <xsl:if test="boolean(//lst[@name='explain'])">
          <xsl:element name="a">
            <!-- can't allow whitespace here -->
            <xsl:attribute name="href">javascript:toggle("<xsl:value-of select="concat('exp-',$pos)" />");</xsl:attribute>?</xsl:element>
          <br/>
          <xsl:element name="div">
            <xsl:attribute name="class">exp</xsl:attribute>
            <xsl:attribute name="id">
              <xsl:value-of select="concat('exp-',$pos)" />
            </xsl:attribute>
            <xsl:value-of select="//lst[@name='explain']/str[position()=$pos]"/>
          </xsl:element>
        </xsl:if>
      </td>
    </tr>
  </xsl:template>
 
  <xsl:template match="doc/arr" priority="100">
    <tr>
      <td class="name">
        <xsl:value-of select="@name"/>
      </td>
      <td class="value">
        <ul>
        <xsl:for-each select="*">
          <li><xsl:value-of select="."/></li>
        </xsl:for-each>
        </ul>
      </td>
    </tr>
  </xsl:template>
 
 
  <xsl:template match="doc/*">
    <tr>
      <td class="name">
        <xsl:value-of select="@name"/>
      </td>
      <td class="value">
      <xsl:variable name="var" select="."/>
      <xsl:choose>
         <xsl:when test="starts-with($var,'file:////')">
      <a>
            <xsl:attribute name="href">
               <xsl:value-of select="$var"/>
            </xsl:attribute>
     <xsl:value-of select="$var"/></a>
         </xsl:when>
  <xsl:otherwise>
             <xsl:value-of select="$var"/>
         </xsl:otherwise>
      </xsl:choose>
      </td>
    </tr>
  </xsl:template>
 
  <xsl:template match="*"/>
 
  <xsl:template name="css">
    <script>
      function toggle(id) {
        var obj = document.getElementById(id);
        obj.style.display = (obj.style.display != 'block') ? 'block' : 'none';
      }
    </script>
    <style type="text/css">
      body { font-family: "Lucida Grande", sans-serif }
      td.name { font-style: italic; font-size:80%; }
      td { vertical-align: top; }
      ul { margin: 0px; margin-left: 1em; padding: 0px; }
      .note { font-size:80%; }
      .doc { margin-top: 1em; border-top: solid grey 1px; }
      .exp { display: none; font-family: monospace; white-space: pre; }
    </style>
  </xsl:template>
 
</xsl:stylesheet>


XSLT Error For Solr - HTTP Status 500 - {msg=getTransformer fails in getContentType...

It is common to apply an XSLT stylesheet to an xml file to give it a cleaner look and Solr is no different coming with 4 pre-written xslt files for you to choose from.  

The error message XSLT Error For Solr - HTTP Status 500 - {msg=getTransformer fails in getContentType... is a common one and in most cases is easily fixed.  There are a few reasons that the error message appears:

  1. You have not specified a stylesheet to use
           e.g http://localhost:8080/solr/select?q=*&wt=xslt
    Make sure you have specified a stylesheet and that the stylesheet you specified actually exists
           e.g http://localhost:8080/solr/select?q=*&wt=xslt&tr=example.xsl
  2. A common mistake is to think that a stylesheet has a .xslt file extension - THEY DONT! The file extension is .xsl so be sure when you save your file and when you specify it in your query that you use .xsl
  3. There are errors in you XSL file - Be careful if you are working in an environment that does not do syntax checking (notepad) - It is easy to forget to close a tag or make a spelling mistake.

Stack Trace:
 {msg=getTransformer fails in getContentType,trace=java.lang.RuntimeException: getTransformer fails in getContentType at org.apache.solr.response.XSLTResponseWriter.getContentType(XSLTResponseWriter.java:74) at org.apache.solr.servlet.SolrDispatchFilter.writeResponse(SolrDispatchFilter.java:623) at org.apache.solr.servlet.SolrDispatchFilter.doFilter(SolrDispatchFilter.java:372) at org.apache.solr.servlet.SolrDispatchFilter.doFilter(SolrDispatchFilter.java:155) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99) at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408) at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1008) at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589) at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.run(AprEndpoint.java:1852) at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown Source) at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) at java.lang.Thread.run(Unknown Source) Caused by: java.io.IOException: 'tr' request parameter is required to use the XSLTResponseWriter at org.apache.solr.response.XSLTResponseWriter.getTransformer(XSLTResponseWriter.java:1