Transforming an XML document using XSLT. What does XML look like in a browser? XSLT Transformation Language

Converting XML data format using Extensible Stylesheet Language Transformations (XSLT)

Before starting work

This tutorial is designed for developers who want to use XSLT to transform XML data into other forms without having to program in Java™ or other languages.

This tutorial assumes you are familiar with XML, but the author doesn't go into any of the language's arcane intricacies, so a basic understanding is sufficient. With the exception of a small section about extensions, you don't need to have any special programming language behind you. And even in this section, the ideas are very simple and applicable to any programming language that is supported by the processor.

What is this guide about?

This tutorial is about Extensible Style Sheet Language (XSLT) transformations. XSLT is one of the core specifications associated with XML, allowing XML data to be easily translated from one form to another.

In this guide you will learn:

  • XSLT Basics
  • Using Simple Templates
  • Publication of data
  • Managing whitespace
  • XPath Basics
  • XPath functions
  • Loops and Conditional Statements
  • Importing and Including Other Style Sheets
  • XSLT extension
  • XSLT Variables

Beginning of work

Imagine for a moment that you have a data set in XML. You may have chosen to store them this way because of the flexibility of XML. You know you'll be able to use them across multiple platforms and with virtually any programming language. But sometimes you will have to change the form of your XML. For example, you may need to translate data into a different XML format to store it in a different system, or a different form for presentation, or something else.

For example, you might have data in XML that you want to publish on the web, which means translating it into HTML. Of course, you could manually view the document and do in it necessary changes, or maybe you've thought about loading the XML into the DOM and then manually creating the output document.

What is XSLT?

Extensible Style Sheet Language Transformations (XSLT) provide a way to automatic translation XML data from one form to another. The target form is usually another XML document, but does not have to be; you can transform XML into almost anything by simply creating an XSLT stylesheet and processing the data. If you want to change the results, you simply change the stylesheet and re-process the XML. There is additional benefit, which empowers non-programmers such as designers to modify the style sheet and influence the results.

Let's see an example.

Task

In this tutorial, we'll take an XML document and transform it into an XHTML document that can be displayed as a Web page. The input is simply a recipe file (see Listing 1).

Listing 1. Basic data
Gush"gosh 1pound hamburger 1pound elbow macaroni 2cups brown sugar 1bag chopped onions 1teaspoon dried dill Brown the hamburger. Add onions and cook until transparent. Add brown sugar and dill. Cook and drain pasta. Combine meat and pasta. A balanced breakfast 1cup cereal 1glass orange juice 1cup milk 2slices toast Combine cereal and milk in bowl. Add all ingredients to table.

Editor's Note: These recipes are given simply as an example, as the author imagines them. The right recipe for Gush'gosh (received from his wife, who prepares this dish) consists of 1 pound (0.454 kg) minced beef, 1 pound horns, 1/2 cup yellow sugar, 1 small package (about 300 grams) finely chopped onion, 1 teaspoon dried dill and 1 small can of tomato paste, to which yellow sugar is added.

Of course, this is a very simple example so you won't get bogged down in the details of the data itself, but you can represent anything from a logging process to finances as XML data.

Our goal is to convert this data into an XHTML page that will display the recipes individually and format their ingredients and cooking instructions (see Listing 2).

Listing 2. Result
Recipe

Gush"gosh

Ingredients:

1 pound hamburger
1 pound elbow macaroni
2 cups brown sugar
1 bag chopped onions
1 teaspoon dried dill

Directions:

  1. Brown the hamburger.
  2. Add brown sugar and dill.
  3. Cook and drain pasta.
  4. Combine meat and pasta.

A balanced breakfast

Ingredients:

1 cup cereal
1 glass orange juice
1 cup milk
2 slices toast

Directions:

  1. Add all ingredients to table.

You can display this result in the browser as shown in Figure 1.

Figure 1. Result displayed in the browser

As mentioned, the end goal could be any format, not just XHTML, and not even necessarily XML.

Let's start with simple transformations.

Simple style sheet

The simplest style sheet is simply an XML document that includes XSLT output (see Listing 3).

Listing 3. The simplest style sheet
Recipe

Ingredients:

Directions:

Note the use of the xsl namespace. Adding this namespace tells the processor which elements are associated with processing and which should simply be output. Value-of elements tell the processor to insert specific data at that location. What data to insert is determined by the contents of the select attribute.

The select attribute consists of an XPath expression. XPath will be discussed in more detail in the section, but here you can see that the title, ingredients, and cooking instructions elements are accessed through the document hierarchy. We start at the root element, /recipes , and work our way down from there.

How to convert

The simplest way to perform XML transformation is to add a stylesheet hint to the XML and display it in the browser (see Listing 4).

Listing 4. Adding to XML instructions on processing using a style sheet
Gush"gosh ...

This processing instruction tells the browser to retrieve the style sheet located in basicstylesheet.xsl and use it to transform the XML data and output the results. If you open our XML document in Microsoft browser® Internet Explorer®, you will see a result similar to Figure 2.

Figure 2. Extracting the style sheet and transforming the XML data

However, this is not exactly what we wanted. If you select View>View HTML Code in your browser, you will see the original XML. To see the result of the conversion, you must perform the conversion and create an output file. This can be done via the command line using Java code with next command(see Listing 5):

Listing 5. Converting a document via the command line
java org.apache.xalan.xslt.Process -IN recipes.xml -XSL basicstylesheet.xsl -out result.html

If you receive a ClassNotFoundException , you may need to download Apache Xalan (see "Get Products and Technologies" in the section) and add the JAR files it includes to the classpath.

After performing the transformation shown in Listing 5, you will see that the result.html file contains the following code (see Listing 6).

Listing 6. Results
Recipe

Gush"gosh

Ingredients:

1poundhamburger 1poundelbow macaroni 2cupsbrown sugar 1bagchopped onions 1teaspoondried dill

Directions:

Brown the hamburger.

I've added some spacing for ease of reading, but there are a couple of things to note here. First, it only displays information for one recipe. Secondly, the ingredients are cobbled together without any gaps. This is also not the result we wanted to get. Luckily, you can create more precise templates to display your data exactly the way you want it.

Adding templates

A transformation is of no use if it does not bring the data into exactly the form we need. To do this, you need to be able to use templates, which is what this section is devoted to.

Creating Templates

Most style sheets don't have the simple form you just saw in the previous section. Instead, they are broken down into a group of patterns, each of which applies to a specific data type. Let's translate our style sheet into this form (see Listing 7).

Listing 7. Redesigned style sheet
Recipe

Ingredients:

Directions:

The information here is unchanged, except that the processor looks at the style sheet and starts with the pattern that matches the document's root element, as specified by the match attribute. It then outputs this template, including all the values, just like before. If you perform the conversion now, you should see exactly the same results as in .

But that's not what we want. We want to be able to format ingredients and instructions. To do this, we can create separate templates for each of these elements and include them in the style sheet (see Listing 8).

Listing 8. Creating additional templates
Recipe

Ingredients:

Directions:

INGREDIENTS HERE

INSTRUCTIONS HERE

Notice that instead of simply rendering the value-of element, we now tell the stylesheet to apply appropriate templates to the ingredients and instructions elements. We then created separate templates for these elements by setting them in the match attribute. Once it reaches the apply-templates element, the processor selects all ingredients elements in the document. It then looks for a pattern for the ingredients, and when it finds one, it outputs that pattern. It does the same thing with the instructions element. The result should be similar to that shown in Figure 3.

Figure 3. Applying the appropriate templates to the ingredients and instructions elements

Okay, this is a little closer, at least it's clear that there are two recipes, but you probably don't want to combine the ingredients and instructions for all the recipes. Fortunately, this problem can be solved the best organization templates

Publishing templates

To better organize your data, let's take a look at how we separate and publish templates. XSLT allows you to process information in an iterative manner. For example, you can divide the information into individual recipes and then format the instructions and ingredients (see Listing 9).

Listing 9. Highlighting recipes
Recipe

Ingredients:

Directions:

INGREDIENTS HERE

INSTRUCTIONS HERE

IN in this case The stylesheet renders the main page (HTML) and then goes through each recipe, displaying the name, ingredients, and instructions for each recipe. Again, we'll study XPath in the section, but in this case the recipe element becomes a context node, so the select attributes relate to this node in the same way that files relate to a specific directory in the file system. The result should be similar to Figure 4.

Figure 4. The recipe element becomes a context node

Great, the format is close to what we want, but we still need to display the actual information. To do this, you need to change the ingredients and instructions templates (see Listing 10).

Listing 10. Working on the ingredients and instructions templates
...

Ingredients:

Directions:


  • An important point when publishing templates: you've told the processor to apply appropriate templates to the ingredients element, but we don't have a specific template for that element. If you apply a template to an element, but there is no template itself, the data simply will not appear. But this is not our case.

    Instead, we take advantage of the fact that when we tell the processor to apply suitable patterns to the ingredients element, it looks not only for the ingredients element, but also for the child elements of the ingredients element. So it finds a template for ingredients where you output the quantity, units, product name and line break.

    We did the same for instructions when we formatted them as list items. Notice that we created an actual ordered list in the main template for the recipe and then submitted the items for individual processing.

    The result should be similar to Figure 5.

    Figure 5: Creating an ordered list in the main recipe template

    The format is definitely getting closer to what we wanted. However, if you look at the output, you'll see that the whitespace issue still exists (see Listing 11).

    Listing 11. Unfinished output
    Recipe

    Gush"gosh

    Ingredients:

    1poundhamburger
    1pound bow macaroni
    2cups brown sugar
    1bagchopped onions
    1teaspoondried dill

    Directions:

    1. Brown the hamburger.
    2. Add onions and cook until transparent.
    3. ...

      Adding spaces

      Why did this happen if we included spaces in the stylesheet? Should they have appeared in the output? Of course not necessary. There are ways to tell a stylesheet to leave white space - we'll look at these in the Looping and Importing section - but in some cases it's easier to explicitly add text to the output (see Listing 12).

      Listing 12. Adding text
      ...
      ...

      Thus, we took care of the missing spaces. In the same way, using the text element, you can add any arbitrary text to the template. (Remember, this is just text, not page break type elements.) The result will be the output we want (see Listing 13).

      Listing 13. Final output
      Recipe

      Gush"gosh

      Ingredients:

      1 pound hamburger
      1 pound elbow macaroni
      2 cups brown sugar
      1 bag chopped onions
      1 teaspoon dried dill

      Directions:

      1. Brown the hamburger.
      2. Add onions and cook until transparent.
      3. Add brown sugar and dill.
      4. Cook and drain pasta.
      5. Combine meat and pasta.

      A balanced breakfast

      Ingredients:

      1 cup cereal
      1 glass orange juice
      1 cup milk
      2 slices toast

      Directions:

      1. Combine cereal and milk in bowl.
      2. Add all ingredients to table.

      The result is shown in Figure 6.

      Figure 6. Missing spaces problem solved

      XPath Basics

      The ability to transform data into the form you want it to be in requires an understanding of the XML Route Language, or XPath, which allows you to control what data is published and/or displayed. This section explains basic XPath concepts and shows how to create simple expressions.

      What is XPath?

      You may have noticed that an important part of how a style sheet works is the ability to select a specific part of a document. For example, if you want to display instructions, you need to know how to reference them. In XSLT, we refer to information using XPath expressions.

      An XPath expression can select a single node or a set of nodes, or return a single value based on one or more nodes in the document. So far we've dealt with very simple XPath expressions that select a node or nodes going down a hierarchical structure. XPath provides several ways to define groups of nodes based on relationships, such as parent-child or ancestor-child. In this tutorial, we'll explore all of these relationships, called axes.

      You'll also learn about some of XPath's more powerful features and predicates are basically conditional statements that can be added to expressions. For example, in the Setting Context section, you'll see how to select all recipe elements in a document; predicates allow you to select only a specific element based on specific criteria.

      Finally, you'll learn about even more powerful functions that enable you to use many of the types of logic that are used in procedural programs.

      Let's start by examining the context of the expression.

      Setting up the context

      The first step in understanding XPath is to understand that the results obtained are largely determined by the current context node. A context node can be thought of as a kind of "you are here" sign, from which you can move in different directions according to the XPath expression. For example, consider a simple table styles in Listing 14.

      Listing 14. Context demonstration

      There is a new element here - copy-of. Where value-of outputs the contents of an element, copy-of does exactly what its name says and outputs the actual node that the select attribute refers to.

      In this case, the select attribute contains one of the simplest possible XPath expressions. A single dot (.) is a reference to a given context node, as in a file system when you want to refer to "the current directory, regardless of what the directory is." So if you do this conversion, you'll get a result like Listing 15.

      Listing 15. Simplest conversion
      Gush"gosh 1pound hamburger 1pound elbow macaroni 2cups brown sugar 1bag chopped onions 1teaspoon dried dill Brown the hamburger. Add onions and cook until transparent. Add brown sugar and dill. Cook and drain pasta. Combine meat and pasta. ...

      You see that this is simply a repetition of the same document; this is because the context node, as indicated by the match template attribute, is the document root, or /. If you change the context node, the output will change. For example, you could set the context node to the first recipe (see Listing 16).

      Listing 16. Moving a context node

      Now, when you run the conversion, you'll see the difference (see Listing 17).

      Listing 17. Results
      Gush"gosh 1pound hamburger 1pound elbow macaroni 2cups brown sugar 1bag chopped onions 1teaspoon dried dill Brown the hamburger. Add onions and cook until transparent. Add brown sugar and dill. Cook and drain pasta. Combine meat and pasta. A balanced breakfast 1cup cereal 1glass orange juice 1cup milk 2slices toast Combine cereal and milk in bowl. Add all ingredients to table.

      Since we moved the context node, the output changed. This is important when you want to select a node relative to a context node. For example, you can select only the title of the recipe (see Listing 18).

      Listing 18. Selecting only the header

      Here, you're selecting a name element one level below the current context node, so the result will be like Listing 19.

      Listing 19. Results
      Gush"gosh A balanced breakfast

      We'll explore specifying nodes by number later, but for now note that we can move the context node into the second recipe (see Listing 20).

      Listing 20. Moving the context node again

      (Ignore the other template, it's there to prevent other recipe text from appearing.)

      We can see that the resulting transformation shows this change in context (see Listing 21).

      Listing 21. Results
      A balanced breakfast

      What are axes for?

      Now that we know where we're starting from, it would be helpful to know where we can go. So far we have used very simple XPath expressions, similar to hierarchy in a file system, but XPath provides much more functionality. For example, so far you have only selected children, but you can also search for the parents of a particular node, as well as its children or ancestors.

      First, let's talk about the notation system. We used a simplified, shortened form of requesting descendants. In "long form" expressions are given as child::name instead of ./name

      In both cases, you specify any node that is a child of the context node and is also a name element. You can also link them together as in the previous case, using /child::recipes/child::recipe instead of /recipes/recipe .

      Descendants

      You may be wondering why bother with the long form when the short form is so much easier. This wouldn't be necessary if the only thing you could do was select descendants. However, this notation can also be used to select other relationships. For example, the XPath expression descendant::instruction selects all instruction elements that are descendants of the context node, not just child elements. In addition, you can combine instructions. For example, you can select all the instructions of the second recipe: /recipes/recipe/descendant::instruction .

      One variation of the child axis is the child-or-item-itself axis, which selects a given node from all children and also searches the context node itself. For example, the expression descendant-or-self::instructions selects all instruction nodes in and below the context node. The usual abbreviation for this axis is the double slash, //. This means that the expressions: /recipes/recipe//instructions and //instructions select all instructions for the second recipe and all instructions in the document, respectively. This second example is very widely used and is useful when you just want to select all elements of a certain type in a document.

      Attributes

      Another common task you will encounter is the need to select an attribute for a specific element. For example, you might want to select a recipeId for a specific recipe. The expression /recipes/recipe/attribute::recipeId selects the recipeId attribute for all recipe elements. This axis also has an abbreviated form: the same expression can be written as follows: /recipes/recipe/@recipeId .

      Parents

      Everything we saw before transported us down along the hierarchy tree, but it is also possible to go up by selecting the ancestor of a particular node. Let's assume that the context node was one of the instructions, and you want to display the recipeId for the current recipe. You can do it like this: ./parent::node()/parent::node()/@recipeId .

      This expression starts at the current instruction node, and then moves to that node's ancestor, the instructions element, and then to THAT element's ancestor, recipe, and then to the corresponding attribute. You may be more familiar with the shortened form: ./../../@recipeId .

      Now let's see how some conditions are set.

      More advanced XPath features

      In most cases, the techniques already discussed are sufficient. However, there are often situations that require greater selectivity. This section shows how to use predicates to select nodes based on specific criteria and introduces some of the features built into XPath.

      Using Predicates

      Often what is required is not just any node, but a specific node selected based on specific conditions. You've seen an example before where you used the expression /recipes/recipe//instructions. This is actually a shorthand version of /recipes/recipe//instructions , which means that the XPath processor must go through every recipes element (there is only one such element, of course) and for every recipes element, go through every recipe element. For each recipe element, check if the expression position() = 2 is true. (In other words, is this second recipe in the list?) If this sentence, called a predicate, is true, then the processor uses that node and continues, returning any instructions.

      There are many things you can do with predicates. For example, you can only return recipes that have the name: /recipes/recipe . This expression simply tests whether a name element exists that is a child of the recipe element. You can also search for specific values. For example, you can only return items that are named "A balanced breakfast": //recipe .

      Keep in mind that the predicate simply tells the processor whether to return the current node, so in this case the recipe element is returned, not the name. Alternatively, you can tell the processor to return only the name of the first recipe using either of these two expressions (see Listing 22).

      Listing 22. Returning only the name of the first recipe
      //recipe[@recipeId="1"]/name //name]

      In the first expression, we first select all recipe elements and then return only the one that has the recipeId element attribute equal to 1. Once we find that node, we move to its child node, which is called name, and return it. The second expression first searches for all name elements, and then selects only the one whose parent has an attribute of 1. Either way, you get the same output (see Listing 23).

      Listing 23. Output
      Gush"gosh

      Functions

      XPath also provides a number of functions. Some of them deal with nodes themselves, such as those that look for a specific position, some handle strings, some, like summation, with numbers, some with booleans.

      Node related functions

      Node-related functions help, for example, to select a specific node depending on its position. For example, you can specifically request the latest recipe: //recipe. This expression selects all recipe elements and then returns only the last one. You can also use functions separately instead of using them as part of a predicate. For example, you can specifically request to count the elements of a recipe: count(//recipe) .

      You've already seen the position() function and how it works. Other node-related functions include id() , local-name() , namespace-uri() and name() .

      String functions

      Most string functions are designed to process strings rather than test them, with the exception of the contains() function. The contains() function shows whether given line part of a larger whole. This will allow, for example, to return only nodes containing certain strings such as: //recipe.

      This expression returns a recipe element that contains the string "breakfast" in its name element.

      The substring() function allows you to select a specific range of characters from a string. For example, the expression: substring(//recipe/name, 1, 5) returns A bal .

      The first argument is the full string, the second is the position of the first character, and the third is the length of the range.

      Other string functions include concat() , substring-before() , substring-after() , starts-with() , and string-length() .

      Numeric functions

      Numeric functions include a number() function, which converts a value to a numeric value so that other functions can operate on it. Numeric functions also include: sum() , floor() , ceiling() and round() . For example, you can find the sum of all recipeId values ​​using the expression: sum(//recipe/@recipeId) .

      Of course, there is no special reason to carry out such a calculation, but it is simple numeric value, given as an example.

      The floor() function finds the largest integer that is less than or equal to the given value, and the ceiling() function finds the smallest integer that is greater than or equal to the given value. The round() function works in the traditional way - it rounds (see Listing 24).

      Listing 24. Results of numeric functions
      floor(42.7) = 42 ceiling(42.7) = 43 round(42.7) = 43

      Boolean functions

      Boolean functions are most useful when working with conditional expressions, which will be discussed in the Conditional Processing section. Perhaps the most useful function is not(), which can be used to determine that a particular node does not exist. For example, //recipe returns every recipe that contains the string "breakfast" in its name element. But what if you need all the recipes except breakfast? You can use the expression: //recipe.

      Other boolean functions include true() and false(), which return constants, and boolean(), which converts a value to a boolean so it can be used as a test value.

      Cycle organization and import

      Let's look at two more important aspects of using XSLT style sheets: creating loops and importing external style sheets.

      Organizing cycles

      When working with XSLT, you need to get used to the fact that it is a functional language, not a procedural one. In other words, you usually have no explicit control over the way it carries out the instructions given to it. However, there are exceptions. For example, it is possible to organize loops and perform conditional operations. Let's start with cycles.

      In the previous example, we used XSLT expressions built into the publication template to apply styling to specific elements. In some cases this works great. However, in situations where you have complex XML files or complex requirements, it is sometimes easier to access the information explicitly (see Listing 25).

      Listing 25. Direct Application styles using loops

      Ingredients:


      Directions:

      The loop structure is very similar to the for-each structure for which it is named. Like its namesake, each loop instance carries the next value of the list. In Java programming, this could be the next value in an array; here it is the next node in the collection of nodes returned by the XPath expression in the select attribute. This means that when you first execute the first loop, the context node is the first ingredient element. This allows you to select the qty, unit and food descendants of this element and add them to the document in the same way as you did earlier using the template. It's the same with instructions, except they're just output directly.

      The results are identical to those obtained when publishing through templates - almost. Each pattern is added to the document as an individual line, but since we need to process this information as one pattern, we lose a lot of the white space we saw before (see Figure 7).

      Figure 7. Results

      For some XML applications this matters, but here we are using HTML so it doesn't matter. However, keep this in mind when deciding which method to use.

      Enabling and importing style sheets

      Another variation of style sheets concerns their structure. Until now, all of our information was stored in a single style sheet. However, in some cases it may be useful to break it up into separate style sheets. This modularity can make it easier to maintain, as well as the flexibility to allow different style sheets to be used for different purposes. For example, we could create two different style sheets, one of which will be used for ingredients (see Listing 26).

      Listing 26. Ingredients.xsl file

      You can also create a separate style sheet for instructions (see Listing 27).

      Listing 27. Instructions.xsl file
    4. These templates are identical to the templates from the current style sheet. They can be added to the stylesheet through inclusion (see Listing 28).

      Listing 28. Including style sheets
      ...

      Ingredients:

      Directions:

      Although we have placed the stylesheets in the same directory as the main stylesheet here, it is not necessary to do so: the href attribute can contain any available URL. Note that we are sending the processor to look for templates for the ingredients and instructions elements, which are not in this file. However, if you process the style sheet, the result is exactly the same as if the templates were included directly, rather than through the include element (see Figure 8).

      Figure 8. Results

      The include element produces the same result as if we had added content starting at that point. Semantically they are identical. On the other hand, there is another way to include information - import.

      XSLT allows you to import a style sheet at the beginning of a file. Why to the beginning? Because the purpose of importing a style sheet is to be able to adjust any templates that are part of the import. For example, we can import the ingredients template and customize it (see Listing 29).

      Listing 29. Importing a style sheet
      ... ...
    5. Here we've actually replaced one template with two, which replace the templates in the imported stylesheet (see Figure 9).

      Figure 9. Results

      Note that since hierarchy depends on location, the same result could be achieved using inclusion. However, XSLT allows you to use the priority attribute to specify the priority of templates when processing imports.

      XSLT extension

      We've seen how to make XSLT more like programming. How about adding actual programming to it? Let's take a look at adding Java functionality to an XSLT stylesheet.

      First, it should be noted that although the extension mechanism is part of the XSLT recommendations, the implementation discussed here is specific to the Xalan XSLT processor. The basic ideas are pretty much the same for other processors, but you'll have to check the documentation for details.

      Expansion elements

      Extending XSLT is done using various techniques. The first is the use of extension elements. The extension element is an element in a namespace that points to a Java class. For example, take a look at the following extension element (see Listing 30).

      Listing 30. Using the extension element
      Recipes ...

      We have created a namespace that corresponds to the comp.backstop.RecipeScaler class, which includes static method called scaleMessage (see Listing 31).

      Listing 31. RecipeScaler class
      package com.backstop;

      public class RecipeScaler ( public static String scaleMessage (org.apache.xalan.extensions.XSLProcessorContext context, org.w3c.dom.Element thisElement)( return "This recipe has been scaled by a factor of " + thisElement.getAttribute("servings" ) + "."; ) ) When the processor reaches the element, it sees the namespace prefix scaler: and knows that it is designated as the prefix of the extension element, and thus understands what class is designated in the namespace definition. The method it calls responds element - scaleMessage . The method itself receives two arguments, of which we actually use one. The context parameter refers to the processor context, which allows us to look at the elements related to the extension element, but we'll just focus on the extension element itself. Since we receive this element as a method parameter, we can extract the values ​​of any attributes added to this element, such as servings in this case. The text returned by the method is added to the output in place of the extension element.

      This means that if we apply a style sheet, we will get the results shown in Figure 10.

      Figure 10. Results of the extension element

      Extension elements can be quite useful, although they can be a little tricky to use.

      extension functions

      Another way to add functionality using style sheets is to use extension functions, which are somewhat easier to implement than extension elements. For example, we could create a function that multiplies the number of ingredients and the number of servings (see Listing 32).

      Listing 32. scaleIngredient() method
      package com.backstop;

      public class RecipeScaler ( public static String scaleMessage (org.apache.xalan.extensions.XSLProcessorContext context, org.w3c.dom.Element thisElement)( return "This recipe has been scaled by a factor of " + thisElement.getAttribute("servings" ) + "."; ) public static int scaleIngredient(int servings, int original)( return (servings * original); ) )

      Adding this function to a style sheet is identical to adding an extension element that already has a namespace map for the class (see Listing 33).
      ...
      ...

      Listing 33. Adding the extension function

      Note that the function call includes a namespace prefix. As before, the processor sees the prefix and knows to make a call to the RecipeScaler class. As a result, the number of ingredients is multiplied by two (see Figure 11).

      Figure 11. Using the extension function

      Although this code works, it is difficult to maintain. Let's look at how to make support easier.

      XSLT Programming

      XSLT Variables

      Before we wrap up, let's look at two aspects of XSLT that provide some of the same features found in regular programming languages.

      It's great that we can execute a function, but it ends up being a constant hidden deep in the style sheet. Wouldn't it be better to set the variables at the beginning of the page? Of course yes (see Listing 34).
      Recipes ...
      ...
      Listing 34. Setting a variable

      Note that the ingredients were multiplied by the number of servings, as expected. However, if you look more closely, you'll see that the extension element misbehaved, mistaking the variable for a string instead of using the value of the variable itself. This is not a glitch; the specification does not require the processor to do anything with attribute values ​​before processing the extension element. Therefore, we need to somehow avoid this problem.

      Conditional Processing

      The first thing we can do is use conditional processing so that the message is only displayed when it is needed. For example, see Listing 35.

      Listing 35. Using the if element
      Recipes ...

      The content of the if element specified by the test attribute must be true. If this is not the case, which is what happened in this case, the output will not appear at all (see Figure 13).

      Figure 13. Results of the if clause

      As written, the sentence doesn't make much sense; if the value is greater than one, the extension element will appear with the value "3." It's better to use multiple selection (see Listing 36).

      Listing 36. The choose element
      Recipes Recipes have been scaled by an invalid number. Recipes have been scaled for multiple portions. ...

      In this case we have a combination of the if-then-else elements and the case clause from traditional languages programming. The choose element acts as a container, but the when element displays its contents only if its test attribute is true. Finally, if none of the when elements are true, the processor displays the contents of the otherwise element.

      The result is as expected (see Figure 14).

      Figure 14. Result

      Now you can more flexibly set the display of a larger number of portions, or adapt to other conditions.

      Conclusion

      Summarizing

      This guide took you from an initial introduction to XSLT transformations to creating a fairly comprehensive complex tables styles. First you learned the basics of style sheets, then XPath expressions, one of the XSLT Basics. In the last part this manual We covered some of the more advanced aspects of XSLT style sheets - variables, conditional processing, and extensions. As a result, you should now have enough knowledge to do almost anything you need to do with XSLT style sheets - or at least understand what else you need to figure out if you run into a problem.

      Annotation: Discusses code generation using XSLT transformations. The XSLT syntax, features of applying transformations, as well as performing operations such as filtering, sorting, and conditional selection in templates are studied. Performing transformation programmatically in C#. Advantages and disadvantages of technology.

      XSLT Transformation Language

      In the second lecture we already looked at an example using XSLT. In this lecture we will look at this technology in more detail. XSL (eXtensible Stylesheet Language) stands for Extensible Style Language, and is a language for creating XML styles documents. XSLT(XSL Transformations) is the XSL Transformation Language and is part of it. The XSLT style is designed to transform the hierarchical structure and format of an XML document. The results of the transformation can be an XML file, text file, program code, HTML file, file in PDF format, and so on. This language provides powerful capabilities for manipulating data, information, and text in a hierarchical form.

      And this is exactly what is needed to generate code. Using XSLT can greatly help code generation. In addition, it provides a convenient alternative to T4 template technology.

      XSLT was developed by a consortium W3C (World Wide Web Consortium). The first version of the language, XSLT 1.0, became a recommendation on November 16, 1999, and XSLT 2.0 became a recommendation on January 23, 2007. Both versions are used quite actively, and in this lecture we will look at the basic functionality that is common to them. This means that we will mainly consider the first version. We will also mention some commands from the second version.

      How XSLT works

      The XSLT model includes the following parts:

      • XML documents,
      • XSLT styles,
      • XSLT processor,
      • output documents.

      XML Documents are input data that needs to be converted into other documents. Document XSLT style is a well formed XML document and contains a set of rules for performing the transformation. In other words, a style document is a template.

      XSLT Processor is an application that accepts XML documents and XSLT styles as input. It performs transformation, that is, applying a set of rules in XSLT styles to XML documents. The result of this work is output documents.

      XSLT processors have many implementations and are built into many browsers like Internet Explorer, Firefox, Mozilla, Opera and others. Internet Explorer uses the MSXML tool developed by Microsoft. XSLT processor is built into Internet Explorer starting from version 4.5. The generated output of the examples in this lecture can be viewed by opening the XML files in one of the browsers. At the end of the lecture, we will look at the possibilities of launching the transformation programmatically, using the appropriate programming language classes.

      XPath

      Another part of XSL technology is the language XPath, designed to access nodes in an XML document by specifying paths and expressions. The Xpath language is used in style files to navigate within XML documents, identifying parts of the source XML document that match one or more predefined patterns. When a match is found, the XSLT processor will apply the appropriate rules from the style file to it and transform it into part of the resulting document. XSLT style files make heavy use of XPath expressions.

      Using XSLT

      The XSLT language consists of many instructions written as tags. The name of each instruction usually begins with the characters xsl. To perform the transformation, the XSLT style document must be a valid XML document.

      To transform an XML document, you need to add a statement similar to the following at the beginning of the document:

      An XSL stylesheet typically contains many elements, the most important of which is the element xsl:stylesheet. It is he who indicates that this XML file is a style file. In addition to it, it may contain other elements, for example xsl:template, xsl:value-of. The XML document and style file are passed to the XSLT processor, which processes these files, performs the transformation and outputs the result of the transformation.

      Below is XML document, containing a list of programming languages.

      C# Visual Basic Delphi Prolog Example 5.1.

      Languages.xml file You need to output this list in HTML format. For this purpose we use the instructions xsl :for-each

      , which will apply part of the template to document sections whose names are specified in the select attribute. In our case, we will specify select="languages/language" .

      The style file that will be used is:

      -

      My favorite languages:

      Example 5.2. You need to output this list in HTML format. For this purpose we use the instructions File languages.xsl xsl:value-of and the specified attribute select="." . This means that the processor must select the text content of the current element in the document. In addition to displaying content, you can specify the names of specific tags, as well as attributes to select the values ​​stored in them. Examples will be discussed below.

      Let's open the XML file through Internet Explorer or another browser. The following text will be displayed:

      My favorite languages:

      • Visual Basic
      • Delphi
      • Prolog

      One of the most important elements in style is xsl:template. Serves to define a reusable template and contains the rules by which the XML document will be transformed. The match attribute contains an expression for selecting nodes to which the template will be applied. A name attribute may also be present. In this case, it is possible to call a template by name with an instruction xsl:apply-templates.

      To repeat the output of the template for each element of the document, use the instruction You need to output this list in HTML format. For this purpose we use the instructions. The pattern is executed for each element that matches the condition specified in the select attribute.

      Instructions xsl:value-of serves to evaluate the expression written in the select attribute and then display the result in the place where the element itself is located.

      Filtration

      We considered the case where the values ​​of each node are read. However, there is often a need to select only part of the data, that is, they need to be filtered. XSLT templates support two filtering methods.

      One of them is using the select attribute of the statement You need to output this list in HTML format. For this purpose we use the instructions, and the second is applying the element's match attribute xsl:template. We'll look at using match later, but for now we'll look at select .

      Let's change the data file a little: add an attribute high, indicating whether a language from our list is a language high level. We will also expand the list of languages.

      C# Visual Basic Delphi Prolog Assembler Java Perl Example 5.3.

      File languages4.xml high Note that the value false for the attribute

      worth only for the value "Assembler" . Let's change the style sheet file a little:

      -
      High level languages:

      Example 5.4. File languages4.xsl In the section [@ high high="true"]

      we specify that only those document nodes that have the attribute

      has the value "true" . The @ sign is a symbol indicating that it is followed by an attribute name.

      • Visual Basic
      • Delphi
      • Prolog

      Let's look at the result:

      High level languages:

      As you can see, the value "Assembler" is not displayed in the list of languages, that is, the XSLT processor filtered the data according to the specified conditions. You need to output this list in HTML format. For this purpose we use the instructions serves to sort the result, to indicate the order of passage of document nodes when performing a transformation. The fields to be sorted are listed separated by semicolons and also have “+” or “-” signs in front of their names, indicating sorting in ascending or descending order.

      Let's consider a slightly modified version of the document - instead of the attribute high we will use the level element, which takes values high or low. And we will write the name of the language in the name element.

      C# high Visual Basic high Delphi high Prolog high Assembler low Java high Perl high Example 5.5.

      File languages6.xml You need to output this list in HTML format. For this purpose we use the instructions In the following stylesheet for instructions

      worth only for the value "Assembler" . Let's change the style sheet file a little:

      -
      apply the order-by attribute with the value +name , where the plus sign means that you need to sort in ascending order.

      Example 5.6.

      File languages6.xsl In the select attribute, we filter by the value of the level element. Also in the select attribute of the statement XSLT(e X tensible S tylesheet L anguage

      T

      transformations) - a language for transforming xml documents.

      Introduction

      The task of generating reports in the DIRECTUM system is one of the most popular.

      This article describes what may not be the most widespread method of generating HTML reports based on xslt transformations. But it undoubtedly deserves attention as one of the most convenient and visual (if you compare it, for example, with an rtf report).

      In short, xslt transformation consists of transforming an xml schema with data into a report based on a pre-prepared template.

      For the example report described in the article, a list of counterparties with their name, TIN and address will be displayed.

      To generate a report you will need two components:

      Xml data for the report

      Xsl report template Data in xml format Data in

      xml format can be obtained with a direct SQL query:

      Select Analit, -- Record ID for generating the link NameAn, -- Contractor name EdIzm, -- INN Dop2 -- Address from dbo.MBAnalit where Vid = %s and Sost = "D" and XRecStat = "+" for xml path( "org"), type -- Get a set of strings

      101702as xml123456789 148965The query described above will return data in this format:631000001 148966Mobile-Auto LLC011101001

      JSC Trinity Far East LLC

      The data needs to be wrapped in a tag

      and save it to a file, adding the header:

      101702as xml123456789The second line of the header of the xml data file is important, it indicates that the file C:\Temp\template.xsl stores the report template into which the data must be transferred. 148965The query described above will return data in this format:631000001The result will be an xml file like this: 148966Mobile-Auto LLC011101001426000, Izhevsk, st. Revolutionary, 44

      443000, Samara region, Samara, st. Lenina, 11

      xsl template

      List of counterparties

      Now you need to create a little magic and specify which data from xml and in what form to insert into the report template.

      To work with data in the xsl template, special tags are used.


      for-each loop and selection rules

      To iterate through all nodes from an xml data file, you need to use the following construction:

      It will allow you to iterate through the entire data tree. In order to select only certain data from the tree, a selection rule is used select="orgs/org". The rules are described in the XPath query language. In the current example, each node will be selected sequentially from .


      Sorting

      If it is necessary for the records to be displayed not in order in the xml file, but sorted, then you need to indicate this in the template:

      Now the records will be sorted pre-sorted by name.


      Display value

      But just sorting through is not enough, you need to display the necessary data in the report, for this there is a construction:

      The construct will display the tag value (name of counterparty).


      Hyperlinks

      To make a link from the name of a counterparty that can be used to open a directory entry, you need to slightly modify the code:


      Case operator and filtering

      Let the counterparty's TIN appear in the report for a reason. If there is no TIN on the card, a message indicating the absence of a TIN will be displayed. To do this you need to use the following construction:

      Taxpayer Identification Number: . TIN is not specified.

      In design choose using a filter test tag contents are checked (TIN) to an empty value ( ). If the content is not empty, then the value is printed. In other cases, the message “TIN is not specified” is displayed.


      Another filter

      Using the filter, it is possible to implement another “little thing” that will mark counterparties with an INN starting, for example, with the region code “18”. It will look like this:

      The design for all TIN records that begin with “18” will additionally display the icon.

      The end result is template code like this:

      List of counterparties

      Taxpayer Identification Number: . TIN is not specified. Address: .


      Result

      And if you open the xml file in the browser, you will get the following report:

      Conclusion

      This article describes only a few basic capabilities xsl, such as filters, sorting, looping, case construction. Besides them there are also interesting opportunities. I hope the article will encourage you to study them too. Perhaps after this, reporting will become more interesting.

      And if you connect this to the report powerful tool as javascript, the described report can easily be made interactive. For example, add an element that allows you to perform some kind of filtering. Or display graphs based on report data.

      What are the advantages of implementing reports in the described way:

      Requires relatively small development large quantity applied computing;

      Developing a template is clear and also relatively inexpensive.

      Everything described in the article is easily integrated into the analytical report, the link to which is given below.

      Less than three years have passed since I had the idea that it was time to learn XSLT -))). The idea arose, but everywhere there was still PHP 4 and the atrocities of Salbotron, which, to put it mildly, was no different high performance. And it was rare that any browser could boast of supporting this very XSLT. For these reasons, I postponed the study of such a promising direction until better times. On this moment we can safely say that these times have come, since PHP 5 has been released with XSLT support and a decent object model, and all top browsers already confidently handle the transformations, just submit XML. :)

      • http://w3c.org - committee for the development and promotion of World Wide Web Internet standards. At the moment, it is the primary source of almost all web-oriented standards and recommendations.
      • http://www.w3.org/TR/xml - Extensible Markup Language specification XML, which is the basis modern web. At the time of writing, the fifth edition, version 1.0, is available, as well as the second edition, version 1.1.
      • http://www.w3.org/TR/xml-names - usage specification namespaces in XML.
      • http://www.w3.org/TR/xpath - specification for using a language for searching parts of an XML document XPath.
      • http://www.w3.org/TR/xsl/ - extended style language specification XSL.
      • http://www.w3.org/TR/xslt - transformation language specification File languages6.xsl.
      • http://validator.w3.org/ - validator HTML.
      • http://www.w3.org/TR/xhtml1/ - specification XHTML1.0.

      Translations into Russian:

      • http://www.rol.ru/news/it/helpdesk/xml01.htm - Extensible Markup Language XML1.0(second edition). /Radik Usmanov/
      • http://www.rol.ru/news/it/helpdesk/xnamsps.htm - Namespaces in XML. /Radik Usmanov/
      • http://www.rol.ru/news/it/helpdesk/xpath01.htm - XML ​​Path Language ( XPath). /Radik Usmanov/
      • http://www.rol.ru/news/it/helpdesk/xslt01.htm - Transformation language XSL (File languages6.xsl). /Radik Usmanov/

      To better understand what's going on, I recommend reading the specifications in the following order:

      1. XML(this is the basis!)
      2. namespaces(mechanism for heterogeneous XML code in one file)
      3. XPath(language for selecting elements from the structure tree)
      4. File languages6.xsl(conversions)
      5. XHTML(what you need to strive for)

      Those who are especially inquisitive can also pay attention to the expanded style language XSL.

      2. Valid XHTML

      What is valid XHTML? First of all, it is an XML document that must conform to the XML specification. Secondly, it’s an almost ordinary HTML page that everyone is used to.

      Why is XHTML needed? Purely for compatibility and cross-browser reasons. A page in XHTML is more likely to display correctly in popular browsers than regular HTML.

      For the average page riveter, the phrase XML document should mean the following:

      1. The document contains an XML document declaration at the very beginning of the page:
      2. The document contains one root element, which contains all the others.
      3. All elements (tags) must have a closing part (
        , ).
      4. Attributes always have a meaning, which must be specified in quotes (single or double). For example, "radio" disabled="disabled" /> .
      5. Control characters & ,< и >should always wear a disguise. For example, "?a=1&b=2" >&. The only exception is, within which special characters need not be masked.

      Also, XHTML itself obliges the following conditions to be met:

      1. The document must declare the namespace within which the HTML elements will be used.
      2. The document must declare a DOCTYPE before the root element and specify one of the XHTML types and the corresponding DTD in it.

      Example of a simple XHTML1.0 document:

      And so about everything in order.

        A declaration of an XML document that specifies its version and encoding.

        Declaration of the namespace and language used.

      Three versions of XHTML1.0 are designed for better backwards compatibility:

      • Strict - provides the greatest compliance with W3C recommendations on the part of browsers. However, the HTML code itself must follow these guidelines.
      • Transitional is a less strict match that causes the browser to behave as if it were a regular HTML document.
      • Frameset - allows you to use frames.

      XHTML1.1 is essentially the same as XHTML1.0 Strict and is intended to supplant other versions of XHTML1.0. However, compared to XHTML1.0 Strict, it has a number of differences:

      1. The lang attribute has been removed, its role is played by xml:lang . (Module [ XHTMLMOD ])
      2. For the a and map elements, you must use the id attribute instead of the name attribute. (Module [ XHTMLMOD ])
      3. A set of ruby ​​elements is available. (Module [RUBY])

      So, if you want the best cross-browser compatibility and W3C compatibility, then XHTML1.1 is it!

      For these reasons, the result of my transformations will be exactly XHTML1.1.

      3. XSLT transformations

      What is XSLT? It is an XML document transformation language that was developed as part of the Extended Stylesheet Language (XSL).

      Why is XSLT needed? It allows you to implement a scheme in which the data is stored separately and its presentation is separate. That is, one XML document is transformed using another XML document (the XSL that contains the XSLT templates) into a final document. The output can be XML, HTML or Text Document any format.

      In order to use XSLT transformations, you first need to generate the correct XSL style and connect it to the XML file.

      A valid XSL document is an XML document that has the xsl namespace specified and has a stylesheet root element. In the very simple case the style might look like this, for example:

      This style does not contain any explicit definitions of templates or other XSL elements. However, it can already be used. To see the result, just generate an arbitrary XML document and attach this style to it:

      The line is responsible for connecting the style:

      In this case, the encoding of the result will be UTF-8, despite the fact that the source document was generated in windows-1251. Unfortunately, browsers usually don't allow you to view the code in the resulting document, but PHP5's XSLT module makes it possible to pass the resulting code into a variable that can be saved to a file. Therefore, using PHP, I will provide the source code of the resulting document:

      This code is not a valid XML document, much less XHTML1.1. In order to generate the necessary code, I will complicate the original XSL style and add the necessary templates and transformations. In this case, the original XML document will remain unchanged.

      As an example, I will give an XSL style that, using XSLT, will display a list of attributes of the source XML document with their values, while valid XHTML1.1 will be generated. So, the style:

      File - test.xsl
      "/" > "http://www.w3.org/1999/xhtml" xml:lang="en" > My first XSLT
      My list:
      1. background-color: #eee;

      To understand how it works, I will describe each action separately:

        XML Document Declaration:

        Required attribute is to define an xsl namespace via an attribute xmlns:xsl= "http://www.w3.org/1999/XSL/Transform".

        The next step in root element stylesheet declares how the resulting document should be formed:

        "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd" />

        Main attributes:

        • method= "xml"- document output method. The resulting document will be in XML format.
        • encoding= "windows-1251"- encoding of the resulting document.
        • omit-xml-declaration="no"- whether or not to skip the initial declaration of the XML document (). Can have the value "yes" or "no" (relevant only for html).
        • indent= "yes"- form indents according to the level of nesting. Can be "yes" or "no".
        • media-type= "text/xml"- MIME type of the resulting document (used only for the html output method).
        • doctype-public="-//W3C//DTD XHTML 1.1//EN"- type of the resulting document (DOCTYPE)
        • doctype-system= "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"- link to DTD

        If the output method is declared as html, then the values ​​of the encoding and media-type attributes will be substituted into the page title ( ...) via a meta tag.

        Main template declaration:

        Attribute xmlns= "http://www.w3.org/1999/xhtml" points to the xhtml namespace that will be applied by default to this element and all child elements, for which it is not specified explicitly.

        xml:lang= attribute "ru" indicates the language in which the page (future) is generated.

      This part of the style was needed to form the attributes of valid XHTML1.1 code.

      Now for XSLT transformations:

        Insert plain text:

        The select attribute accepts an XPath expression, based on which it makes a selection. If the selection returned a list of nodes, then the loop starts running for each element.

        In this case, the selection will return a list of attributes for this (root) and all child elements.

        Checking the condition:

        In this case, if the position of the element is even (determined by the higher if), then the style of the element

      1. The background color will be gray.

        Displaying element values:

        This code will insert into the parent element a string compiled from the name of the current element and its value. The content of the select attribute matches the XPath.

        Parser developer: "system-property("xsl:vendor-url")" /> "system-property("xsl:vendor-url")" /> "system-property("xsl:vendor")" />

      The result of processing this style (test.xsl) will be the following code:

      Result - source code
      "1.0" encoding="windows-1251"?> "http://www.w3.org/1999/xhtml" xml:lang="en" > My first XSLT
      My list:
      1. attr1 = Main attribute
      2. style=" background-color : #eee ;" > attr1 = my attribute1
      3. attr2 = my attribute2
      4. style=" background-color : #eee ;" > attr5 = Free attribute
      Parser developer: libxslt

      This code complies with the XHTML1.1 standard and was generated from the original XML document. To check, you can use the W3C validator, which is located at http://validator.w3.org/.

      In the browser this code looks something like this:

      // Output HTML code as text header("Content-Type: text/plain;" ); // Source XML document object$xml = new DOMDocument(null , "windows-1251" ); $xml ->load("test.xml" ); // Style object $xsl = new DOMDocument(null , "windows-1251" ); $xsl ->load("test.xsl" ); // Creating a parser$proc = new XSLTProcessor(); // Connecting the style to the parser$proc ->importStylesheet($xsl ); // Processing of the source XML document by the parser$parsed = $proc ->transformToXml($xml ); // Output the resulting code echo $parsed ; // Write a file with the resulting code file_put_contents("parsed.html" , $parsed );?>
      IE 6 FireFox 3 Opera 9.02

      Additional information on using XSLT in PHP5 can be found at http://ru2.php.net/manual/ru/book.xslt.php.

      Thinking out loud

      “Comrades, we are standing on the edge of a huge abyss! And I propose to take a big, decisive step forward!”

      2019 Anton Pribora. When copying materials from the site, please provide a link to the source.

      An alternative introduction to using XSL Transformations in PHP using Sablotron.

      This material should be taken as an alternative introduction to using XSLT with Sablotron in PHP.

      The terms XSL and XSLT are close to each other, and for beginners they can be considered synonyms. Details of what the differences are are described in the XSL Transformations W3C specification.

      Anyone interested in the capabilities of XSLT read standard example from the manual, or examples given in articles on XSLT on various sites. A working example from the same series:

      Railroad Tycoon II Platinum economic strategy PopTop software G.O.D. games 2001 Grand Prix 4 car simulator Geoff Crammond & Simergy Infogrames Entertainment 2002 "; $xslData = " Games

      Games

      Name genre year developer publisher
      "; $xh = xslt_create(); $arguments = array("/_xml" => $xmlData, "/_xsl" => $xslData); $result = @xslt_process($xh, "arg:/_xml", " arg:/_xsl", NULL, $arguments); if ($result) print ($result); else ( print ("There was an error that occurred in the XSL transformation...n"); print ("tError number : " . xslt_errno($xh) . "n"); print ("tError string: " . xslt_error($xh) . "n"); exit; ) ?>

      There are plenty of similar examples on the Internet. All of them show well that XSL transformation in php works, but after reading them it remains unclear why XSL is needed, or rather the opposite - why XSL is not needed.

      “Really,” the reader will think, “if the data is in the database, why bother creating XML first and then converting it via XSL? The HTML template class will do this just as well.”

      After this, the disappointed programmer completely loses interest in XSL and labels the technology as “unnecessary nerd.”

      You, dear readers, are lucky to have found such a wonderful site as “php in detail”. Here you will read about how XSL can not only convert XML to HTML, but also how XSL can make working with PHP scripts easier.

      Beginning of work

      The above example, although too simple, illustrates well how XSL transformation is done in PHP.

      For this code to work, you need to install the Sablotron XSLT processor. On a Windows machine this is done like this:

      1. put iconv(-1.3).dll, expat.dll and sablot.dll in C:windowsSystem (all files are in the standard php distribution)
      2. open C:windowsphp.ini and find the extension_dir parameter in it. If the parameter value is "." or something like "./", change to, say, "f:usrlocalphpextension" (or the address of the directory in which you have/will have php extensions). This will now be the php extensions directory.
      3. put the file php_xslt.dll (this is for php version 4.2.x), or php_sablot.dll (for version 4.0.x) into the extensions directory
      4. in php.ini uncomment the line extension=php_xslt.dll (4.2.x) or extension=php_sablot.dll (4.0.x)

      Theory

      Using XSLT allows you to separate the work of formatting and presenting data from PHP scripts. This is not only a reduction in the amount of code, but also the removal of a large number of logical constructs(if, else, switch), and therefore facilitating the work of writing and debugging programs. I dare say that anyone who has not tried working with XSLT has no idea how much easier PHP coding will be.

      However, don’t delude yourself: if you had several if ... else constructs in a PHP script, they will most likely appear in the same number in the XSL file.

      Now to the examples.

      List output

      All the complications that come from the need to display the list in a human-readable form are transferred to the shoulders of XSL. Example #2. A list of articles on the site with highlighting of the article that is being read now, alternating colors in the lines and numbering of the list.

      2002-05-30 Catching errors in PHP A living project and a dead magazine Working with MySQL. Part 7. Trees Manual sorting in the web interface How to get along between a designer and a programmer Relax this is PHP

      ...

      ... #cccccc <

      Custom markup

      When translating a site with texts (like this one) to XML, it’s natural to want to create your own article markup. For example, in the important container, highlight very important places and be able to highlight them not necessarily with bold font, but maybe with color, CSS style. Or write quotes like quote text and be able to change their design style along with the site design.

      Slowly moving forward from the simplest first example, many stumble upon this problem and cannot find a solution. After all, if you select a paragraph in the tag And to make a template for it, at first glance, there are three ways to display the content:

      1. xsl:value-of tag displays text but removes all tags in the paragraph
      2. xsl:copy-of tag displays a copy of all content (without the ability to apply templates to children - internal tags) and the container itself (which is not very nice in HTML).
      3. finally xsl:apply-templates will apply the templates to the children but will skip the text

      The problem seems hopeless, but there is a solution. I use "magic" templates that display both the text and the tags in it with all the attributes and without changes. Example #3:

      This example uses magic patterns for parsing arbitrary markup. This avoids the following complaints: People, please tell us, we are not local! I can’t display tags in text using value-of!


      Remember these patterns once and for all! Then you can process any text Almost any.

      The first thing the XSLT processor does when calling the apply-templates statement is to look for a template for each element. There is a template for the strong element, and it is in accordance with it that such elements will be processed. There is no template for the hyperlink, so it will be displayed as is. You can add a template to the XSL for links that would display next to each text link picture to open it in a new window:

      * the template uses the match="a[@href]" parameter - this template will only be applied to those link tags that have an href field and will skip anchors ().

      Invalid code and

      The seeming need to write valid XML code also discourages many XSLT neophytes. Okay, from tomorrow we will write only valid articles, fortunately at home you can check if there is an XML error in the text - mismatched tag or invalid token - we will deal with this somehow. But, in an amicable way, the entire archive needs to be translated into valid code! And I thought so too when the opportunity arose to redesign the site in XML.

      The solution to the problem is quite simple: if you don’t want it, don’t write it validly. Write as you are used to - without quotes in tag attributes, use simple
      And so on. Enough to enclose the text in a container(example below).

      As for the situation here: there is no nbsp element in XML. There are lt, gt, quot, but not nbsp (quite logical - this is a non-braking space, which relates to formatting and was invented for HTML). Therefore, it must be declared in the document, or used only internally.

      Example #4:

      People, please note, we are not locals ourselves!


      Remember these patterns too!

      Very comfortably! Big changes there is no need to add it to the archive. You can start writing validly, but continue at random. Or you can combine these two approaches. In order not to write in archive files CDATA tag, I did a simple conversion using regular expressions(It is also important to remember that one CDATA tag should not contain another).

      $doc = preg_replace("~<(p|h|pre)>(.*?)~", "<\1>\2", $doc);

      Cycles

      Let's say we need to make a form for editing an article, including its date. For ease of use, you need to make three drop-down lists (hereinafter referred to as “twists”) - date from 1 to 31, month, year. The first solution that comes to mind is to make the HTML code of the spinners in php, paste it into XML in a CDATA container, and then output it to XSL with the disable-output-escaping="yes" parameter.

      In fact, XSLT can do that too. It is enough to insert the date, month and year into the XML data. The spinners can be drawn directly in XSLT.

      Let's write a template that is not intended for any document element. It will be called by the xsl:call-template command and receive two parameters: the counter value and the maximum. First, it will output the data we need with the counter value, then call itself with the parameters maximum and the counter increased by 1. Example #5:

      February March April May June July August September October November December

      ... 7 10 2002

      ... ...

      As homework, I leave you with a template for displaying a twist with the year.