xslt include, xml inclusion

Include

1. xsl:include example
2. xsl:include with device:file under Windows
3. Conditional Includes
4. How To Include external XSL files into a master XSL file
5. Conditional inclusions
6. Including XML in a stylesheet
7. How to include a text file
8. Include document1 in document 2
9. xsl:include from a jar file

1.

xsl:include example

Steve Muench

If I'm understanding what you want:

a reusable "chunk" of tags and <xsl:***> elements
that is responsible for handling the formatting for the "ChargeListRSQ" block of your source document
In a way that allows the "chunk" of tags to use xpath expressions that are relative to the "ChargeListRSQ"
Without mentioning a particular XML file that <ChargeListRSQ> "lives in"...

Then an <xsl:template> can do all these for you.

Let's say your data looks like this:

<TR300>
  <ChargeListRSQ>
     <Charge id="1">ABC</Charge>
     <Charge id="2">DEF</Charge>
  </ChargeListRSQ>
</TR300>

Then you can create a "tab.xsl" stylesheet with a template whose match pattern is match="ChargeListRSQ", and it will

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

   <!-- This template handles ChargeListRSQ "block" -->
   <xsl:template match='ChargeListRSQ'>
     <table border="1">
        <xsl:for-each select="Charge">
          <tr>
             <td><xsl:value-of select="@id"/></td>
             <td><xsl:value-of select="."/></td>
          </tr>
        </xsl:for-each>
     </table>
   </xsl:template>

</xsl:stylesheet>

and then include "tab.xsl" into another main stylesheet like "main.xsl"...

  <xsl:output method="html" indent="yes"/>

  <xsl:include href="tab.xsl"/>

  <xsl:template match="/">
    <html>
      <body>
         <xsl:apply-templates/>
      </body>
    </html>
  </xsl:template>

</xsl:stylesheet>

And by the magic of the "Apply Templates" processing, when it comes time for handle the formatting for the <ChargeListRSQ> in the source, your template will "fire" and your reusable chunk of tags will kick in.

2.

xsl:include with device:file under Windows

Kay Michael

Is it possible to call xsl-StyleSheet from a different XSl-StyleSheet

> href="C:/Portal/com/vizional/portal/xsl/head.xsl"
> it returns file not found exception is this right way to give 
> path or is there any other way in xsl.

The href attribute to xsl:include must be a URL, not a filename. Prefixing it with "file:/" should work. (No-one seems to know how many slashes are correct, but it seems to work anyway).

3.

Conditional Includes

Mike Kay


> This is our situation. We have a global xsl that
> ensures that all our webpages have a certain content.
> We are trying to make the inclusion of local xsl
> stylesheets conditional 

The usual mistake. You should import the global stylesheet into the local one, not the other way around.

4.

How To Include external XSL files into a master XSL file

G. Ken Holman

>What is the syntax to link multiple child style sheets into
>a master style sheet ...
>
>e.g.
>header style sheet     header.xsl
>footer style sheet      footer.xsl
>data style sheet       data001.xsl
>master style sheet.  master.xsl
>
>this way i can always reference the master.xsl
>style sheet from any/all   *.xml files
>and then link in header.xsl (this one never changes)
>then the appropriate data.xsl (this one changes)
>then link the footer.xsl (this one never changes)

Your syntax above implies you want different snippets to be included in the root template, which can be done for the content of a single template, but I suspect you would rather want to include different sets of template rules into a single stylesheet.

If you must have a portion of a given template in an external file, you can use the XML external parsed general entities, but that syntactic scheme does not support reuse properly (though many coerce it to try). Personally, I don't put portions of templates in external files, rather, I use the <xsl:call-template> construct to accomplish what you are implying.

There are two semantic inclusion schemes at the top level of a stylesheet (children of the stylesheet container element): inclusion and importation.

You can use <xsl:include> to pull in top-level elements from another stylesheet and all such constructs are included as if they were edited in-situ (which sometimes can introduce problems accommodating template conflict resolution).

You can use <xsl:import> to pull in top-level elements from another stylesheet with the concept of "importance". This confers more importance on the importing stylesheet constructs than on the imported stylesheet constructs, without conflict. This is a powerful way to exploit an existing stylesheet with tweaks from an importing stylesheet.

>also
>what is the proper syntax in the included external xsl files

Included and imported stylesheets are entire stylesheets in their own right.

5.

Conditional inclusions

Jeni Tennison



>Let's say I have an XMl file which has an element such as:
><include url="file.xml"/>
>This file would be part of the "input tree".
>You would probably say that xsl:include would do the trick, yes but that's
>not my question.
	

Actually, from your description of the problem, we wouldn't say that xsl:include would do the trick. xsl:include, like xsl:import is about including/importing *stylesheets* into an XSLT stylesheet. In other words, xsl:include/xsl:import are what you would use if you wanted to build modular stylesheets; they aren't what you use to pull in more information for processing. For that, you use the document() function. For example, you can use document() to pull in information from a particular file and process it:

  <xsl:apply-templates select="document('file.xml')" mode="include" />

If you have a filename specified within your source XML, such as with your include:

  <include url="file.xml" />

you can use XPath to access the name of the file, and document() to access its content:

  <xsl:apply-templates select="document(include/@url)" mode="include" />
>We want to make these inclusions conditional, and than work on that result
>tree.
><if include="1">
><then>
><include url="file1.xml"/>
></then>
><else>
><include url="file2.xml"/>
></else>
></if>

It's not particularly clear to me whether the specification of these conditions is done in your source XML or in your stylesheet. You could specify this in your stylesheet using something like:

  <xsl:choose>
    <xsl:when test="$include = 1">
      <xsl:apply-templates select="document('file1.xml')" mode="include" />
    </xsl:when>
    <xsl:otherwise>
      <xsl:apply-templates select="document('file2.xml')" mode="include" />
    </xsl:otherwise>
  </xsl:choose>

If the above XML is in your source file, then you need a template that matches 'if' and decides what to do based on its contents:

<xsl:template match="if">
  <xsl:choose>
    <xsl:when test="@include = $include">
      <xsl:apply-templates select="document(then/include/@url)"
                           mode="include" />
    </xsl:when>
    <xsl:otherwise>
      <xsl:apply-templates select="document(else/include/@url)"
                           mode="include" />
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

In the above, I've used xsl:apply-templates on the result of the call to document() in 'include' mode. The reason for this is that document() returns the root node of the XML document that you're accessing, which will match a template that matches the root node, which is often used as the base template in a stylesheet. So, if you had, for example, a template like:

<xsl:template match="/">
  <xsl:apply-templates select="document('file.xml')" />
</xsl:template>

you'd cause an infinite loop: the template is matched by the root node of the source document, then templates are applied to the root node of file.xml, which fires the template again, so templates are applied to the root node of file.xml, which fires the template again and so on.

Adding a mode means that you can do:

<xsl:template match="/">
  <xsl:apply-templates select="document('file.xml')" mode="include" />
</xsl:template>

<xsl:template match="/" mode="include">
  <!-- do something else -->
</xsl:template>

Another way of getting round the problem is to apply templates to the document element of the accessed document rather than its root node (although this only works if the document elements of the accessed document and source document aren't the same).

Of course, you don't have to apply templates at all: you can assign the root node of the accessed document to a variable and index into it as you desire, or use xsl:for-each to iterate over its contents.

Mike Kay:

This has been raised a number of times. On a previous thread we came to the conclusion that the user was trying to write a general-purpose stylesheet G and then specialize it by conditionally including a special-purpose stylesheet A or B. The way to meet this requirement is to have A and B include G, not the other way around, and then you conditionally select A or B as the principal stylesheet when starting the transformation.

6.

Including XML in a stylesheet

Jeni Tennison

xsl:import and xsl:include are designed to allow you to use the variables, keys, templates and other XSLT constructs from a stylesheet in another stylesheet, *not* to include a particular snippet of XML in your stylesheet.

There are two ways of keeping XML snippets in separate files and including them in your stylesheet. In both, the snippet is stored in a separate file. So, you create an XML file that contains the text that you want to include. For example, style.xml might be:

- --- style.xml ---
<style type="text/css" id="NOF_STYLE_SHEET">
  DIV#Picture25LYR { position:absolute; visibility:inherit; }
  DIV#Picture26LYR { position:absolute; visibility:inherit; }
  DIV#Picture27LYR { position:absolute; visibility:inherit; }
</style>

The first is to use entities. Within your stylesheet, declare the entity within a DOCTYPE at the top of the page:

<!DOCTYPE xsl:stylesheet [
  <!ENTITY style SYSTEM 'style.xml'>
]>

Then, at the point where you want to include the contents of that file, refer to the entity you've defined with an entity reference:

<xsl:template match="/">
  <html>
    <head>
      <title>My Page</title>
      <!-- CSS styles included here -->
      &style;
    </head>
    <body>
      ...
    </body>
  </html>
</xsl:template>

The contents of your style.xml file will then be included wherever you reference the entity.

The second option is to use the document() function in XSLT to pull in the contents of the style.xml file. The call:

  document('style.xml')

accesses the XML document node, and you can then copy it to insert it into your output:

<xsl:template match="/">
  <html>
    <head>
      <title>My Page</title>
      <!-- CSS styles included here -->
      <xsl:copy-of select="document('style.xml')/style" />
    </head>
    <body>
      ...
    </body>
  </html>
</xsl:template>

The two approaches each have advantages and disadvantages. The entities approach is very useful for inserting any well-formed XML into your stylesheet: it could be used to insert five elements, or a piece of text, for example. With document(), on the other hand, the XML being imported has to be XML, and has to be a *document* - that means it has to have one, and only one, element. On the other hand, the document() approach allows you more easily to *process* the nodes that you pull in, which means that the included document can itself be transformed before being outputted.

7.

How to include a text file

Steve Muench

Here's a Java extension function I used while formatting examples for my book . This function reads in an external text file and returns a single String representing its content.

I use it from within a stylesheet to read in a filename like this:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
	xmlns:ext="http://TextUtils">
	
	
<xsl:template match select="an-appropriate-place">
   <xsl:value-of select="ext:contents('textfilename')"/>

This is the java file, TextUtils.java

import java.io.*;

public class TextUtils {

  public static  String contents(String actualFileName) {

   FileReader in = null;
   try {
     in = new FileReader(actualFileName);
   }
   catch (FileNotFoundException e) {
     return "File '"+actualFileName+"' not found.\n";
   }
   StringWriter out = new StringWriter();

   char[] buffer = new char[4096];
   int numchars;
   try {
     while((numchars = in.read(buffer)) != -1)
            out.write(buffer, 0, numchars);
          out.close();
   }
   catch (IOException e) {
     return "IO Error reading file '"+actualFileName+"'.\n";
   }
   String returnContents = out.toString();
   return returnContents.trim();

  }

}

8.

Include document1 in document 2

Jim Fuller


 
> How should I write a mostly-identity transformation that puts a.xml into a
> specific child of b.xml and outputs the whole thing?  
> I've tried
	

method 1

use  <xsl:copy-of select='document("somexmldocument.xml")'/>

mehtod 2 : include it using a DTD

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE document [ <!ENTITY  resourcedb SYSTEM 
'file:/some/absolute/path/a.xml'> ]>
<resource>
<childofb>&resourcedb;<childofb>
</resource>

9.

xsl:include from a jar file

J.Pietschmann



> SUN JVM should be able to grok something like
>   <xsl:include href="jar:file:///foo/bar.jar!/com/sample/baz.xsl"/>

I tested it, works fine with both Xalan and Saxon, and it should work with any Java implementation as long as it uses java.net.URL.

if the jar or the file within it doesn't exist then Xalan fails with: javax.xml.transform.TransformerException: Had IO Exception with stylesheet file: jar:file:///foo/bar.jar!/com/sample/baz.xsl

and Saxon: Failure reading jar:file:///foo/bar.jar!/com/sample/baz.xsl: no more input