The code: NOTE: $id is a local variable:
A piggy bank of commands, fixes, succinct reviews, some mini articles and technical opinions from a (mostly) Perl developer.
Jump to
XSL array/hash/lookup table
The code: NOTE: $id is a local variable:
URI encoding in Java
URIEncoder encodes to
application/x-www-form-urlencoded (i.e. spaces turn to +)import java.io.UnsupportedEncodingException;
import java.net.URISyntaxException;
import java.net.URLEncoder;
String uriTest2(String uri) {
String encodedUri = null;
String encoding = "UTF-8";
try {
encodedUri = URLEncoder.encode(uri, encoding);
} catch (UnsupportedEncodingException e) {
System.err.println("Unsuported encoding: "+encoding);
e.printStackTrace();
}
return encodedUri;
}
String encodedUri = null;
URI uri = null;
try {
uri = new URI("http","bbc.co.uk","/search/news/",path,null);
} catch (URISyntaxException e) {
System.err.println("Caught URI Syntax Exception");
e.printStackTrace();
}
encodedUri = uri.getRawQuery();
return encodedUri;
}
See also.
oXygen Eclipse plugin
- it's not all that, but step-through-debugging does work
- have to manually set the file association defaults to Oxygen types
- unreadable default colour scheme for Oxygen filetypes. It is difficult to import syntax-highlighting preferences in Eclipse. You're better off setting them yourself.
- to use step-through debugging, you need to:
- 'Configure Transformation Scenario' (under XML/XSL menu - it appears when you open an XML or XSL file)
- open the 'Debug Scenario' perspective in the XML/XSL menu
- setting the input parameters for debugging is fiddly
- the XML file being used as input must be "part of the project"
Nginx high-performance webserver
Seems to be used by quite a lot of sites and a few people have noticed nginx 404 error pages by facebook and youtube indicating they may also be using it? http://wiki.nginx.org/NginxWhyUseIt
Comes also with a memcached module to talk with memcached directly: http://www.igvita.com/2008/02/11/nginx-and-memcached-a-400-boost/
And has embedded perl in it as standard: http://wiki.nginx.org/NginxEmbeddedPerlModule
And call perl directly from SSI
<!- # perl sub="module::function" arg="parameter1" arg="parameter2"... >
For XSLT fans: http://wiki.nginx.org/NginxHttpXsltModule
For-each over static values in XSL
<xsl:for-each select="$some_value in ('a','b','c','d')"><!-- invalid? -->
You have to do this:
<xsl:variable name="items">
<item>a</item>
<item>b</item>
<item>c</item>
<item>d</item>
</xsl:variable>
<xsl:for-each select="$items/item">
<xsl:choose>
<xsl:when test="$some_value = .">
Eclipse plugins
- Target Management (Remote file browsing, via SSH): http://www.eclipse.org/dsdp/tm/
- works great (but sshfs is simpler)
- Instead of that, see also http://wills-tech-notes.blogspot.com/2010/07/remote-file-browsing.html
- XSLT: http://www.eclipse.org/webtools/
- can't download through update manager, it's too slow
- supposed to offer XML/XSL features, but I can't see any
- Oxygen XML/XSLT: http://www.oxygenxml.com/download_oxygenxml_editor.html#Eclipse
- Works. To use step-through debugging,you need to open the 'Debug Scenario' in the XML or XSL menu (it appears when you open an XML or XSL file)
- vim -- why not use vim editor inside Eclipse? No good solution, apparently (none of these were tested):
- http://www.viplugin.com/viplugin/ (2009 - costs a few pounds)
- http://eclim.org/vim/ (recent)
- http://vrapper.sourceforge.net/ (recent)
- http://sourceforge.net/projects/vimplugin/ (2007, but states it supports syntax files)
- Full Screen: http://code.google.com/p/eclipse-fullscreen/ (just works)
- P4WSAD: Perforce plugin: http://www.perforce.com/perforce/products/p4wsad.html (had to download zip file from FTP site and install manually, as automatic install URL was too slow)
- Plugin can be slow to use if you browse the repository directly, but is faster if you check out, then do right-click | Import as project, and use the standard Eclipse Navigator or Project tab to work with the files.
How to use Saxon XSL 2 processor
XSL tips
- In XSL templates, when generating new static elements with attributes, instead of <xsl:element name="foo"><xsl:attribute name="bar"><xsl:value-of select="'baz'"> etc, you can just do <foo bar="baz">! The main use for <xsl:element> and <xsl:attribute> is for dynamically named elements and attributes.
- Print debug statements like this: <xsl:message><xsl:text>min_score = </xsl:text><xsl:value-of select="$min_score"/></xsl:message>
Stop XML::LibXSLT and XML::LibXML connecting to w3.org
<!DOCTYPE xml PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
Then your parser may connect to w3.org for validation. If w3 blocks you for hammering their server, then you may get this error message: http error : Operation in progress
http error : Operation in progress
If you don't want/need validation against the DTD (and you probably don't), you can turn off that feature in XML::LibXML:1.70
$parser = XML::LibXML->new(load_ext_dtd => 0);
< 1.70
$parser = XML::LibXML->new();
$parser->load_ext_dtd(0);
Min/Max for XSLT
<!-- Create a variable named $minEventDate containing the MIN date -->
<xsl:variable name="minEventDate">
<xsl:for-each select="event">
<xsl:sort select="@date" data-type="text" order="ascending" />
<xsl:if test="position() = 1">
<xsl:value-of select="@date" />
</xsl:if>
</xsl:for-each>
</xsl:variable>
Obtaining the MAX:
<!-- Create a variable named $maxEventDate containing the MAX date -->
<xsl:variable name="maxEventDate">
<xsl:for-each select="event">
<xsl:sort select="@date" data-type="text" order="descending" />
<xsl:if test="position() = 1">
<xsl:value-of select="@date" />
</xsl:if>
</xsl:for-each>
</xsl:variable>
XSLT1 processing, using Perl
$ perl -MXML::LibXML -le'print $XML::LibXML::VERSION'
1.69
$ perl -MXML::LibXSLT -le'print $XML::LibXSLT::VERSION'
1.59
Code:
#!/usr/bin/perl
use strict;
use warnings;
use XML::LibXSLT;
use XML::LibXML;
my $xslt = XML::LibXSLT->new();
#my $source = XML::LibXML->load_xml(location => 'file.xml');
my $parser = XML::LibXML-> new();
my $source = $parser->parse_file('file.xml');
#my $style_doc = XML::LibXML->load_xml(location=>'file.xsl', no_cdata=>1);
my $parser2 = XML::LibXML-> new();
my $style_doc = $parser2->parse_file('file.xsl');
my $stylesheet = $xslt->parse_stylesheet($style_doc);
my $results = $stylesheet->transform($source);
#print $stylesheet->output_as_bytes($results);
print $results->toString;
XSL data types
<xsl:stylesheet
xmlns:sch="http://www.w3.org/2001/XMLSchema"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0"
exclude-result-prefixes=" sch">
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
<xsl:variable name="a" as="sch:integer" select="12"/>
<xsl:variable name="b" as="sch:float" select="12.123456789123456789"/>
<xsl:variable name="c" as="sch:double" select="12.123456789123456789"/>
<xsl:variable name="d" as="sch:decimal" select="12.123456789123456789"/>
</xsl:stylesheet>
Debugging XSLT
<!-- DEBUG -->
<xsl:if test="$debug">
<xsl:message><xsl:text>--------</xsl:text></xsl:message>
<xsl:message><xsl:text>FUNCTION display-pagination-links:</xsl:text></xsl:message>
<xsl:message><xsl:text>--------</xsl:text></xsl:message>
<xsl:message><xsl:text>direction: </xsl:text><xsl:value-of select="$direction"/></xsl:message>
<xsl:message><xsl:text>link_type: </xsl:text><xsl:value-of select="$link_type"/></xsl:message>
</xsl:if>
XSLT math
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output method="xml" omit-xml-declaration="yes"/>
<xsl:template match="numbers">
A. 4 + 3.2 = <xsl:value-of select="x + y"/>
B. 3.2 - 4 = <xsl:value-of select="y - x"/>
C. 4 * 3.2 = <xsl:value-of select="x * y"/>
D. 11/3.2 = <xsl:value-of select="z div y"/>
E. 4 + 3.2 * 11 = <xsl:value-of select="x+y*z"/>
F. (4 + 3.2) * 11 = <xsl:value-of select="(x+y)*z"/>
G. 11 mod 4 = <xsl:value-of select="z mod x"/>
H. 4 + 3.2 + 11 = <xsl:value-of select="sum(*)"/>
I. floor(3.2) = <xsl:value-of select="floor(y)"/>
J. ceiling(3.2) = <xsl:value-of select="ceiling(y)"/>
K. round(3.2) = <xsl:value-of select="round(y)"/>
L. 11 + count(*) = <xsl:value-of select="11+count(*)"/>
M. 3.2 + string-length("3.2") =
<xsl:value-of select="y + string-length(y)"/>
N. 11 + "hello" = <xsl:value-of select="z + 'hello'"/>
</xsl:template>
</xsl:stylesheet>
Warning With some XSLT processors, the use of decimal numbers may introduce a tiny error. For example, the "3.2 - 4" in this example comes out as "-.7999999999999998" on some processors. While being off by .0000000000000002 isn't much, being off at all shows that math is not XSLT's strong point.
Display output of XSL transformation using PHP
<?
$query = $_GET['q'];
$filePath = 'http://source-server:8889/page/'.$query;
$xslDoc = new DOMDocument();
$xslDoc->load("http://localhost/xslt/page_render.xsl");
$xmlDoc = new DOMDocument();
$xmlDoc->load( $filePath );
$proc = new XSLTProcessor();
$proc->importStylesheet($xslDoc);
echo $proc->transformToXML($xmlDoc);
?>
No XSLT2 in PHP
There is only one known xslt2 processor called SAXON (http://saxon.sourceforge.net/), built by Michael Kay, which was released for the Java and .NET platforms.
Other XSLT processors, including Sablotron, Xalan and MSXML, have not yet adopted xslt2.
Kay writes: "implementation [for xslt2 in php] does not exist because no-one has written one". He continues, "The usual workaround I recommend is to implement XSLT 2.0 transformation as a (Java-based or .NET-based) REST web service, and for the php application to submit transformation requests to that web service by means of HTTP requests. An alternative is to use a php-Java bridge"
Michael Kay manages an email-based discussion group called MulberryTech, a good resource for learning XSLT techniques (both 1 and 2). (http://www.mulberrytech.com/xsl/xsl-list/)
(If, Then, Else) LOGIC in XSL
<xsl:if test="XXX">
<!-- do something -->
</xsl:if>
<xsl:choose>
<xsl:when test="XXX">
<!-- do one thing -->
</xsl:when>
<xsl:when test="YYY">
<!-- do another thing -->
</xsl:when>
<xsl:otherwise>
<!-- do default thing -->
</xsl:otherwise>
</xsl:choose>
Logic examples:
<xsl:when test="matches(sql:feedurl_id, '^(\d+)$')">
<xsl:if test="$canonical-urls/agg:canonical-url[text()=$canonical-link-href][1]/@module = $module-type">
<xsl:when test="$module-type = 'knowledge'">
<xsl:when test="$module-type='iplayer' or $module-type='schedule'">
<xsl:if test="$debug">
<xsl:when test="document('')//this:modules/this:module[@type=$module-type]/this:merge-feeds">
<xsl:if test="position()=1">
<xsl:if test="position()=3 and count(agg:module)=0">
<xsl:when test="starts-with($name,'profile') or starts-with($name,'weather')">
<xsl:when test="starts-with(@type,'profile')">
<xsl:when test="@type='weather'">
<xsl:when test="count($modules/agg:modules/agg:module[starts-with(@type,'profile')])>0">
Cocoon XSLT errors
This could mean you've used the wrong attribute name in a tag, e.g.
<xsl:attribute type="type">
instead of
<xsl:attribute name="type">
There seems to be no syntax checking to warn in cases like this.
XML::Validator::Schema
use XML::SAX::ParserFactory;
use XML::Validator::Schema;
# create a new validator object, using foo.xsd
$validator = XML::Validator::Schema->new(file => 'foo.xsd');
# create a SAX parser and assign the validator as a Handler
$parser = XML::SAX::ParserFactory->parser(Handler => $validator);
# validate foo.xml against foo.xsd
eval { $parser->parse_uri('foo.xml') };
die "File failed validation: $@" if $@;
The problem is:
- XML::Validator::Schema ignores missing tags
- and attribute fixing doesn't work, at all
Nested comments
They may already be inside a comment.