XT Frequently Asked QuestionsMaintained by : the team 4xt Most of these questions and answers are borrowed from the XSL Frequently Asked Questions "gleaned from the list kindly hosted by Mulberrytech" by Dave Pawson. Table of contentQ & AImplementations of XSLTLinda van den Brink Saxon by Michael Kay, the first full implementation of XSLT, December 1999. XT by James Clark, http://www.jclark.com/xml/xt.html LotusXSL by IBM Alphaworks, LotusXSL 1.0.0 is a complete and a robust reference implementation of the W3C Recommendations for XSL Transformations (XSLT) and the XML Path Language (XPath). XSLT has been implemented in many commercial applications specifically in credit card payment processing companies. Examples of commercial use include usage at the payment processor networks platforms such as: MSG Merchant Group, Patriot Bankcard and at High Risk Experts. http://www.alphaworks.ibm.com/tech/LotusXSL4XSLT (in Python) by Fourthought supports a sub-set of the latest working draft: http://opentechnology.org/4Suite/4XSLT/ and http://FourThought.com/4Suite/4XPath Oracle's XSLT Engine http://technet.oracle.com/tech/xml TransforMiiX is a C XSLT processor. You can get its source code from Mozilla at www.mozilla.org/owners.html For a more complete list, see http://www.xmlsoftware.com/xsl/ Up to table of content Where to start with XSLMike Brown (Somewhat abused: I have added others in since, but Mike gave me the starter. Thanks Mike.) See the References section for the W3C and other references TUTORIALS The XSL Chapter from Elliotte Rusty Harold's XML Bible is a very good free resource. It is located at http://metalab.unc.edu/ xml/books/bible/updates/14.html Crane Softwrights Ltd has a nice tutorial called Practical Transformation Using XSLT and XPath, which I found extremely helpful. Part of it is free, but the whole thing will cost you 40 dollars. It's well worth it, IMHO. You get free updates. Practical Transformation Using XSLT and XPath (XSL Transformations and the XML Path Language) Sixth Edition - 1999-11-19 - ISBN 1-894049-03-9 Copyright (c) 1999 Crane Softwrights Ltd. 310 Pages / Subscription price includes free updates New in the comprehensive Sixth Edition: (1) - all constructs of the W3C Recommendations for XSLT 1.0 and XPath 1.0 are documented (2) - illustrations have been updated with new content in response to comments and questions (3) - a ZIP file is provided with all of the XML and XSLT sample files used in the book (4) - the reference annexes in the free preview excerpt download have been updated to the REC and to the latest version of XT As with our other editions of this XSLT training material, the purchase of any edition of this publication entitles the customer to any future edition of the same material. Note that the work on this material *has not stopped* ... work will continue on a prose version of the book, formatted with XSL (while I begin writing the "Practical Formatting Using XSL" material). For more information see http://www.CraneSoftwrights.com Stuart Zakon writes: Our site has a very nice tutorial on using XSL to solve a real world problem: transforming XMI to HTML. XMI is the XML standard for storing UML models. http://www.objectsbydesign.com/projects/xmi_to_html.html XSL NEWS AND SOFTWARE The official specs for XSL, XSLT, and XPath make more sense after you have read the tutorials and experimented with up-to-date tools. Lars Garshol maintains an annotated list of XML related software, including XSL tools, at http://www.stud.ifi.uio.no/~larsga/linker/XMLtools.html Robin Cover's SGML/XML Web Page has an exhaustive list of all things related to XSL. The URL is http://www.oasis-open.org/cover/xsl.html The W3C maintains a little XSL news, info and software page at
http://www.w3.org/Style/XSL/Up to table of content String->LocationPathNikolai Grigoriev
I tried to run a stylesheet that inputs a parameter and
interprets the value of it as a location path.
I.e.
<xsl:param name="query">no-default</xsl:param>
...
<xsl:template name="querytemp">
<xsl:apply-templates select="$query"/>
</xsl:template>
This yields "cannot convert to node-set" when
running it with XT.
Try <xsl:apply-templates select="*[name()=$query]"/>.
Up to table of content How to include or exclude content for debugDavid Carlisle something like this? <xsl:param name="debug-flag" select="0"/> ... <xsl:if test="$debug-flag > 0"> <xsl:message>foo</xsl:message> <xt:document href="debug-trace.txt">....</xt:document> </xsl:if> ... xt file.xml style.xsl out.xml debug-flag=6 Up to table of content How to copy the DOCTYPE valueSteve Muench
if you preprocess a document with:
<!DOCTYPE xxx SYSTEM "yyy">
<xxx>
<foo/>
</xxx>
into:
<!DOCTYPE xxx SYSTEM "yyy">
<!-- DOCTYPE xxx SYSTEM "yyy" -->
<xxx>
<foo/>
</xxx>
This doesn't alter the validity of the document in any way,
but does add a "comment item" into the document's infoset
that XSLT/XPath can address.
Then you can use an XPath expression like:
file://comment()[contains(.,'DOCTYPE')][1]
to refer to the first comment containing DOCTYPE and then
use a combination of normalize-space(), substring-after, and
substring() to get out the uri for the DTD of the document.
Since you cannot set the doctype-system="" property of
<xsl:output> dynamically, you'd have to then resort to a
use of
<xsl:value-of disable-output-escaping="yes"/>
and concat() to literally print the <!DOCTYPE into the
result tree.
Given the post-processed source document above, the
following XSLT transform produces the output:
<!DOCTYPE xxx SYSTEM "yyy">
<xxx>
<foo/>
</xxx>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:template match="/">
<!--
| Output the Doctype in the result based on
| the DOCTYPE comment we preprocessed into the document
+-->
<!-- For convenience, get a literal quote sign in a variable -->
<xsl:variable name="q">"</xsl:variable>
<!-- Get the DOCTYPE comment in a variable -->
<xsl:variable name="d"
select="//comment()[contains(.,'DOCTYPE')][1]"/>
<!-- Get the "uri" part of the doctype comment -->
<xsl:variable name="e"
select="substring-after(normalize-space($d),'SYSTEM ')"/>
<!-- Strip off the quotes from the "uri" -->
<xsl:variable name="f"
select="substring-before(substring-after($e,$q),$q)"/>
<!-- Output the <!DOCTYPE -->
<xsl:value-of disable-output-escaping="yes"
select="concat('<!DOCTYPE ',name(/*[1]),
' SYSTEM',$q,$f,$q,'>
')"/>
<xsl:apply-templates
select="@*|*|processing-instruction()|comment()"/>
</xsl:template>
<!--
| Identity Transformation. XT doesn't seem to support the
| more terse "@*|node()" at present, so this is the long form.
+-->
<xsl:template match="@*|*|processing-instruction()|comment()">
<xsl:copy>
<xsl:apply-templates
select="@*|*|processing-instruction()|comment()"/>
</xsl:copy>
</xsl:template>
<!-- Suppress printing our little trick in the output -->
<xsl:template match="//comment()[contains(.,'DOCTYPE')][1]"/>
</xsl:transform>
Note that xt insists that yyy exists! - DaveP
Mike Brown cautions:
Anyone using this should note that this will only work if
the string '-->' does not occur in the internal DTD
subset. The following would throw it, for example:
<!DOCTYPE xxx SYSTEM "yyy" [
<!-- a comment in the internal subset -->
<!ENTITY foo "bar"> ]>
Up to table of content Merging two documentsKen Holman
A working example using XT-19990813 is below.
doc1.xml
<?xml version="1.0"?>
<!DOCTYPE BookSet [
<!ATTLIST Book id ID #IMPLIED>
]>
<BookSet>
<Book id="id1"><Name>The wizard of OZ</Name></Book>
<Book id="id2"><Name>Java Servlet Programming</Name></Book>
<Book id="id3"><Name>John Coltrane Rage</Name></Book>
</BookSet>
doc2.xml
<BookList>
<Book id="id1"/>
<Book id="id2"/>
</BookList>
list.xsl
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Tranform" version="1.0">
<xsl:output method="xml" indent="yes"/>
<xsl:param name="source" select="''"/> <!--source of data-->
<xsl:template match="/BookList"> <!--document element-->
<BookList>
<xsl:for-each select="Book">
<Book id="{@id}">
<xsl:variable name="id" select="string(@id)"/>
<!--note you cannot use document($source)/id($id)-->
<xsl:for-each select="document($source)">
<xsl:copy-of select="id($id)/*"/>
</xsl:for-each>
</Book>
</xsl:for-each>
</BookList>
</xsl:template>
</xsl:stylesheet>
Output
<BookList>
<Book id="1">
<Name>The wizard of OZ</Name>
</Book>
<Book id="2">
<Name>Java Servlet Programming</Name>
</Book>
</BookList>
Up to table of content document() questionKen Holman.
Q: Expansion
>I have a string in a variable and I want to convert it
>to a document via the document() function.
Trying to feed a variable of rich markup to the document() function is
impossible.
However ... getting data from the stylesheet isn't impossible and if
that is what you want to do, an example is below.
In this example I have stopped using ID so that I can use the same id
attribute values in two places. I have invoked the engine twice, once
with a default value and a second time with an argument.
Note that a stylesheet writer does not have control over an XSLT
engine's emission of namespace declarations
T:\ftemp>type doc2.xml
<BookList>
<Book id="1"/>
<Book id="2"/>
</BookList>
T:\ftemp>type list3.xsl
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Tranform" version="1.0"
xmlns:data="any-uri">
<xsl:output method="xml" indent="yes"/>
<data:BookSet set="first">
<Book id="1"><Name>The wizard of OZ</Name></Book>
<Book id="2"><Name>Java Servlet Programming</Name></Book>
<Book id="3"><Name>John Coltrane Rage</Name></Book>
</data:BookSet>
<data:BookSet set="second">
<Book id="1"><Name>An Uninteresting Book</Name></Book>
<Book id="2"><Name>Another Uninteresting Book</Name></Book>
<Book id="3"><Name>Yet Another Uninteresting Book</Name></Book>
</data:BookSet>
<xsl:param name="source" select="'first'"/>
<xsl:template match="/BookList"> <!--document element-->
<BookList>
<xsl:for-each select="Book">
<Book id="{@id}">
<xsl:variable name="id" select="string(@id)"/>
<!--note you cannot use document("")/id($id)-->
<xsl:for-each select='document("")'><!--the stylesheet-->
<xsl:copy-of select="//data:BookSet[@set=$source]
/Book[@id=$id]
/*"/>
</xsl:for-each>
</Book>
</xsl:for-each>
</BookList>
</xsl:template>
</xsl:stylesheet>
T:\ftemp>xt doc2.xml list3.xsl result1.xml
T:\ftemp>type result1.xml
<BookList xmlns:data="any-uri">
<Book id="1">
<Name xmlns:xsl="http://www.w3.org/1999/XSL/Tranform" version="1.0">
The wizard of OZ</Name>
</Book>
<Book id="2">
<Name xmlns:xsl="http://www.w3.org/1999/XSL/Tranform" version="1.0">Java Servlet
Programming</Name>
</Book>
</BookList>
T:\ftemp>xt doc2.xml list3.xsl result2.xml source=second
T:\ftemp>type result2.xml
<BookList xmlns:data="any-uri">
<Book id="1">
<Name xmlns:xsl="http://www.w3.org/1999/XSL/Tranform" version="1.0">
An Uninteresting Book</Name>
</Book>
<Book id="2">
<Name xmlns:xsl="http://www.w3.org/1999/XSL/Tranform" version="1.0">
Another Uninteresting Book</Name>
</Book>
</BookList>
Up to table of content Where can I find the XSLT DTD?John E Simpson
There can't be one for all cases.
>I'll never be able to validate ANY of my XSL doc?
No... unless you do as suggested, and create an
application-specific DTD for use in validating your
stylesheet. This can be quite complicated; if XHTML were the
result tree's vocabulary, for instance, you'd have to allow
for the appearance of just about any XHTML element as a
child of just about any XSLT element.
As someone else said, almost no one bothers checking XSLT
stylesheets for validity -- well-formedness is all right, as
long as the XSLT processor (XT, SAXON, whatever) detects
syntax and other XSLT-specific errors. Validity in the XML
sense is not critical for XSLT. Actually, I'd guess that
absolutely no one bothers to check validity of stylesheets;
the "almost" is just a hedge. :)
Joe English adds
Validators usually give better error messages than XSLT
processors, which is helpful for catching gross structural
errors.
Plus, in cases where the stylesheet makes heavy use of
literal result elements, this can go a long way towards
semantically validating the stylesheet (that is, making sure
that the stylesheet produces valid result documents).
However, constructing a DTD against which to validate the
stylesheet in this case can be a bit tricky. It's usually
not hard to customize the XSLT DTD fragment:
<!ENTITY % xsl.dtd SYSTEM "xslt.dtd">
<!ENTITY % html.dtd PUBLIC
"-//W3C//DTD XHTML 1.0 Strict//EN" "/dev/null">
%html.dtd;
<!ENTITY % result-elements "%inline; | %block;" >
%xsl.dtd;
but the target DTD *also* has to be parameterized in order
to allow XSL instructions inside literal result elements!
This isn't difficult either if you "cheat" and use an SGML
parser for validation; inclusion exceptions fit the bill
nicely here.
Up to table of content How do I get XT to output correct HTML character entitiesJames C If you put in the result namespace attribute correctly,
you will get í.
For example,
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Tranform"
version="1.0">
<xsl:output method="html">
<xsl:template match="/">
<html>í</html>
</xsl:template>
</xsl:stylesheet>
outputs:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>í</html>
Up to table of content Unknown entities (unicode characters)problemSebastian Rahtz
Q expansion:
I've got an XML file, that may contain weird Unicode entities
(such as &laqno;). Of course the parser crashes because my DTD only
contains the most usual Unicode entities.
Has anyone a smarter idea than building a DTD with all Unicodes?
http://www.tug.org/applications/jadetex/unicode.xml
contains everything that I have ever discovered, from which you can
extract what you want. the real claim to fame of this monster is that
it contains all the MathML characters (all recent changes to this file
come from David Carlisle, using it for MathML)
David Carlisle added:
The xsl below will extract an XML compatible entity file (or files)
from unicode.xml, just edit it to get the sets you want, as posted it
just makes one for ISOPUB from ISO 8879. It uses the xt:document
extension for xt. Information for how to make it work with other XSL
engines greatfully received. (Vendor neutral extension namespace,
perhaps?:-)
David
For those not having the time to do so, the editor pre-compiled this lot, and has put it at Unicode Entities
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xt="http://www.jclark.com/xt"
extension-element-prefixes="xt"
version="1.0">
<xsl:output
method="text"
/>
<xsl:template name="alphadecl">
<xsl:param name="set"/>
<xsl:variable name="x">
<xsl:choose>
<xsl:when test="starts-with($set,'9')">
<xsl:value-of select="substring-after($set,'13-')"/>
</xsl:when>
<xsl:when test="starts-with($set,'8')">
<xsl:value-of select="substring-after($set,'-')"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$set"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xt:document method="text" href="{$x}.ent">
<xsl:for-each select="character/entity[@set=$set]">
<xsl:sort select="@id"/>
<xsl:text><!ENTITY </xsl:text>
<xsl:value-of select="@id"/>
<xsl:call-template name="pad">
<xsl:with-param
name="x"
select="15-string-length(@id)-string-length(string(../@dec))"/>
</xsl:call-template>
<xsl:text> "&#</xsl:text>
<xsl:if test="60 = ../@dec or 38 = ../@dec">
<xsl:text>38;#</xsl:text>
</xsl:if>
<xsl:value-of select="../@dec"/>
<xsl:text>;" ><!--</xsl:text>
<xsl:value-of select="../@id"/>
<xsl:text> </xsl:text>
<xsl:value-of select="desc"/>
<xsl:text> -->
</xsl:text>
</xsl:for-each>
</xt:document>
</xsl:template>
<xsl:template name="pad">
<xsl:param name="x"/>
<xsl:if test="$x > 0">
<xsl:text> </xsl:text>
<xsl:call-template name="pad">
<xsl:with-param name="x" select="$x - 1"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
<xsl:template match="charlist">
<xsl:call-template name="alphadecl">
<xsl:with-param name="set" select="'9573-13-isoamsa'"/>
</xsl:call-template>
<xsl:call-template name="alphadecl">
<xsl:with-param name="set" select="'9573-13-isoamsb'"/>
</xsl:call-template>
<xsl:call-template name="alphadecl">
<xsl:with-param name="set" select="'9573-13-isoamsc'"/>
</xsl:call-template>
<xsl:call-template name="alphadecl">
<xsl:with-param name="set" select="'9573-13-isoamso'"/>
</xsl:call-template>
<xsl:call-template name="alphadecl">
<xsl:with-param name="set" select="'9573-13-isoamsr'"/>
</xsl:call-template>
<xsl:call-template name="alphadecl">
<xsl:with-param name="set" select="'9573-13-isogrk3'"/>
</xsl:call-template>
<xsl:call-template name="alphadecl">
<xsl:with-param name="set" select="'9573-13-isomfrk'"/>
</xsl:call-template>
<xsl:call-template name="alphadecl">
<xsl:with-param name="set" select="'9573-13-isomopf'"/>
</xsl:call-template>
<xsl:call-template name="alphadecl">
<xsl:with-param name="set" select="'9573-13-isomscr'"/>
</xsl:call-template>
<xsl:call-template name="alphadecl">
<xsl:with-param name="set" select="'9573-13-isotech'"/>
</xsl:call-template>
<xsl:call-template name="alphadecl">
<xsl:with-param name="set" select="'8879-isobox'"/>
</xsl:call-template>
<xsl:call-template name="alphadecl">
<xsl:with-param name="set" select="'8879-isocyr1'"/>
</xsl:call-template>
<xsl:call-template name="alphadecl">
<xsl:with-param name="set" select="'8879-isocyr2'"/>
</xsl:call-template>
<xsl:call-template name="alphadecl">
<xsl:with-param name="set" select="'8879-isodia'"/>
</xsl:call-template>
<xsl:call-template name="alphadecl">
<xsl:with-param name="set" select="'8879-isogrk1'"/>
</xsl:call-template>
<xsl:call-template name="alphadecl">
<xsl:with-param name="set" select="'8879-isogrk2'"/>
</xsl:call-template>
<xsl:call-template name="alphadecl">
<xsl:with-param name="set" select="'8879-isolat1'"/>
</xsl:call-template>
<xsl:call-template name="alphadecl">
<xsl:with-param name="set" select="'8879-isolat2'"/>
</xsl:call-template>
<xsl:call-template name="alphadecl">
<xsl:with-param name="set" select="'8879-isonum'"/>
</xsl:call-template>
<xsl:call-template name="alphadecl">
<xsl:with-param name="set" select="'8879-isopub'"/>
</xsl:call-template>
<xsl:call-template name="alphadecl">
<xsl:with-param name="set" select="'mmlextra'"/>
</xsl:call-template>
<xsl:call-template name="alphadecl">
<xsl:with-param name="set" select="'mmlalias'"/>
</xsl:call-template>
</xsl:template>
</xsl:stylesheet>
Rick Geimer answered:
You could just include the entity files from MATHML in your DTD, since
they contain unicode mappings from just about all the old iso sgml
entity sets. You can download the entites from the W3C at the
following URL:
http://www.w3.org/TR/REC-MathML/mmlents.zipUp to table of content Character entities appear as garbageDavid Carlisle > With the output method set to "xml", however, references > to certain character entities result in garbage Are you sure it is garbage? most likely it is just that you are looking at the file with a termianl or editor expecting latin1 encoding, but the default encoding for xml is utf8. Up to table of content Viewing entities in XSLT outputMike Brown > All the from the orginal XML document are translated by XT into unexpected characters. The non-breaking space characters are being serialized with UTF-8 encoding. The non-breaking space character, U+00A0, is encoded as 2 bytes. Whatever you are using to view the document is not decoding it properly and is showing the 2 bytes as 2 characters. This could indicate something wrong in your stylesheet if you were expecting to see a character or entity reference. Are you using the text output method, by chance? Nikolai Grigoriev adds: XT produces only UTF-8 and ignores encoding specifiers in xsl:output. For every  , you get C2 A0 - a UTF-8 representation of   Use SAXON and specify encoding="ISO-8859-1" in xsl:output if you want to get it readable ;-). Up to table of content HTML to XMLDavid Carlisle
Can I tranform HTML to XML?
Not quite, but this is a close second best.
The following stylesheet takes as input an XSL stylesheet
that writes HTML, and produces a stylesheet that writes XML
that hopefully matches the XHTML specification. (It does not
check that the output matches the DTD.) It does the
following things:
* Adds a DOCTYPE giving FPI and URL for one of the three
flavours of XHTML1. (Transitional unless the original
stylesheet asked for Frameset or Strict HTML.) If the
system-dtd parameter is set then instead of the canonical
XHTML PUBLIC DTD, a SYSTEM declaration is given to the
supplied URL.
* Writes all HTML elements and attributes as lowercase, with
elements being written in the XHTML namespace.
* Writes canonically empty elements such as <BR> as
<br class="html-compat"/> . (Appendix C
recommends <br /> rather than <br/> but an XSL
stylesheet has no control over the concrete syntax of the
linearisation, so adding an attribute is probably the best
that can be done. (No attribute is added if the element
already has attributes.)
* Changes the output method from html to xml in xsl:output
(and also in the xt:document extension element).
* Forces a line break after opening tags of non elements
which are not canonically empty, to ensure that they are
never written with XML empty syntax, so
<p>
</p>
not
<p/>
* Copies any elements from XSL or XT namespaces through to
the new stylesheet.
* Duplicates name attributes to id unless element already
has id.
* Adds meta element to head specifying utf-8 encoding.
html2xhtml.xsl: HTML to XHTML XSL stylesheet converter
========================================================
$Id: html2xhtml.xsl,v 1.3 1999/12/07 14:11:58 davidc Exp $
Copyright 1999 David Carlisle NAG Ltd
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xt="http://www.jclark.com/xt"
xmlns="http://www.w3.org/1999/xhtml"
version="1.0"
>
<xsl:output method="xml" indent="no"/>
<xsl:param name="system-dtd" />
<xsl:template match="xsl:*|xt:*">
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:template match="xsl:output|xt:document">
<xsl:copy>
<xsl:attribute name="method">xml</xsl:attribute>
<xsl:choose>
<xsl:when test="$system-dtd">
<xsl:attribute name="doctype-system">
<xsl:value-of select="$system-dtd"/>
</xsl:attribute>
</xsl:when>
<xsl:when
test="contains(@doctype-public,'Frameset')">
<xsl:attribute name="doctype-public">
<xsl:text>-//W3C//DTD XHTML 1.0 Frameset//EN
</xsl:text>
</xsl:attribute>
<xsl:attribute name="doctype-system">
<xsl:text
>http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd
</xsl:text>
</xsl:attribute>
</xsl:when>
<xsl:when
test="contains(@doctype-public,'Strict')">
<xsl:attribute name="doctype-public">
<xsl:text>-//W3C//DTD XHTML 1.0 Strict//EN</xsl:text>
</xsl:attribute>
<xsl:attribute name="doctype-system">
<xsl:text
>http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd</xsl:text>
</xsl:attribute>
</xsl:when>
<xsl:otherwise>
<xsl:attribute name="doctype-public">
<xsl:text>-//W3C//DTD XHTML 1.0 Transitional//EN
</xsl:text>
</xsl:attribute>
<xsl:attribute name="doctype-system">
<xsl:text
>http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd
</xsl:text>
</xsl:attribute>
</xsl:otherwise>
</xsl:choose>
<xsl:attribute
name="indent">yes</xsl:attribute>
<xsl:copy-of select="@*[not(
name(.)='method' or
name(.)='doctype-public' or
name(.)='doctype-system' or
name(.)='indent'
) ]"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:template match="*|xsl:element">
<xsl:variable name="n">
<xsl:choose>
<xsl:when test="self::xsl:element">
<xsl:value-of select="translate(@name,
'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
'abcdefghijklmnopqrstuvwxyz')"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="translate(local-name(.),
'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
'abcdefghijklmnopqrstuvwxyz')"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:element
name="{$n}"
namespace="http://www.w3.org/1999/xhtml">
<xsl:for-each select="self::*[not(self::xsl:element)]/@* |
self::xsl:element/@use-attribute-sets">
<xsl:attribute name="{translate(local-name(.),
'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
'abcdefghijklmnopqrstuvwxyz')}">
<xsl:value-of select="."/>
</xsl:attribute>
</xsl:for-each>
<xsl:if test="@name and not(@id)">
<xsl:attribute name="id"
><xsl:value-of
select="@name"/></xsl:attribute>
</xsl:if>
<xsl:if test="@NAME and not(@id)">
<xsl:attribute name="id"
><xsl:value-of
select="@NAME"/></xsl:attribute>
</xsl:if>
<xsl:choose>
<xsl:when test="not($n='br' or $n='hr'
or $n='link' or $n='img' or
$n='base' or $n='meta'
or $n='head')">
<xsl:element name="xsl:text"
xml:space='preserve'>
</xsl:element>
<xsl:apply-templates/>
</xsl:when>
<xsl:when test="local-name(.)='head'">
<meta http-equiv="Content-Type"
content="text/html; charset=utf-8"/>
<xsl:apply-templates/>
</xsl:when>
<xsl:when test="not(@*)">
<xsl:attribute
name="class">html-compat</xsl:attribute>
</xsl:when>
</xsl:choose>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
Up to table of content xsl:number and XTMike Kay > <xsl:number value="position()" level="single" count="title"/> If value attribute is specified, level and count are ignored. The above is equivalent to <xsl:value-of select="position()"/>. The only reason for using the value attribute of <xsl:number> is if you want to take advantage of the number formatting capabilities. Up to table of content How to check that the content of an element is numeric?David Carlisle
<xsl:template match="a">
<xsl:value-of select="."/>
<xsl:if
test= "string(number(.))='NaN'">
is not a number</xsl:if>
</xsl:template>
Up to table of content RTF? Node set? What are they?Mike Kay
Result Tree Fragment. Not a pretty name, and the
abbreviation RTF is unfortunate, but we have to live with
it.
When the body of an <xsl:variable> element is
evaluated (or "instantiated" to use the correct
jargon), the result is written to an RTF. There are only
three things you can do with an RTF: you can use xsl:copy-of
to copy it to the result tree (or to another RTF), you can
convert it implicitly or explicitly to a string, and you can
pass it to a function. There aren't any standard
functions that process RTFs, so in practice this means an
extension function.
SAXON and xt both provide extension functions to convert an
RTF to a node-set. This conversion can't be done
implicitly. The reason your xsl:for-each fails is that the
expression in the select attribute must yield a
node-set. Nothing else will do, in particular, it cannot be
an RTF.
David Carlisle adds:
A node set is what you get back from a select expression so
select="aaa[@xxx]|aaa[bbb]"
gives you the set of all elements with name aaa and either a
xxx attribute or a bbb child. Note this is a set not a list.
If some aaa element has both xxx attribute and bbb child,
you only get it once. The set is however ordered (in
document order, normally)
A node set is what you can apply templates to
<xsl:apply-templates select="aaa[@xxx]|aaa[bbb]"/>
ie it's the relevant part of the input document (or some
secondary input document via the docyument() function)
A result tree fragment is what you produce in a template.
You can save it in a variable and while it has similar
structure to a node set (it's a bunch of XML nodes) it is
essentially opaque to XSL You can not apply templates to it
or interrogate its structure. The only thing you can do is
use xsl:copy-of to put the value of the variable holding the
result tree fragment into the result tree at some point.
xt and saxon (at least) have an extension function that
converts result tree fragments to node sets.
> <xsl:for-each select="$members">
members holds the result tree fragment, so you can't select
into it.
You could use
<xsl:for-each select="xt:node-set($members)">
Mike Brown adds:
You can identify *any combination* of unique nodes from
different places in the source tree, using an XPath
expression that selects the ones you want. Those nodes are
a "node set". They don't have to form a hierarchy or
anything.
You can create a new hierarchy of nodes (or multiple
hierarchies that are siblings of each other), using various
XSLT instructions and/or literal result elements. Those
nodes are a "result tree fragment". They're branches of a
tree.
So a result tree fragment *is* a set of nodes. It's just not
a "node set"
Up to table of content Sort and xt:node-setSebastian Rahtz
<foo>
<bar id="1" links="a b c"/>
<bar id="2" links="b d d e f"/>
<bar id="3" links="b"/>
<bar id="4" links="c a"/>
<bar id="5" links="g j"/>
<bar id="6" links="a f"/>
</foo>
and I want make a sorted catalogue of the bits of the
"links" attribute, showing the <bar> each is found in.
I append my stylesheet, using XT's node-set extension. I
run over the <bar> elements, splitting the
"links" value, and building a new node-set. I then
sort that, make a new node-set, and step through it finding
the different 'a', 'b', 'c' etc.
Sebastian Rahtz
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0"
xmlns:xt="http://www.jclark.com/xt"
extension-element-prefixes="xt">
<xsl:template match="foo">
<!-- store in a variable the inverted list of <bar> elements -->
<xsl:variable name="results">
<xsl:for-each select="bar">
<xsl:call-template name="searchlist">
<xsl:with-param name="list"
select="concat(@links,' ')"/>
</xsl:call-template>
</xsl:for-each>
</xsl:variable>
<!-- now convert the list to a node-set, sort, and store again -->
<xsl:variable name="sorted">
<xsl:for-each select="xt:node-set($results)/bar">
<xsl:sort select="@id"/>
<xsl:sort select="@parent"/>
<bar id="{@id}" parent="{@parent}"/>
</xsl:for-each>
</xsl:variable>
<!-- now convert that to a node-set and step through it,
looking for the first occurrence of each id -->
<xsl:for-each select="xt:node-set($sorted)/bar">
<xsl:variable name="c" select="@id"/>
<xsl:if test="not(preceding-sibling::bar[$c=@id])">
Link: <xsl:value-of select="@id"/>
- ----------
<xsl:apply-templates select="." mode="final"/>
<xsl:apply-templates
select="following-sibling::bar[$c=@id]" mode="final"/>
- -----------
</xsl:if>
</xsl:for-each>
</xsl:template>
<xsl:template match="bar" mode="final">
<xsl:value-of
select="@parent"/><xsl:text> / </xsl:text>
</xsl:template>
<xsl:template name="searchlist">
<!--
split up the list by space, and for each value
make a new <bar> element, and then recurse to get another
value
- -->
<xsl:param name="list"/>
<xsl:if test="not($list = '')">
<bar id="{substring-before($list,' ')}"
parent="{@id}"/>
<xsl:call-template name="searchlist">
<xsl:with-param name="list"
select="substring-after($list,' ')"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
Up to table of content Non-Latin characters in XT outputMichael Kay
Q expansion
I have some non-Latin characters in my xml documents as character
references and I'd like to run the documents through xt and those
character references would still be there. example:
Source:
<?xml version="1.0" encoding="ISO-8859-1"?>
<character>
i G I ć
</character>
Stylesheet:
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Tranform"
version="1.0">
<xsl:output method="html" indent="yes"/>
<xsl:template match="/">
<xsl:value-of select="character"/>
</xsl:template>
</xsl:stylesheet>
when I run it through the latest xt, I get:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0
Transitional//EN">
i G I ć
, but I when I try to output it as xml by changing the method to
"xml", I get:
i G I Ä ?
and I'd like to get in my xml output:
i G I ć
Answer:
The XSLT syntax to achieve this is <xsl:output
encoding="iso-8859-1"/>. You'll have to
check whether xt supports it. (SAXON 4.7 does, provided that
the Java runtime does.
David Carlisle adds:
Of course you _shouldn't_ want that. As the version with utf-8
encoded output is completely equivalent to an XML application.
However, assuming that you will want that anyway, I think
that the way to get this in XSL would be to change the
output encoding from utf-8 to anything else which does not
directly encode position ć then this slot will
have to be output as that (or the decimal equivalent)
so in otherwords you want
<xsl:output
method="xml"
encoding="iso-8859-1"/>
However xt (the new release to match the new PR) says:
The xml output method ignores the encoding, doctype-system,
doctype-public, so currently I don't think you can do
this in xt (without a lot of pain)
David later explained,
The xml/unicode character set consists of the numbered
characters in the range 1 through to hex 10FFFF (with some
slots disallowed, but ignore that for now).
That is the `Universal Character Set (UCS)'
utf8 is a particular encoding of that range (actually it can
encode the full UCS4 range, up to hex FFFFFFFF, although
`only' the first 17 planes of 2^16 characters are
currently in Unicode (and only the first 2^16 characters up
to FFFF are in Unicode 2.x)
Note that utf8 is just an `encoding' of the 32bit
character number into 1 or more sequences of 8bit bytes, it
does not re-order or subset the available characters.
Now `traditional' encodings like `latin1' or
`latin2' or `windows ansi' or `microsoft code page
850' or the 8bit cyrillic encodings are subsets of the
available characters in UCS (if they are not subsets they
can not be used in XML as the underlying character set in
XML is always unicode).
If you say
<?xml version="1.0" encoding="microsoft-weirdness" ?>
then the available characters and the way they are encoded
as bytes (ie effectively their order) is whatever Bill Gates
says it is. So the byte with value 255 may or may not be
y-umlaut (which is what position 255 is in latin1 and
unicode) However the syntax ÿ (and equivalently
ÿ) _always_ refers to the unicode numbering not the
current encoding used to decode bytes of character data.
So....
If the encoding is the default utf8 encoding and an XML
system wants to output the character hex 107 (which is
c-acute) then it can _always_ output it as either
ć or ý
however since that is 6 or 7 bytes, if the xml declaration
specifies an encoding for character data that includes this
slot then probably the system will just do that. This is a
latin-2 character so if the encoding is specified as latin-2
then c acute can be encoded in the single byte with value
230. If the encoding is utf8 then there will be a two byte
representation of character position 263, as shown in the
original posters question.
Since the request in this case was to force the system to
use the character reference form, the actual encoding for
the character data did not matter, as long as this character
was _not_ part of the encoding.
If you pick latin-1 (or ascii, or presumably a cyrillic
encoding) then in that encoding there is no encoding for
c-acute ie no encoding for unicide #x107, so with any of
these encodings the only way to get a c acute is to use
k (actually you could use c followed by a combining
acute character, but whether or not that is the same thing
depends on who you are, and what you are doing...)
Up to table of content Bulgarian or Cyrilic characters in my xml/xsl?Nikolai Grigoriev It depends mostly on whether the appropriate fonts are installed on your machine. IE4-5 under Win95/NT works fine with UTF-8 if you have the appropriate charset (204) in your fonts; normally, Times New Roman, Arial, and Courier New contain the charset 204, and all other do not. In the same environment, you may also try windows-1251 as the charset name. If you are under Unix, try either koi8-r (sometimes spelled as koi8r, without dash) or iso-8859-5; chances are that you have at least one of the two. Another problem is whether your XSLT processor is able to handle any of these. I admire XT but it still lacks support for anything but UTF-8 in the output; SAXON is much more foreigner-friendly ;-). Please note that UTF-8/Unicode, windows-1251, koi8-r and iso-8859-5 are all mutually incompatible. If you were about to publish Cyrillic texts in Russian over the Internet, I would recommend using koi8-r. Bulgarian uses the same repertory of glyphs, but I don't know which is the preferred charset; they could also have a fifth version ;-). Up to table of content How to use a string variable as part of a pattern?G. Ken Holman
If the variable isn't a node set, then it cannot be used
directly as a location step in a location path in this
fashion, therefore, the XT behaviour is correct.
String variables are allowed in *predicates*, so you could select all
element children and then filter based on the element type name:
<xsl:variable name="enums"
select="document(
'../common/enum.xml')/enums/*[local-name(.)=$enum]"/>
Up to table of content Variables and constantsLars Marius Garshol
can anyone explain to me the rationale for not having true
variables a'la procedural programming languages (i.e. you
can re-assign the value of an existing variable)?
XSLT is not alone in not having assignment, in fact there is
a whole family of programming languages called the
functional programming languages that work this way. The
best-known are perhaps Standard ML and Haskell. (No, Lisp
does not belong here. Lisp is imperative, just like the
mainstream languages.)
The difference between the traditional imperative languages
and the functional ones is a deep one and not easily
understood. At the deepest level it has to do with whether
change (that is, time) is allowed in a program or not.
If change is banished, functions always return the same
values and reasoning about what is going on in the program
becomes enormously much simpler.
The best description you are likely to find of what this
really means appears in 'The Structure and Interpretation of
Computer Programs', by Abelson, Abelson and Sussman. (The
book is definitely recommended for anyone who wants to to
serious programming, BTW.)
David Carlisle exemplifies
The fact that some calculations are rather awkward in xslt
is not really due so much to the functional style, as to
the fact that the main `function' expression that you have
available, namely the template returns a result of a type
`result tree fragment' that is opaque to the expression
language.
If the restrictions on querying into rtf were not there or
(equivalently) a function is provided to coerce an rtf back
to a node set so that it may be queried, then many things
become much simpler.
So here is your basket calculation sans recursion but with
xt:node-set
<x>
<thing><quantity> 1</quantity><price> 2</price></thing>
<thing><quantity> 4</quantity><price> 5</price></thing>
<thing><quantity> 3</quantity><price>10</price></thing>
<thing><quantity> 2</quantity><price> 1</price></thing>
</x>
<total xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xsl:version="1.0"
xmlns:xt="http://www.jclark.com/xt"
>
<xsl:variable name="x">
<xsl:for-each select="x/thing">
<a><xsl:value-of select="quantity * price"/></a>
</xsl:for-each>
</xsl:variable>
<xsl:value-of select="sum(xt:node-set($x)/a)"/>
</total>
xt basket.xml basket.xsl
<?xml version="1.0" encoding="utf-8"?>
<total>54</total>
Up to table of content How to run XT on a MacViewing XSLT output on the MacChuck White Jeremy Quinn
I finally figured out how to run XT on a Mac (non OSX, which
is a non-issue), and thought I'd share it with the group.
As you know, running XT or FOP requires a command line
interface, which of course the Mac doesn't have unless
you're using OSX. I have tried this before, to no avail, but
the MRJ (the Apple Java runtime) was updated so I downloaded
it, and perhaps that is why XT now runs. I don't know the
answer.
Anyway, here are the instructions:
First, you need to have JBindery, which I believe comes with
the MRJSDK (I don't think it's part of the
runtime). You can find the MRJ 2.1 SDK (the Apple Java
software development kit) at
http://developer.apple.com/java/text/download.html.
Then comes the fun part: trying to build command lines using
a GUI. It will help if you refer to the following command
line structure James Clark has on his XT page:
java -Dcom.jclark.xsl.sax.parser=your-sax-driver
com.jclark.xsl.sax.Driver source stylesheet result
The directions below will compare the GUI stuff with the
corresponding commands one would normally use in a command
line environment.
1. When you launch JBindery, you're presented with a
screen with six icons on the left and a series of text
fields on the right. Clicking on the top icon reveals the
fields you use to create your "command line"
setup. The top-most field is called "Class
name". Here you should input
'com.jclark.xsl.sax.Driver'. This corresponds to the
command of the same name above, and is the name of the main
class file. The field below that is called "Optional
parameters". Here, you should input the file names at
the end of the above command line: "source stylesheet
result". I input stuff based on the XT sample files:
"slidesTest.xml slides2.xsl slidesOut.xml". Below
the "optional parameters" fields are a redirect
stdout drop down menu and a redirect stdin drop down menu. I
left the redirect stdin alone, but for the redirect stdout I
named a file called "test.out". This text file will
troubleshoot any problems you're having, and should be
empty if all is well. This first set of fields also has a
"Save Settings" option, which is of course a good
idea.
2. Next, set up the class path (I guess this is normally a
first step, but, hey, I'm on a Mac), which you access
with the next icon on the left, the classpath icon. This is
actually pretty easy in JBindery. You just use the dialog
box that is revealed on the right when the classpath icon is
clicked to browse for any jar files you think you'll be
using. I put in all the jar files I anticipate using,
including XP, SAX, and even FOP, since I know I want to use
this later. I put the XT jar files in the same folder as
JBindery so as not to deal with any other classpath issues
for now.
3. The next icon on the left is the properties icon. This is
sort of a confusing interface, but your goal is to mimic the
properties shown first in the XT command line I listed
previously:
"-Dcom.jclark.xsl.sax.parser=your-sax-driver". You'll
see three fields on the right hand side of the dialog box
after clicking the properties icon. Ignore the top
field. It will fill in automatically when you fill in the
two fields below it. In the left field I input
"jclark.xsl.sax.parser". In the right field, I input
"com.jclark.xml.sax.Driver". You can put whatever
SAX driver you want, of course.
I should mention that the slides.xsl example included with
the XT build doesn't work with these settings. I'm
thinking it's just cuz I'm using an older SAX
driver, though, and need to try a different one. I had to
make a simpler xsl file, which I was able to output
successfully.
If there is interest and/or need, I'd be happy to post
some GIF files showing how the screens should look for
JBindery. If anyone tries this and can't get it working,
feel free to e-mail me and I'll try to help.
I have XT/XP/SAX running on >Apple's MRJ SDK 2.1.4.
The tests run, my own scripts run (from my win32 >xt.exe
development), but the output is giving me the wrong line
breaks >such that I can only open the resulting files on
UNIX, that dread ^M pops >up everywehre so nothing will
open these files (BBedit, all my old >faithfuls, and the
Mac finder calls the .xml files graphics . . . go
>figure-- Microsoft isn't the only hokey file
response feedback sometimes).
It sounds like you need to re-build your desktop after
having assigned the .xml (and .xsl) suffixes to BBedit in
the Internet CP. (There are also droplets that will batch
set file type/creator for you).
BBEdit opens, views, edits and saves files with any line
ending, no problem. It also handles MacRoman (obviously :)
and Unicode, but not Latin1 unfortunately.
Up to table of content XSL Processors in batch modeBob Lyons > Does anyone know offhand if either XT or Xalan can run an entire > subdirectory's XML files through a stylesheet from one command on the > command line? What're the arguments to use? XT can do this by invoking it as follows: xt source_dir stylesheet result_dir XT will apply the stylesheet to each file in the source_dir directory and put the output files in the result_dir directory. Note that XT will re-parse the stylesheet for each source file in the source directory. The stylesheet should not be in the source_dir. When XT creates an output file, it will use the same file name as the corresponding input file. Let's say that your input XML documents are in the IN directory, and your stylesheet (xlate.xsl) is in the current directory, and you want the output files to be placed in the OUT directory. Then you would execute the following command: xt in xlate.xsl out I don't think that this XT feature is documented. I found out about it by reading the source code of the com.jclark.xsl.sax.Driver class (the 19991102 version of XT). Up to table of content Which XSLT processor?Sebastian Rahtz - XT is best because its the fastest - Saxon is best because it implements all the spec - Oracle is best because it has a C version alongside (incomplete) - Xalan is best because it it is politically correct (in Apache) - Microsoft is best 'cos its in the browser If Michael Kay's reported optimization changes in Saxon live up to expectations (ie it reaches the approximate speed of XT), I for one plan to switch to it from XT. Perhaps a downside (or strength, depending on your view) is that it has a single author who does it for "fun".[1] The fact that James Clark seems to have gone entirely quiet with xt (ie it is still incomplete vis-a-vis the spec) shows the problem with that. If Microsoft release a version of their XSLT which 100% implements the spec, of course the picture changes dramatically. Up to table of content Using XSLT with a DatabasePaul Tchistopolskii / Steve Muench I suggest to take a look at http://www.pault.com/Pxsl/ PXSLServlet v 0.2. is a wrapper around XT and it allows feeding XT with the data from SQL server as if it is XML. and from Steve M If you get your hands on the free XSQL Servlet from Oracle, it makes doing what you're doing very easy against Oracle and non-Oracle databases running under any servlet engine. You type in your query, you provide a stylesheet. Presto. Live demos running at: http://technet.oracle.com/tech/xml/demo/demo1.htm and the demos are all included in the release to learn from. Download by visiting: http://technet.oracle.com/tech/xml/xsql_servlet and clicking on the "Software" icon at the top. and from Mike Kay You might like to look at the SQL extension elements in Saxon: a very simple "demo" facility, but with a little energy it could be turned into something very useful for loading XML data into relational databases. > Another question is if XSLT can take other > datasource other than XML for exporting data from database. I > am exploring the solutions, so any thoughts are appreciated. Yes. Most XSLT processors will accept input from any SAX parser, so all you need is to write an implementation of the SAX parser interface to supply the data. Up to table of content How to get ISO 8859-1 output from XT?JC JC (Aug 1999)
With the current XT you can just do
<xsl:output method="html" encoding="iso-8859-1"/>
Up to table of content XT and encodingsJames Clark
On input, it's up to the XML parser you use. If you're
using XP, it doesn't support iso-8859-2. It only supports
iso-8859-1, us-ascii, utf-8 and utf-16.
On output, it depends on the output method. The XML output
method supports only UTF-8. The other output methods
support any encodings supported by your Java VM.
Up to table of content How to execute FOP from within XT.James Tauber I'm sure you could hack either FOP or XT to enable this, by treating FOP as an output method handler. But FOP currently implements the reverse, at James Clark's suggestion. FOP can treat XT as if it were a SAX Parser, thereby executing XT from within FOP. The com.jtauber.fop.apps.XTCommandLine (now org.apache.fop.apps.XTCommandLine) class provides a way of doing this on the command line. Up to table of content How to get the login and full name of the user running XT?Pete Johnston
I _think_ you should be able to get at this using the XSLT
system-property() function, but I haven't been able to
get this to work as I hoped (and didn't get any response
to my query here on the subject a couple of weeks ago.)
However, using XT, you can call the getProperty method of
java.lang.System directly to access properties specified at
run time. Something like:
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/XSL/Transform/1.0"
xmlns:prop="http://www.jclark.com/xt/java/java.lang.System"
result-ns="">
<xsl:template match="/">
<xsl:value-of select="prop:get-property('my.prop')"/>
</xsl:template>
</xsl:stylesheet>
when run from the DOS command line with
java -Dmy.prop=xxx com.jclark.xsl.sax.Driver prop.xml prop.xsl
generates:
xxx
so if you can put the values you require into properties in
whatever procedure invokes XT, then I think you should be in
business.
Up to table of content Invoking XT from the command lineMike Brown The XT documentation says: java -Dcom.jclark.xsl.sax.parser=your-sax-driver com.jclark.xsl.sax.Driver source stylesheet result
Do not use the above command line as-is. If you are using XP
for your parser, you don't need to have the
-Dcom.jclark.xsl.sax.parser=your-sax-driver argument on the
command line. This is sufficient:
java com.jclark.xsl.sax.Driver MySource.xml MyStylesheet.xsl In order for this to work, you need:
. a java interpreter (which it sounds like you have),
. MySource.xml and MyStylesheet.xsl
. the following in your classpath:
xt.jar
sax.jar
xp.jar
and the core Java classes (classes.zip)
If you are having trouble setting the appropriate classpath in your environment, you can also put it on the command line. You said you're on a UNIX system, so the following should work. Replace /path/to with the appropriate, explicit paths to the .zip and .jar files you need.
java -classpath
/path/to/jdk/lib/classes.zip:/path/to/xt/xt.jar:/path/to/xt/sax.jar:/path/to
/xp.jar com.jclark.xsl.sax.Driver MySource.xml MyStylesheet.xsl
The same thing will work on MS-DOS if you reverse the slashes and use semicolons instead of colons as separators in the classpath argument. There are some more examples under the "How to use XT" heading of Chapter 14 of the XML Bible: XSL Transformations, at http://metalab.unc.edu/xml/books/bible/updates/14.html and on Slide 272/Page 91 ("Invoking XT") in the Crane Softwrights' Practical Transformation Using XSLT and XPath free preview download at http://www.cranesoftwrights.com/training/index.htm#ptux Up to table of content XSLT Timing comparisonsGreg Bylenok
I tried running the transform under a few different
processors, which much success. Here are the results: (all
times are in seconds)
Sample LotusXSL XT Saxon Saxon
Size: (Oct) (Oct) (July)
50kb 2.5 7 5.0 3.9
100kb 8.3 7 12.1 5.1
200kb 42.2 9 20.0 7.2
400kb 348.9 11 62.8 12.8
800kb ** 15 216.0 25.8
Conclusions:
While this test was by no means rigorous, it shows that the
LotusXSL processor is good for small samples but may not be
suitable for large samples. By comparison, the XT processor
is very well suited for large samples. Interestingly, the
only processor which showed clear linear behavior was the
older version of Saxon.
A few notes about the test:
IBM's XML4J parser was used in all cases. Times listed for
XT are estimates, because XT doesn't seem to print out the
processing time.
The XML sample is much broader than it is deep (many
branches off the root node, only three or four levels deep
in places). The number of branches off the root node grows
pretty much linearly with the file size. Thus, a 50Kb file
has about 50 branches off the root node, etc...
Up to table of content XT as servletKirk V. Hastings Well I struggled with implementing JC's XT Servlet for a long time and I finally did get it to work, with boss-pleasing results. The secret for me was using Tomcat rather than Jserv. James says very explicitly with regard to using XT as a servlet: "This requires a servlet engine that implements at least version 2.1 of the Java Servlet API." Jserv, unfortunately, is only compliant with version 2.0 of the Java Servlet API. Many have rewritten the XT Servlet so that it functions under Jserv, but I've had nothing but trouble with all of these versions. Under Tomcat I was able to use it completely unmodified, well nearly so. For a working example see: http://sunsite.berkeley.edu:11112/kirk/servlet/xt/dynaxml/test/test What you are looking at is a single XML file being processed by XT using a single stylesheet. All dynamic behavior is implemented by passing parameters in the URL. There are no static files. Please excuse the speed, this is a test server. Also, I've been too busy to modify my stylesheets (both XSLT & CSS) to get it to look good in all browsers. Please, please, please view only with IE 5 for now. ;) If anyone is interested, I'd be glad to share both my stylesheets and server setup... khasting@library.berkeley.edu Paul Tchistopolskii adds: PXSLServlet ( being invoked in 'simple' mode) implements *exactly* this scenario. When invoked in 'advanced' mode it grabs the source XML file from SQL database instead of text file, but that's another story. The source code is available at www.pault.com/Pxsl/ It is work in progress, but mostly that progress happens in SQL part. I'l not provide too much support for version 0.2, but will start providing support for version 0.3 ( on the way ). However, if one is able to read 2 small and clear java files - the version 0.2 already has all the source code needed to suport the scenario you have described above. Up to table of content Where can I find out about the XT extension functions?Mike Brown
Looking at
http://www.jclark.com/xml/xt.html,
"Extension Functions
A call to a function ns:foo where ns is bound to a namespace of the
form http://www.jclark.com/xt/java/className is treated as a call of
the static method foo of the class with fully-qualified name
className."
In other words, you have access to the methods of any Java class in
the CLASSPATH known to the Java instance that's running XT. mkdir() is
one such method that is in the standard java.io.File class.
xt:mkdir has been mentioned on the list twice before, so none of you
have any excuse for not having heard about xt:mkdir before now! (I'm
kidding)
In response, I received the following advice from James Clark on how to use
what gets returned by the mkdir function in a variable:
"In XT's current implementation, the definition of a result tree
fragment valued variable is evaluated lazily once each time the
variable is referenced. So if a definition of a result tree fragment
valued variable has side-effects, make sure you reference that
variable exactly once."
Richard Lander gave an example.
<?xml version='1.0' standalone='no'?>
<!DOCTYPE xsl:stylesheet [
]>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xtfile="http://www.jclark.com/xt/java/java.io.File"
version="1.0"
xmlns:xt="http://www.jclark.com/xt"
extension-element-prefixes="xt">
<xsl:param name="filepath" select="'Output/'"/>
<xsl:output method="xml" indent="yes"/>
<xsl:template match='/'>
<xsl:comment>
<xsl:value-of select=
"xtfile:mkdir(xtfile:new(string($filepath)))"/>
</xsl:comment>
<xsl:apply-templates/>
</xsl:template>
</xsl:stylesheet>
try:
xt mkdir.xsl mkdir.xsl
and
xt mkdir.xsl mkdir.xsl filepath=anydir
If you are calling xt from a batch file, you may need to use quotation
marks, as in: "filepath=anydir"
Up to table of content How to pipeline XT processing.David Carlisle
an alternative, for xt, is to use xt:node-set. Run one set
of templates and stuff the entire result tree into a
variable then get it back as a node set and run some more
templates on it, all within the same stylesheet.
Up to table of content xt:nodesetDavid Carlisle
An example of re-using parts of the output tree.
This is a simple case, but you can get finer control if you
want it.
Starting from
===========================================
<doc xmlns="one">
<head>test</head>
<section>
<head>one</head>
<p>this paragraph
this paragraph</p>
<p>another paragraph
another paragraph</p>
</section>
</doc>
==========================================
You could use this stylesheet to get to html
=========================================
<xsl:stylesheet xmlns:xsl=
"http://www.w3.org/1999/XSL/Transform"
version="1.0"
xmlns:one="one"
xmlns:two="two"
>
<xsl:output method="xml" indent="yes"/>
<xsl:template match="one:doc">
<two:html>
<two:head>
<two:title><xsl:value-of select="one:head"/></two:title>
</two:head>
<two:body>
<two:h1><xsl:value-of select="one:head"/></two:h1>
<xsl:apply-templates select="one:section"/>
</two:body>
</two:html>
</xsl:template>
<xsl:template match="one:section">
<two:h2><xsl:value-of select="one:head"/></two:h2>
<xsl:apply-templates select="*[not(self::one:head)]"/>
</xsl:template>
<xsl:template match="one:p">
<two:p><xsl:apply-templates/></two:p>
</xsl:template>
</xsl:stylesheet>
==========================================
which results in
==========================================
<?xml version="1.0" encoding="utf-8"?>
<two:html xmlns:one="one" xmlns:two="two">
<two:head>
<two:title>test</two:title>
</two:head>
<two:body>
<two:h1>test</two:h1>
<two:h2>one</two:h2>
<two:p>this paragraph
this paragraph</two:p>
<two:p>another paragraph
another paragraph</two:p>
</two:body>
</two:html>
===========================================
If you had an html to text stylesheet that looked like
===========================================
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0"
xmlns:t="two"
>
<xsl:output method="text"/>
<xsl:template match="t:head">
</xsl:template>
<xsl:template match="t:h1">
<xsl:value-of select="."/>
<xsl:text>
</xsl:text>
<xsl:value-of select="translate(.,'eston','=====')"/>
<xsl:text>
</xsl:text>
</xsl:template>
<xsl:template match="t:h2">
<xsl:value-of select="."/>
<xsl:text>
</xsl:text>
<xsl:value-of select="translate(.,'eston','-----')"/>
<xsl:text>
</xsl:text>
</xsl:template>
<xsl:template match="t:p">
<xsl:text>
</xsl:text>
<xsl:apply-templates/>
<xsl:text>
</xsl:text>
</xsl:template>
</xsl:stylesheet>
==========================================
You could run that on the above output and get
==========================================
test
====
one
- ---
this paragraph
this paragraph
another paragraph
another paragraph
==========================================
Alternatively you could merge the two stylesheets and get
one stylesheet that does the work of two, like this
==========================================
<xsl:stylesheet xmlns:xsl=
"http://www.w3.org/1999/XSL/Transform"
version="1.0"
xmlns:xt="http://www.jclark.com/xt"
extension-element-prefixes="xt"
>
<xsl:output method="text"/>
<xsl:import href="chain2.xsl"/>
<xsl:import href="chain1.xsl"/>
<xsl:template match="/">
<xsl:variable name="x">
<xsl:apply-templates/>
</xsl:variable>
<xsl:apply-templates select="xt:node-set($x)/*"/>
</xsl:template>
</xsl:stylesheet>
==========================================
which produces the above text output if given the original
document modulo a spurious xml declaration that may or may
not be a bug in xt (I need to check what the spec says about
xsl:import producing multiple conflicting xsl:output )
Up to table of content Multiple input to multiple outputRobert C. Lyons
Is it possible to use XSL to process all the XML files in a directory
according to one stylesheet and create one output file for each input file?
Sebastian wrote
surely this is best done with a conventional script? like
for i in *.xml
do
xslprocess $i foo.xsl
done
or whatever the equivalent in Windows command language is?
David C wrote:
> Can I by any chance use the document function for this?
only if you know in advance what the files are:
<xsl:apply templates select="document('file1.xml')"/>
<xsl:apply templates select="document('file2.xml')"/>
.
.
.
Which is a bit of a pain, in which case it is easier to do
for i in *.xml ; do xt $i style.xsl ; done (whatever the nt
command line syntax for a loop is, that is (ba)sh syntax)
The disadvantage of that is it starts up the java virtual
machine and reparses the stylesheet afresh on each input
file. This is normally what I do, but what probably I ought
to do is instead of running xt from the command line like
that, have a small java wrapper program that gets all the
files in the directory and passes them to the xt class.
Robert gives us:
Yes, this is possible using XT.
You can invoke XT as follows:
xt source_dir stylesheet result_dir
XT will apply the stylesheet to each file in the source_dir
directory and put the output files in the result_dir
directory.
The stylesheet should not be in the source_dir. When XT
creates an output file, it will use the same file name as
the corresponding input file.
Let's say that your input XML documents are in the IN
directory, and your stylesheet (xlate.xsl) is in the current
directory, and you want the output files to be placed in the
OUT directory. Then you would execute the following command:
xt in xlate.xsl out
I don't think that this XT feature is documented.
I found out about it last week by reading the source code of
the com.jclark.xsl.sax.Driver class (the 19991102 version of
XT).
Mitch Christensen adds
I would recommend a general purpose Perl script which
outputs an XML representation of the directory (optionally
recursive). This directory.xml then can be used for any/all
file processing from within XSL.
An example would be.
<directory location="file:///C:/">
<file name="foo" ext="xml" createdate="blah".../>
...
<directory location="file:///C:/DOS">
...
</directory>
</directory>
Once this file exists, you can use the document() function
to process files/directories as you like.
Up to table of content Pipe or chainingMike Kay > Im trying to do two xslt transformations chained after each other. If you can't combine the operations directly, there are two approaches to chaining: 1. Use the node-set extension. The first transformation creates a result tree fragment, you convert this to a node-set using the node-set() extension function, then you process this node-set with the second transformation. It's probably best for each transformation to use a separate mode. 2. Use two stylesheets, and arrange (via the XSLT vendor's published API) to pipe the output of the first as the input to the second. The details will vary for each product. Saxon has an extension <saxon:output next-in-chain="phase2.xsl"> to make this kind of chaining easy. Up to table of content |
A site designed by |