How XSLT works. An overview.
1. | What's it all about? | |||
Broadly speaking, XSLT is very good at "down-translations" (manipulating information based on explicit markup structures and features), but not so good for "up-translations" (inferring structures and features that are not directly expressed in the markup). Regular expressions and more sophisticated string handling in general, along with the nodeset() function, will take it some way towards the latter. Grouping is a good proof of this rule, as it's an up-translation (though not the most challenging one). If you want to know why this is, the historical context that Dave C. cited is helpful; the first paragraphs of the XSLT Rec, where its design goals are stated, are also worth contemplating. A corollary to this principle is that XSLT is at its best when working over XML whose design is well fitted to the task. From well-designed (and well tagged) XML, most everyday applications will be "downhill". Poorly designed XML makes the XSLT hard. (Though only remarked on occasionally, we see this every day on this list.) Ironically, it seems these days that much of the work to which XSLT is being put is really just to mitigate difficulties caused by poor design (to wrestle the XML, that is, through some combination of up- and down- translation, into something more tractable for the next step). | ||||
2. | Where to start with XSL | |||
See the References section for the W3C and other references 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/ | ||||
3. | XML parsers and XSLT processors | |||
> xml parsers and xslt processors. Which one is MSXML? This is useful info for anybody: XML parser: reads the byte sequences that comprise a physical XML document, and reports on the logical structures it finds therein. The two most popular implementations produce either a stream of SAX events a la "begin element foo, begin CDATA, CDATA bar, end element foo..." or a DOM object. XSLT processor: uses information in a node tree (the stylesheet tree) to create a new node tree (the result tree), possibly drawing upon information in one or more other node trees (the source tree(s)). Most XSLT processors accept as input SAX events generated by some XML parsers, and some accept DOM objects that may be generated by other XML parsers or created from scratch. The SAX events or DOM objects are used as the basis for the node trees that follow the XPath/XSLT data model. Some XSLT processors are bundled with XML parsers and provided as standalone applications (Instant Saxon, standalone XT are examples). Others are toolkits that application developers can utilize and integrate into their own software (Saxon, XT, etc). MSXML is one such toolkit that provides both an XML parser and an XSL processor in one Windows DLL. IE 5.0 is an application that utilizes MSXML to handle the processing of XML documents that have been associated with a stylesheet by means of a processing instruction in the XML. The version of MSXML that ships with IE 5.0 is based on and doesn't fully implement an very obsolete working draft of the XSL spec, before XSL was split into XSLT, XSLFO, and XPath. This is the source of much confusion among people new to XSLT. | ||||
4. | What does an XSLT stylesheet do? | |||
With an XSLT stylesheet, you direct an XSLT processor to create a logical, abstract, DOM-like tree of data (the result tree). During the construction of this tree, you have access to another tree (the source tree) that was derived from a parsed XML document. A typical XSLT processor will accept an unparsed XML document to be used for the source tree, and an unparsed XML/XSLT document for the stylesheet. The processor then invokes an XML parser to derive the source and stylesheet trees. Then, it processes the root node of the source tree, using the best matching template in the stylesheet tree (or a built-in template). Instructions in the stylesheet templates direct the processor to visit other nodes in the source tree, and create new nodes in the result tree. After the result tree is completed, it is typically emitted in some fashion. You can usually serialize it as a string of characters (Unicode, if passing directly to another application, or encoded as bytes, if writing to a stream) in either
Sometimes you can emit it as a DOM object or a series of SAX events. If you choose XML output, and have not used disable-output-escaping, the serialized result will be well-formed, always. Whether or not the result is valid according to some DTD or schema depends upon your stylesheet! You have total control, through your stylesheet, of the logical contents of the output, which is what validation is concerned with. | ||||
5. | Parser vs XSLT processors | |||
XSL is an effort to develop a standard for the presentation of XML. Early on its development, it was decided that this process involved two stages - Transformation and then Formatting. The transformation specification was finished first, and was found to have uses beyond its original purpose - it could be used transform XML to generate HTML or a different form of XML, and constitutes a good general purpose XML transformation system. This is XSLT, which is what most people mean when they say "XSL". The latter process, formatting, is still being developed, and is often referred to as XSL:FO (Formatting Objects), to distinguish it from XSLT. A parser is a tool to help an application read an XML file. An XSLT processor is a tool which performs XSL transformations. As it happens, this processor is likely to use a parser, to read the source XML and the XSLT. Mike Kay adds W3C uses XSL to mean the as-yet-unfinished family of standards of which XSLT is part. Microsoft uses XSL to mean the language they implemented in IE5, which is related to an early draft of XSLT. An XML processor (popularly called a parser, but called a processor in the XML Recommendation) reads a source XML file and identifies the syntactic units such as elements, attributes, and text content. An XSLT processor takes a stylesheet and applies it to the tree representation of a source XML document (produced by an XML parser), and generates a tree representation of an output XML document. Wendell Piez adds Mike Kay has already stated quite succinctly what "XSL vs. XSLT" is. To what he says about processors vs. parsers, I'd like to add an interpretation An "XML processor" is a software program that does something with XML documents. These documents may be input to the program either as static entities in the notation described in the XML Recommendation (that is, files using tags following the XML definition of "well-formed"), or more generally, as "documents" constructed through some other method (for example, presented by some other application as a pre-built DOM tree, or fired as a series of SAX events). Accordingly, the term "XML Processor" is somewhat loose with respect to its input, and wide open with respect to its operations or output. An XSLT processor is a species of XML processor that can take as input, both arbitrary XML documents, and stylesheets ("transformation specifications") as described in the XSLT Recommendation, and perform operations on them also as described in the Rec. Since XSLT is a transformation language, this usually means turning one kind of XML document into another kind of (structured) output. An "XML parser" is a class of XML processor whose job it is to interpret the *notation* described in the XML Rec, and present the information in a document (the Rec describes what is a "document") in some way to a processor. (The notation indicates what, in a document, is an element, and element type name, an attribute, an attribute value, etc.) The XML Rec describes this operation as occurring in two stages, the second of which is optional: one, in which a well-formed document is simply presented, the second, in which it is first validated against a formal model in DTD syntax (also described in the XML Rec). Since, in doing its job, the parser is compelled by the specification to recognize some kinds of input as XML (conforming to the rules of the notation), and others not, and further to recognize documents as being valid to a given model (DTD), it is natural for it to create, as output, error messages, instead of the hoped-for result, a "parsed document" (whatever that may be, it depends on the parser). Accordingly, a parser may be used to check whether something is (a) actually XML ("well-formed"), and (b) valid to a given DTD (according to the XML definition of "valid"). Sometimes this error-reporting has been taken to be the main function of a parser, which is not the case. But it is very useful in this role, even on a stand-alone basis (that is, parsing is the only operation performed, essentially as a test of the input document). The XML Rec describes the syntax (i.e. the notations) both for documents and for DTDs. But what it says about the data model implied by these notations is not very formal or complete: much has been left up to applications to determine. Consequently, there is quite a bit of play in how any XML processor does its job, or even in the kind of information that's presented by an XML parser (remember the parser's job is to go from notation to data model), or the manner of its presentation (in-memory tree, series of events, stack of punchcards). While this poses problems for interoperability of tools, it may be a medium-term benefit, encouraging experiments and allowing Darwin to do his thing. (After all, we always have the notation to fall back on.) XSLT processors are sometimes built so they may accept input in different forms. However, since the XML notation is normative, but an XML data model or "Infoset" is not, the usual case is for an XSLT processor to be wired to a parser to accept XML files using that notation, as input. The parser becomes a component of the processor. XSLT processors usually come with their own parser, but many allow you to switch that parser out for some other one (that provides the application with the same input). Because of the nature of XSLT transformations, which operate on a tree-like data model described in the XPath spec, the inputs and outputs take the form of one or another kind of representation of a tree. Since these trees often start and end life as documents in XML notation, we can think we're changing tags in those documents, but we're not: what XSLT is doing goes deeper than that, the tags being only a way of representing underlying data structures. A whole class of misunderstandings about the way XSLT stylesheets are best written stems from this misconception. Perhaps the real savants on this list will weigh in if I've misstated anything. Note that this take on it differs from what Andrew Watt said on this list (an XML processor and XML parser are "one and the same"). I am making a distinction between them, related to a distinction I am making between software that does something with XML-the-notation (a processor which must be or contain a parser), and software that does something with XML-a-data-model (a processor which does not necessarily have a parser, like an XSLT processor, though it may sit downstream from one). | ||||
6. | The XSLT processing model, some questions answered. | |||
1- Is XSL protocol independent? Yes, it is protocol-independent. XSLT has its own processing model; in order to process an XSLT document you need a dedicated XSLT processing engine (XT, Saxon, MSXML, etc) 2- Reference from one element to any other element in the resided document or outside of it. I mean, if IDREF(s) supports in XSL so you can refer to some element from a certain element, provided that the IDREF is defined in the DTD file? XSLT supports ID/IDREF attribute types via XPath functions. However, because ID/IDREF attribute types are rather limited, XSLT offers a more powerful solution called keys. Keys establish a relationship between nodes that pass a certain test (string-value equivalency) and some other nodes that are usually found using a relative path from the matching nodes. Keys can be used in any source tree, but only in one tree at a time. You do have access to other source trees by using the document() function, which is specific to XSLT. 3 - Structural preservation: How is an input xml document treated by xsl. XSLT treats the input document as a node tree that follows the XPath model. This model is similar to that implied by the DOM, but it does have some differences (mainly related to attribute nodes). 4 - XSL is a tree -to- tree query and transformation language, but, is it as an ordered -or unordered tree, both the input and output xml document treats by XSL? If I understand the question, ordered. The input document(s) imply source trees that follow the XPath data model, which prescribes ordering for most types of nodes (but not namespace nodes or attribute nodes). With XSLT you create a new tree, the result tree. This tree also follows the XPath data model, with some minor additions for certain XSLT specific situations (disable-output-escaping attributes, for example). The parts of the tree that are ordered will be in whatever order your stylesheet said to create them in. 5 - Do node ID remain the same while they parsed by processors? If you are talking about ID-type attributes on elements, they are not treated specially, except that extra access is given to them via certain XPath functions. If you are talking about the internal ID string generated for every node (of any type) in a source tree, this is specific to XSLT processors and may vary from run to run. You generally only use these IDs to test that the same node exists in 2 different sets; the ID itself doesn't matter. 6 - Does XSL preserve the same documental structure for the input XML document and maintain the same order or structure in the output file? If you are doing an identity transform, sure, but I think your question is exactly why the word 'transformation' is a misnomer when applied to XSLT. XSLT is about creating a node tree. During the creation process you have access to 1 or more node trees that were typically derived from input XML documents. How you go about creating the tree is your own business; it does not have to have any relationship to the source tree(s) at all. At the end of the process, some kind of serialized output may be derived from your result tree automatically. 7- Universal and existential quantifiers "If one or all nodes in a certain collection fulfil some condition, as found in SQL": Is this available in XSLT? Yes, within an XPath expression you can use predicates: /path/to/somenodes[ foo ] will evaluate to only those somenodes for which 'foo' is true. document('otherdoc.xml')/otherdoc/stuff[ . = 'hello' ] will be 'stuff' elements that have a string-value of 'hello' and that are children of 'otherdoc' elements which, in turn, are children of the root node in the tree derived from otherdoc.xml 8- Does XSL have support for infinite or finite definition, that is to say, if an infinite loop may appear in the XSL structure or not?. You can define whatever you want, but you cannot reference or process something that has an infinite definition. The XSLT processor will run out of memory. For example, you can have this in your stylesheet: <xsl:variable name="infinite_result_tree_fragment"> <xsl:call-template name="add_to_fragment"/> </xsl:variable> ... <xsl:template name="add_to_fragment"> <data>hello world</data> <xsl:call-template name="add_to_fragment"/> </xsl:template> but if you ever get to a point during processing where you process the xsl:variable assignment, you will go into infinite recursion. So the answer to your question is no. 9- What about the Null values, how xsl works or behaves in relation to it? The data types in XPath are: number, string, boolean, node-set The data type added by XSLT 1.0 is: result tree fragment (it is a node-set in a different context) number: can be an IEEE 754 number, but not null. string: can be an empty string, but not null. boolean: can only be true or false, not null. node-set: can be empty (no nodes in the set), but not null. result tree fragment: can be empty (no nodes in the set), but not null. So there is no concept of "null" per se. You either have an object of one of those types, or you don't. It is an error if you reference an object that is not defined. This will not work, if foo hasn't been defined... <xsl:if test="not($foo)"> But this will... <xsl:variable name="foo" select="''"/> <!-- empty string --> <xsl:if test="not($foo)"> ... The test will be true if foo is an empty string, empty node-set, number 0, or boolean false. | ||||
7. | Debugging tips | |||
There are several possible default template rules you can use when matching unknown elements. The one that's built-in is <xsl:template match="*"> <xsl:apply-templates/> </xsl:template> This is quite useful when you're rendering document-oriented XML, because it means "when you find an unknown element, ignore the tags and process the content as if the tags were not there." If the element is intended to switch on Ukrainian hyphenation rules, and you don't know how to do that, then it's best to ignore the element but not to ignore its content. Another useful rule is: <xsl:template match="*"> <xsl:copy> <xsl:copy-of select="@*"/> <xsl:apply-templates/> </xsl:copy> </xsl:template> This is called the identity template, and its effect is to copy any unknown element from the source to the result - while still applying template rules to its content. This is probably the one that you are most likely to want if the source vocabulary and result vocabulary are the same. Another one that you might see is: <xsl:template match="*"> <xsl:message>Unknown element <xsl:value-of select="name()"/></xsl:message> </xsl:template> This is useful if you intended to write template rules for all possible elements, and you want to treat any other element as an error. You sometimes see: <xsl:template match="*"> <xsl:copy-of select="*"/> </xsl:template> This copies unknown elements unconditionally to the result tree. It's less flexible than the identity template, because you can't do any further processing on the content of this element. Occasionally you might want: <xsl:template match="*"/> which means that if there's an unknown element in the source tree, you want to exclude not only that element, but all its content, from the result tree. The answer to the question, why is the first one above the built-in default, is that the WG probably thought that rendition of document-oriented XML was the most common application area for XSLT. But don't be afraid to declare a different default that suits your application better. | ||||
8. | Template selection | |||
The actual rules run something like this. To determine which template is applied when a node is selected, all matching templates are considered. When more than one template matches: 1. The one with highest "import precedence" is selected (Import precedence is determined by your import hierarchy when you use xsl:import to bring in stylesheet modules, enabling you to override imported templates transparently in an importing stylesheet. If you want modularity without this behavior, use xsl:include.) 2. If two or more templates have the same import precedence, then each candidate template is assigned a priority as follows, and the one with the highest priority is used: 2a. If an explicit priority is given, this is the priority assigned. 2b. If no explicit priority is given, priority is assigned as follows: match with just a node test by name - priority is 0 (e.g. match="div" or match="@type") match with a node test only by type - priority is -0.5 (e.g. match="*" or match="comment()") match with a node test by type, except namespace-qualified - priority is -0.25 (e.g. match="html:*") anything else - priority 0.5 (e.g. match="div/p" or match="p[not(preceding-sibling::*)]" or match="//div") Matches on either side of a "|" operator are considered separately, so if you have match="div/div | p" the priority will be 0.5 or 0 depending on whether it's a div or a p that's doing the matching. As you can see, this provides for a rough, but not too super-complicated, assignment of higher priority to "better matches". (Early drafts of XSL had more complex methods but this is what they settled on.) But it's not enough to help you pick between "div/div" and "div/div/div" when you have a div that matches both. Those are cases where you have to provide a priority explicitly. (NB: match="div" and match="//div" both match the same nodes, but with different priorities, 0 and 0.5 respectively. It's because of this that we frown on match="//div" since this is almost always unintentional but almost never useful.) All this is described in the XSLT Rec, at http://www.w3.org/TR/xslt#conflict "5.5 Conflict Resolution for Template Rules" Now, you ask, okay, what if priority is assigned and I still have a conflict? In that case, the behavior depends on your implementation. (It's one of relatively few occasions where implementations are allowed to differ.) One reason many of us like Saxon for development is that Saxon will signal a warning before it uses the last best template. MSXML simply uses that one. Other processors signal an error. YMMV. When teaching this stuff, I always recommend to students that they test their processor on this so they know what to expect. | ||||
9. | If then else? | |||
In XSLT there are only two routing statements, xsl:if and xsl:choose. The former is a simple equivalent of the classic if. There is no extension to allow elseif! <xsl:if test="child"> Truth case </xsl:if> The example above tests if the current node has a child named 'child' and executes the instructions within the 'if' statement if this child exists. See W3C for the detail The second statement is xsl:choose, which allows alternatives. <xsl:choose> <xsl:when test="@val = 1"> Action when attribute is 1 </xsl:when> <xsl:when test="@val=2"> Action when attribute is 2 </xsl:when> <xsl:otherwise> Action when attribute is other than 1 or 2 </xsl:otherwise> </xsl:choose> This example shows how the xsl:choose statement works, selecting the first boolean true test and actioning the enclosed statements. Again see W3C for the detail |