FAQ 4xt [ Home ]  [ List ]  [ News ]  [ Docs ]  [ FAQ ]  [ Downloads ]  [ Resources ]  [ About ] Search : / Home / FAQ XT Frequently Asked Questions Maintained 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 content Implementations of XSLT Where to start with XSL String->LocationPath How to include or exclude content for debug How to copy the DOCTYPE value Merging two documents document() question Where can I find the XSLT DTD? How do I get XT to output correct HTML character entities Unknown entities (unicode characters)problem Character entities appear as garbage Viewing entities in XSLT output HTML to XML xsl:number and XT How to check that the content of an element is numeric? RTF? Node set? What are they? Sort and xt:node-set Non-Latin characters in XT output Bulgarian or Cyrilic characters in my xml/xsl? How to use a string variable as part of a pattern? Variables and constants How to run XT on a Mac XSL Processors in batch mode Which XSLT processor? Using XSLT with a Database How to get ISO 8859-1 output from XT? XT and encodings How to execute FOP from within XT. How to get the login and full name of the user running XT? Invoking XT from the command line XSLT Timing comparisons XT as servlet Where can I find out about the XT extension functions? How to pipeline XT processing. xt:nodeset Multiple input to multiple output Pipe or chaining Q & A Implementations of XSLT Linda 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/LotusXSL 4XSLT (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 XSL Mike 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->LocationPath Nikolai 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 debug David Carlisle something like this? <xsl:param name="debug-flag" select="0"/> ... <xsl:if test="$debug-flag &gt; 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 value Steve 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 documents Ken 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() question Ken 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 entities James C If you put in the result namespace attribute correctly, you will get &iacute;. For example, <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Tranform" version="1.0"> <xsl:output method="html"> <xsl:template match="/"> <html>&#x0ED;</html> </xsl:template> </xsl:stylesheet> outputs: <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html>&iacute;</html> Up to table of content Unknown entities (unicode characters)problem Sebastian 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>&lt;!ENTITY &lt;/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> "&amp;#&lt;/xsl:text> <xsl:if test="60 = ../@dec or 38 = ../@dec"> <xsl:text>38;#&lt;/xsl:text> </xsl:if> <xsl:value-of select="../@dec"/> <xsl:text>;" &gt;&lt;!--&lt;/xsl:text> <xsl:value-of select="../@id"/> <xsl:text> &lt;/xsl:text> <xsl:value-of select="desc"/> <xsl:text> --&gt; &lt;/xsl:text> </xsl:for-each> </xt:document> </xsl:template> <xsl:template name="pad"> <xsl:param name="x"/> <xsl:if test="$x &gt; 0"> <xsl:text> &lt;/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 garbage David 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 output Mike Brown > All the &nbsp; 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 &nbsp, you get C2 A0 - a UTF-8 representation of &#160; 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 XML David 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 XT Mike 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-set Sebastian 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 output Michael 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> &#x0069; &#x0047; &#x0049; &#x0107; </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 &#263; , but I when I try to output it as xml by changing the method to "xml", I get: i G I &Auml; ? and I'd like to get in my xml output: i G I &#x0107; 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 &#x0107; 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 &#255; (and equivalently &#xFF;) _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 &#x107; or &#253; 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 &#107; (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 constants Lars 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 Mac Viewing XSLT output on the Mac Chuck 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 mode Bob 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 Database Paul 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.