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.zip Up 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 |