Wednesday, 27 May 2009

Saxon XSLT 2.0 format-number problem (update!)


Later: following the post below, I managed to ask on the saxon-help list about this. The reply from Michael Kay (He Should Know!)
is that this is the expected behaviour. Looking in the W3C recommendation, it refers to the JDK 1.1 DecimalFormat class, which indeed states:
Symbol Meaning  
0      a digit  
#      a digit, zero shows as absent  
.      placeholder for decimal separator  
,      placeholder for grouping separator.  
;      separates formats.  
-      default negative prefix.  
%      multiply by 100 and show as percentage  
? multiply by 1000 and show as per mille  
¤ currency sign; replaced by currency symbol; if
         doubled, replaced by international currency symbol.
         If present in a pattern, the monetary decimal separator
         is used instead of the decimal separator.  
X      any other characters can be used in the prefix or suffix  
'      used to quote special characters in a prefix or suffix.  
...so , perverse as it seems, the behaviour is as advertised.

Original post:
One of the (many) advantages of using XSLT 2.0 is its supposed ability to understand scientific notation, e.g. 1E-2 is correctly interpreted as 0.01. However the only implementation I know of for XSLT 2.0 is Saxon, so the XSLT 2.0 standard basically defines this one application. Here's a nasty I discovered while trying to format exponential numbers using Saxon 9.1.0.6: Formatting zero with
format-number(xs:double($myNumber),'#.#######')
causes an empty string to be output.
Heres a sample xml:

<numbers>
<test> id="1">1.3</test>
<test> id="2">8E-4</test>
<test> id="3">8E-8</test>
<test> id="4">0.0</test>
<test> id="5">0</test>
</numbers>


and an xslt:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs"
version="2.0">
<xsl:output method="text"/>
<xsl:template match="numbers">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="test">
<xsl:value-of select="concat('Original: ',text())"/>
Format with #.#####
'
<xsl:value-of select="format-number(xs:double(.), '#.#####')"/>'
Format with #.#########
'
<xsl:value-of select="format-number(xs:double(.), '#.#########')"/>'
</xsl:template>
</xsl:stylesheet>


But the output is not what one would expect:

Original: 1.3
Format with #.#####
'1.3'
Format with #.#########
'1.3'

Original: 8E-4
Format with #.#####
'.0008'
Format with #.#########
'.0008'

Original: 8E-8
Format with #.#####
''
Format with #.#########
'.00000008'

Original: 0.0
Format with #.#####
''
Format with #.#########
''

Original: 0
Format with #.#####
''
Format with #.#########
''



Tuesday, 26 May 2009

CherryPy Caching: reprise

Finally I had to turn off caching, even with my fix in place. Users reported a malformed xml being returned for certain queries, and it turned out that anything longer than the maxobjectsize was being cached and returned truncated. I'm sure there's an easy way around this, but not sure I want to spend more time on it just now.

Friday, 15 May 2009

CherryPy Caching


I just tried turning on CherryPy web caching, this is one of the few things which receives only very cursory treatment in Sylvain Hellegouarch's  excellent book, 'CherryPy Essentials'. I managed by incorporating the 
conf = {'/':{'tools.caching.on':True}}
line in my code, however I was dismayed to discover that once on, I couldn't form a request would not get the cached result. Neither 'Cache-Control:max-age=0' nor 'Pragma: no-cache' would do it. Looking into the code (I'm using v. 3.1.1), I found the caching.py tool and indeed saw it pays pretty much no attention to the http request headers except (bizarrely, I think) the 'Vary' header. I've inserted a few lines into caching.py to fix this and submitted a trac bug, so we'll see whether this changes. The code lines are reproduced here:
#some people still use Pragma : no-cache to demand a fresh resource
        pragma_no_cache=False
        pragma_header=request.headers.get('Pragma')
        if pragma_header:
            pragma_values=[header.strip() for header in pragma_header.split(',')]
            for this_value in pragma_values:
                if 'no-cache' in this_value:
                    pragma_no_cache=True
                    break
        #added by shaun, look at cache-control
        max_acceptable_age=MemoryCache.delay
        age_seconds=int(response.time - create_time)
        cache_control_header=request.headers.get('Cache-Control')
        if cache_control_header:
            #split string on commas to get the multiple words
            cache_control_values=[header.strip() for header in cache_control_header.split(',')]
            #look for max-age
            for this_value in cache_control_values:
                if ('max-age' in this_value) and ('=' in this_value):
                    age_pair=[age.strip() for age in this_value.split('=')]
                    if age_pair[1].isdigit():
                      max_acceptable_age=int(age_pair[1])
                    break
                  
        #return if the cache is older than the acceptable age
        if (age_seconds > max_acceptable_age) or pragma_no_cache:
            request.cached = False
            request.cacheable = True
            return False
            
        # Add the required Age header
        response.headers["Age"] = str(age_seconds)

Wednesday, 4 June 2008

Reviews and DB

I've been reviewing the InDetGlobalMonitoring code for Heidi, and trying to get more info into my 'run summary' page for the FDR. This second has not been easy, I need to understand the Tier0 database a lot better!

On the bright side, I had my SEDUX paper accepted for the SVG conference in Nuremberg in August.

Thursday, 22 May 2008

Serving jnlp from PHP for WebStart applications

So... I had to incorporate the TriggerTool information in the runlist summary, but it is served as a jnlp with arguments in the jnlp format. My first attempts at generating the jnlp dynamically would work either in Safari or in Firefox, but not both until I renamed the web application to 'test.php.jnlp'.. this worked but is ugly. Finally I hit on the solution: not only making the http header into 'Content-Type: application/x-java-jnlp-file' but also adding '; name=smtp.jnlp' onto the end of that. Now the file comes back as a .jnlp which is recognised by both browsers.
This last week, meanwhile has been a hectic rush as I was initially blamed for submitting broken tags into Athena. It turned out it was a subtle bug in the pixel software which went something like this:
Gaudi has a templated stream insertion operator for all types.
A PixelDcsData class also had a stream insertion operator.
A PixelDcsData class also had a single argument constructor, that argument being 'Identifier'.
Now, when trying to output 'Identifier' with stream insertion, the compiler complained of an ambiguously overloaded '<<' because it couldn't decide whether to convert Identifier to a PixelDcsData class and then use the custom '<<' or use the intrinsic templated '<<'. Constructors with a single argument act as conversion operators. To avoid this, qualify the constructor with 'explicit'.

Wednesday, 7 May 2008

Tier0 and other animals

Managed to get the data filenames from Tier0; wrote a PHP service which returns plain text, html or xml according to the 'Accept' header sent in the request. Wrote documentation and an example application, then incorporated this into my 'run details' service.
Created an /SCT/Derived/Monitoring folder in Cool for Kazu. 
Over the last week: created a Plone site at home and made this visible via dyndns as a  demo of what it can do, following from a presentation on collaborative tools last week. It seems that CERN is opting for Sharepoint as a CMS; a very bad decision, given that all our data and programs are running under linux...

Wednesday, 23 April 2008

Absence

Long time since I updated this... I missed some Wednesdays due to meetings, then was in Ringberg ... now ill !
I managed to get the SCT Configurations to read dead strips and inserted this in SiClusterizationTool for release 14.1.0 before I went to Ringberg; however that release still has not been built due to various problems. Carl Gwilliam has been testing it and patching it since then.
I volunteered to help the Muons insert their cabling into Cool, although I have to wonder about the methodology they are using: of 1.3 million table entries, 70% of them are empty.
Today I'll fix the detector mask interpretation in runlist and see where I get to ...