Oracle9i XML Developer's Kits Guide - XDK Release 2 (9.2) Part Number A96621-01 |
|
This chapter contains the following sections:
The XSLT processor operates on two inputs: the XML document to transform, and the XSLT stylesheet that is used to apply transformations on the XML. Each of these two can actually be multiple inputs. One stylesheet can be used to transform multiple XML inputs. Multiple stylesheets can be mapped to a single XML input.
To implement the XSLT Processor in the XML Parser for Java use XSLProcessor class.
Figure 5-1 shows the overall process used by class XSLProcessor
. Here are the steps:
removeParam()
- remove parameterresetParam() -
remove all parameterssetParam()
- set parameters for the transformationsetBaseURL()
- set a base URL for any relative references in the stylesheetsetEntityResolver()
- set an entity resolver for any relative references in the stylesheetsetLocale
- set locale for error reportingXSLProcessor.newXSLStylesheet()
to create a stylesheet object:
This creates a stylesheet object which is thread-safe and can be used in multiple XSL Processors.
XSLProcessor.processXSL(xslstylesheet, xml instance)
The results can be one of the following:
This example uses one XML document and one XSTT stylesheet as inputs.
public class XSLSample { public static void main(String args[]) throws Exception { if (args.length < 2) { System.err.println("Usage: java XSLSample xslFile xmlFile."); System.exit(1); } // Create a new XSLProcessor. XSLProcessor processor = new XSLProcessor(); // Register a base URL to resolve relative references // processor.setBaseURL(baseURL); // Or register an org.xml.sax.EntityResolver to resolve // relative references // processor.setEntityResolver(myEntityResolver); // Register an error log // processor.setErrorStream(new FileOutputStream("error.log")); // Set any global paramters to the processor // processor.setParam(namespace, param1, value1); // processor.setParam(namespace, param2, value2); // resetParam is for multiple XML documents with different parameters String xslFile = args[0]; String xmlFile = args[1]; // Create a XSLStylesheet // The stylesheet can be created using one of following inputs: // // XMLDocument xslInput = /* using DOMParser; see below in this code */ // URL xslInput = new URL(xslFile); // Reader xslInput = new FileReader(xslFile); InputStream xslInput = new FileInputStream(xslFile); XSLStylesheet stylesheet = processor.newXSLStylesheet(xslInput); // Prepare the XML instance document // The XML instance can be given to the processor in one of // following ways: // // URL xmlInput = new URL(xmlFile); // Reader xmlInput = new FileReader(xmlFile); // InputStream xmlInput = new FileInputStream(xmlFile); // Or using DOMParser DOMParser parser = new DOMParser(); parser.retainCDATASection(false); parser.setPreserveWhitespace(true); parser.parse(xmlFile); XMLDocument xmlInput = parser.getDocument(); // Transform the XML instance // The result of the transformation can be one of the following: // // 1. Return a XMLDocumentFragment // 2. Print the results to a OutputStream // 3. Report SAX Events to a ContentHandler // 1. Return a XMLDocumentFragment XMLDocumentFragment result; result = processor.processXSL(stylesheet, xmlInput); // Print the result to System.out result.print(System.out); // 2. Print the results to a OutputStream // processor.processXSL(stylesheet, xmlInput, System.out); // 3. Report SAX Events to a ContentHandler // ContentHandler cntHandler = new MyContentHandler(); // processor.processXSL(stylesheet, xmlInput, cntHandler); } }
oraxsl
is a command-line interface used to apply a stylesheet on multiple XML documents. It accepts a number of command-line options that dictate how it should behave.
To use oraxsl
ensure the following:
Use the following syntax to invoke oraxsl
:
oraxsl options source stylesheet result
oraxsl
expects to be given a stylesheet, an XML file to transform, and optionally, a result file. If no result file is specified, it outputs the transformed document to standard out. If multiple XML documents need to be transformed by a stylesheet, the -l or -d options in conjunction with the -s and -r options should be used instead. These and other options are described in Table 5-1.
XML extension functions for XSLT processing allow users of XSLT processor to call any Java method from XSL expressions.
Java extension functions should belong to the namespace that starts with the following:
http://www.oracle.com/XSL/Transform/java/
An extension function that belongs to the following namespace:
http://www.oracle.com/XSL/Transform/java/classname
refers to methods in class classname
. For example, the following namespace:
http://www.oracle.com/XSL/Transform/java/java.lang.String
can be used to call java.lang.String
methods from XSL expressions.
If the method is a non-static method of the class, then the first parameter will be used as the instance on which the method is invoked, and the rest of the parameters are passed on to the method.
If the extension function is a static method, then all the parameters of the extension function are passed on as parameters to the static function.
The following XSL, static function example:
<xsl:stylesheet xmlns:math="http://www.oracle.com/XSL/Transform/java/java.lang.Math"> <xsl:template match="/"> <xsl:value-of select="math:ceil('12.34')"/> </xsl:template> </xsl:stylesheet>
prints out '13'.
The extension function 'new' creates a new instance of the class and acts as the constructor.
The following constructor function example:
<xsl:stylesheet xmlns:jstring="http://www.oracle.com/XSL/Transform/java/java.lang.String"> <xsl:template match="/"> <!-- creates a new java.lang.String and stores it in the variable str1 --> <xsl:variable name="str1" select="jstring:new('Hello World')"/> <xsl:value-of select="jstring:toUpperCase($str1)"/> </xsl:template> </xsl:stylesheet>
prints out 'HELLO WORLD'.
The result of an extension function can be of any type, including the five types defined in XSL:
They can be stored in variables or passed onto other extension functions.
If the result is of one of the five types defined in XSL, then the result can be returned as the result of an XSL expression.
Here is an XSL example illustrating the Return value extension function:
<!-- Declare extension function namespace --> <xsl:stylesheet xmlns:parser = "http://www.oracle.com/XSL/Transform/java/oracle.xml.parser.v2.DOMParser" xmlns:document = "http://www.oracle.com/XSL/Transform/java/oracle.xml.parser.v2.XMLDocument" > <xsl:template match ="/"> <!-- Create a new instance of the parser, store it in myparser variable --> <xsl:variable name="myparser" select="parser:new()"/> <!-- Call a non-static method of DOMParser. Since the method is anon-static method, the first parameter is the instance on which themethod is called. This is equivalent to $myparser.parse('test.xml') --> <xsl:value-of select="parser:parse($myparser, 'test.xml')"/> <!-- Get the document node of the XML Dom tree --> <xsl:variable name="mydocument" select="parser:getDocument($myparser)"/> <!-- Invoke getelementsbytagname on mydocument --> <xsl:for-each select="document:getElementsByTagName($mydocument,'elementname')"> ...... </xsl:for-each> </xsl:template> </xsl:stylesheet>
Overloading based on number of parameters and type is supported. Implicit type conversion is done between the five XSL types as defined in XSL.
Type conversion is done implicitly between (String, Number, Boolean, ResultTree) and from NodeSet to (String, Number, Boolean, ResultTree).
Overloading based on two types which can be implicitly converted to each other is not permitted.
The following overloading will result in an error in XSL, since String and Number can be implicitly converted to each other:
Mapping between XSL type and Java type is done as following:
String -> java.lang.String Number -> int, float, double Boolean -> boolean NodeSet -> XMLNodeList ResultTree -> XMLDocumentFragment
The following example illustrates both ora:node-set and ora:output in action.
If you enter:
$ oraxsl foo.xml slides.xsl toc.html
where "foo.xml" is any XML file, you get:
<!-- | Illustrate using ora:node-set and ora:output | | Both extensions depend on defining a namespace | with the uri of "http://www.oracle.com/XSL/Transform/java" +--> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ora="http://www.oracle.com/XSL/Transform/java"> <!-- <xsl:output> affects the primary result document --> <xsl:output mode="html" indent="no"/> <!-- | <ora:output> at the top-level enables all attributes | that <xsl:output> enables, but you must provide the | additional "name" attribute to assign a name to | these output settings to be used later. +--> <ora:output name="myOutput" mode="html" indent="no"/> <!-- | This top-level variable is a result-tree fragment +--> <xsl:variable name="fragment"> <slides> <slide> <title>First Slide</title> <bullet>Point One</bullet> <bullet>Point Two</bullet> <bullet>Point Three</bullet> </slide> <slide> <title>Second Slide</title> <bullet>Point One</bullet> <bullet>Point Two</bullet> <bullet>Point Three</bullet> </slide> </slides> </xsl:variable> <xsl:template match="/"> <!-- | We cannot "de-reference" a result-tree-fragment to | navigate into it with an XPath expression. However, using | the ora:node-set() built-in extension function, you can | "cast" a result-tree fragment to a node-set which *can* | then be navigated using XPath. Since we'll use the node-set | of <slides> twice below, we save the node-set in a variable. +--> <xsl:variable name="slides" select="ora:node-set($fragment)"/> <!-- | This <html> page will go to the primary result document. | It is a "table of contents" for the slide show, with | links to each slide. The "slides" will each be generated | into *secondary* result documents, each slide having | a file name of "slideNN.html" where NN is the two-digit | slide number +--> <html> <body> <h1>List of All Slides</h1> <xsl:apply-templates select="$slides" mode="toc"/> </body> </html> <!-- | Now go apply-templates to format each slide +--> <xsl:apply-templates select="$slides"/> </xsl:template> <!-- In 'toc' mode, generate a link to each slide we match --> <xsl:template match="slide" mode="toc"> <a href="slide{format-number(position(),'00')}.html"> <xsl:value-of select="title"/> </a><br/> </xsl:template> <!-- | For each slide matched, send the output for the current | <slide> to a file named "slideNN.html". Use the named | output style defined above called "myOutput". <xsl:template match="slide"> <ora:output use="myOutput href="slide{format-number(position(),'00')}.html"> <html> <body> <xsl:apply-templates select="title"/> <ul> <xsl:apply-templates select="*[not(self::title)]"/> </ul> </body> </html> </ora:output> </xsl:template> <xsl:template match="bullet"> <li><xsl:value-of select="."/></li> </xsl:template> <xsl:template match="title"> <h1><xsl:value-of select="."/></h1> </xsl:template> </xsl:stylesheet>
This section lists XSL and XSLT Processor questions and answers.
I don't know what is wrong here. This is my news_xsl.xsl
file:
<?xml version ="1.0"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/TR/WD-xsl"> <xsl:template match="/"> <HTML> <HEAD> <TITLE> Sample Form </TITLE> </HEAD> <BODY> <FORM> <input type="text" name="country" size="15"> </FORM> </BODY> </HTML> </xsl:template> </xsl:stylesheet>
ERROR:End tag 'FORM' does not match the start tag 'input'. Line 14, Position 12 </FORM>- ----------^news.xml <?xml version="1.0" ?> <?xml-stylesheet type="text/xsl" href="news_xsl.xsl"?> <GREETING/>
Answer: Unlike in HTML, in XML every opening or starting tag must have an ending tag. Even the input that you are giving should have a matching ending tag, so you should modify your script like this:
<FORM> <input type="text" name="country" size="15"> </input> </FORM>
Or:
<FORM> <input type="text" name="country" size="15"/> </FORM>
Also, remember that in XML the tags are case sensitive, unlike in HTML.
Is the output method html
supported in the recent version of the XSL parser? I was trying to use the <BR>
tag with the <xsl output method="xml"/>
declaration but I got an XSL error message indicating a not well-formed XML document. Then I tried the following output method declaration: <xsl output method="html"/>
but I got the same result.
Here's a simple XSL stylesheet I was using:
<?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl output method="html"/> <xsl:template match="/"> <HTML> <HEAD></HEAD> <BODY> <P> Blah blah<BR> More blah blah<BR> </P> </BODY> </HTML> </xsl:template>
How do I use a not well-formed tag like <IMG>
or <BR>
in an XSL stylesheet?
Answer: We fully support all options of <xsl output>
. The problem here is that your XSL stylesheet must be a well-formed XML document, so everywhere you are using the <BR>
element, you need to use <BR/>
instead. The <xsl output method="html"/>
requests that when the XSLT engine writes out the result of your transformation, it is a proper HTML document. What the XSLT engine reads in must be well-formed XML.
Question: I have a question regarding your reply. I have an XSL stylesheet that preforms XML to HTML conversion. Everything works correctly with the exception of those HTML tags that are not well formed. Using your example if I have something like:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="html"/> ...... <input type="text" name="{NAME}" size="{DISPLAY_LENGTH}" maxlength="{LENGTH}"> </input> ...... </xsl:stylesheet>
It would render HTML in the format of
<HTML>......<input type="text" name="in1" size="10" maxlength="20"/> ...... </HTML>
While Internet Explorer can handle this, Netscape cannot. Is there any way to generate completely cross-browser-compliant HTML with XSL?
Answer 2: If you are seeing:
<input ... />
instead of:
<input>
then you are likely using the incorrect way of calling XSLProcessor.processXSL()
, since it appears that it's not doing the HTML output for you. Use:
void processXSL(style,sourceDoc,PrintWriter)
instead of:
DocumentFragment processXSL(style,sourceDoc)
and it will work correctly.
I'm using <xsl output method="html" encoding="iso-8859-1" indent = "no" />
. Is it possible to prevent XSLT from outputting <META http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
in the HEAD
element because Netscape 4.0 has difficulties with this statement. It renders the page twice.
Answer: The XSLT 1.0 recommendation says in Section 16.2 ("HTML Output Method") that if there is a HEAD
element, then the HTML output method should add a META
element immediately after the start-tag of the HEAD
element specifying the character encoding actually used.
For example:
<HEAD><META http-equiv="Content-Type" content="text/html; charset=EUC-JP">.
So any XSLT 1.0-compliant engine needs to add this.
Netscape 4.0 has following bug:
When Mozilla hits the meta-encoding tag it stops rendering the page and does a refresh, thereby producing an annoying flickering. I probably have to do a replacement in the servlets Outputstream, but I don't like doing so. Are there any alternatives?
Answer: The only alternatives I can think of are:
<HEAD>
section in your HTML page. According to the XSLT specification, this will suppress the inclusion of the <META>
tag.method="HTML"
for the output. Since it defaults to "HTML"
, according to the specification for result trees that start with <HTML>
(in any mixture of case), you'd have to explicitly set it to method="xml"
or method="text"
.Neither is pretty, but either one might provide a workaround.
I get the error XSL-1900, exception occurred. What does this mean? How can I find out what caused the exception?
Answer: If you are using Java, you could write exception routines to trap errors. Using tools such as JDeveloper also helps.
The error messages of our components are usually clearer. XSL-1900 indicates possible internal error or incorrect usage.
I am trying to generate an HTML form for inputting data using column names from the user_tab_columns
table and the following XSL code:
<xsl:template match="ROW"> <xsl:value-of select="COLUMN_NAME"/> <: lt;INPUT NAME="<xsl:value-of select="COLUMN_NAME"/>> </xsl:template>
although gt;
is generated as the greater than (>) character, lt;
is generated as #60;
. How do I generate the less than (<) character?
Answer: Use the following code:
<xsl:text disable-output-escaping="yes">entity-reference</xsl:text>
I cannot display HTML from XML. In my XML file, I store the HTML snippet in an XML tag:
<body.htmlcontent> <<table width="540" border="0" cellpadding="0" cellspacing="0"><tr><td><font face="Helvetica, Arial" size="2"><!-- STILL IMAGE GOES HERE --><img src="graphics/imagegoeshere.jpg" width="200" height="175" align="right" vspace="0" hspace="7"><!-- END STILL IMAGE TAG --><!-- CITY OR TOWN NAME GOES FIRST FOLLOWED BY TWO LETTER STATE ABBREVIATION --><b>City, state abbreviation</b> - <!-- CITY OR TOWN NAME ENDS HERE --><!-- STORY TEXT STARTS HERE -->Story text goes here.. <!-- STORY TEXT ENDS HERE --></font></td></tr></table> </body.htmlcontent>
I use the following in my XSL:
<xsl:value-of select="body.HTMLcontent" disable-output-escaping="yes"/>
However, the HTML output
<
still appears and all of the HTML tags are displayed in the browser. How do I display the HTML properly?
That doesn't look right. All of the less than (<) characters are #60;
in the code with an ampersand in front of them. They are still that way when they are displayed in the browser.
Even more confusing is that it works with oraxsl
, but not with XSLSample.java
.
Answer: Here's why:
oraxsl
internally uses void XSLProcessor.processXSL (style,source,printwriter);
XSLSample.java
uses DocumentFragment XSLProcessor.processXSL (style,source);
The former supports <xsl:output>
and all options related to writing output that might not be valid XML (including the disable output escaping). The latter is pure XML-to-XML tree returned, so no <xsl:output>
or disabled escaping can be used since nothing's being output, just a DOM tree fragment of the result is being returned.
Is there any site which has good examples or short tutorials on XSLT?
Answer: This site is an evolving tutorial on lots of different XML, XSLT, and XPath-related subjects:
http://zvon.vscht.cz/ZvonHTML/Zvon/zvonTutorials_en.html
Is there a list of features of the XSLT that the Oracle XDK uses?
Answer: Our version 2 parsers support the W3C Recommendation of w3c XSLT version 1.0, which you can see at http://www.w3.org/TR/XSLT
.
I am in the process of trying to convert an XML document from one format to another by means of an XSL (or XSLT) stylesheet. Before incorporating it into my Java code, I tried testing the transformation from the command line:
> java oracle.xml.parser.v2.oraxsl jwnemp.xml jwnemp.xsl newjwnemp.xml
The problem is that instead of returning the transformed XML file (newjwnemp.xml
), the above command just returns a file with the XSL code from jwnemp.xsl
in it. I cannot figure out why this is occurring. I have attached the two input files.
<?xml version="1.0"?> <employee_data> <employee_row> <employee_number>7950</employee_number> <employee_name>CLINTON</employee_name> <employee_title>PRESIDENT</employee_title> <manager>1111</manager> <date_of_hire>20-JAN-93</date_of_hire> <salary>125000</salary> <commission>1000</commission> <department_number>10</department_number> </employee_row> </employee_data> <?xml version='1.0'?> <ROWSET xmlns:xsl="HTTP://www.w3.org/1999/XSL/Transform"> <xsl:for-each select="employee_data/employee_row"> <ROW> <EMPNO><xsl:value-of select="employee_number"/></EMPNO> <ENAME><xsl:value-of select="employee_name"/></ENAME> <JOB><xsl:value-of select="employee_title"/></JOB> <MGR><xsl:value-of select="manager"/></MGR> <HIREDATE><xsl:value-of select="date_of_hire"/></HIREDATE> <SAL><xsl:value-of select="salary"/></SAL> <COMM><xsl:value-of select="commission"/></COMM> <DEPTNO><xsl:value-of select="department_number"/></DEPTNO> </ROW> </xsl:for-each> </ROWSET>
Answer: This is occurring most likely because you have the wrong XSL namespace URI for your xmlns:xsl="..."
namespace declaration.
If you use the following URI:
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
then everything will work.
If you use xmlns:xsl="-- any other string here --"
it will do what you're seeing.
I cannot find anything about using XSL. Can you help? I would like to get an XML and XSL file to show my company what they can expect from this technology. XML alone is not very impressive for users.
Answer: A pretty good starting place for XSL is the following page:
http://metalab.unc.edu/xml/books/bible/updates/14.html
It provides a simple discussion of the gist of XSL. XSL isn't really anything more than an XML file, so I don't think that it will be anymore impressive to show to a customer. There's also the main Web site for XSL which is:
http://www.w3.org/style/XSL/
I recall seeing discussions about the XSL processor producing more than one result from one XML and XSL. How can this can be achieved?
Answer: The XML Parser version 2 release 2.0.2.8 and above supports <ora:output>
to handle this.
|
Copyright © 2001, 2002 Oracle Corporation. All Rights Reserved. |
|