Skip Headers

Oracle® Application Developer's Guide - XML 10g (9.0.4) Part Number B12099-01 |
Home | Contents | Index

# 4
Using XSL and XSLT

This chapter contains the following sections:

- Introducing XSL

- XSL Transformation (XSLT)

- XML Path Language (Xpath)

- CSS Versus XSL

- XSL References

- Frequently Asked Questions: XSL and XSLT

## Introducing XSL

XML documents have structure but no format. Extensible Stylesheet Language (XSL) adds formatting to XML documents.

XSL provides a way of displaying XML semantics. It can map XML elements into other formatting langauges such as HTML.

### The W3C XSL Specification

The W3C is developing the XSL specification as part of its Style Sheets Activity. XSL has document manipulation capabilities beyond styling. It is a stylesheet language for XML.

The July 1999 W3C XSL specification, was split into two separate documents:

- XSL syntax and semantics

- How to use XSL to apply style sheets to transform one document into another

The formatting objects used in XSL are based on prior work on Cascading Style Sheets (CSS) and the Document Style Semantics & Specification Language (DSSSL). XSL is designed to be easier to use than DSSSL.

Capabilities provided by XSL as defined in the proposal enable the following functionality:

- Formatting of source elements based on ancestry and descendency, position, and uniqueness

- The creation of formatting constructs including generated text and graphics

- The definition of reusable formatting macros

- Writing-direction independent stylesheets

- An extensible set of formatting objects.

#### XSL Specification Proposal

The XSL specification defines XSL as a language for expressing stylesheets. Given a class of arbitrarily structured XML documents or data files, designers use an XSL stylesheet to express their intentions about how that structured content should be presented; that is, how the source content should be styled, laid out, and paginated in a presentation medium, such as a window in a Web browser or a hand-held device, or a set of physical pages in a catalog, report, pamphlet, or book. Formatting is enabled by including formatting semantics in the result tree.

Formatting semantics are expressed in terms of a catalog of classes of formatting objects. The nodes of the result tree are formatting objects. The classes of formatting objects denote typographic abstractions such as page, paragraph, table, and so forth.

Finer control over the presentation of these abstractions is provided by a set of formatting properties, such as those controlling indents, word and letter spacing, and widow, orphan, and hyphenation control. In XSL, the classes of formatting objects and formatting properties provide the vocabulary for expressing presentation intent.

An implementation is not mandated to provide these as separate processes. Furthermore, implementations are free to process the source document in any way that produces the same result as if it were processed using the conceptual XSL processing model.

### Namespaces in XML

A namespace is a unique identifier or name. This is needed because XML documents can be authored separately with different DTDs or XML Schemas. Namespaces prevent conflicts in markup tags by identifying which DTD or XML Schema a tag comes from. Namespaces link an XML element to a specific DTD or XML Schema.

Before you can use a namespace marker such as `rml:`, `xhtml:`, or `xsl:`, you must identify it using the namespace indicator, `xmlns` as shown in the next paragraph.

See Also: http://w3.org/TR/REC-xml-names

### XSL Stylesheet Architecture

The XSL stylesheets must include the following syntax:

- Start tag stating the stylesheet, such as `<xsl:stylesheet2>`

- Namespace indicator, such as `xmlns:xsl="http//www.w3.org/TR/WD-xsl"` for an XSL namespace indicator and `xmlns:fo="http//www.w3.org/TR/WD-xsl/FO"` for a formatting object namespace indicator

- Template rules including font families and weight, colors, and breaks. The templates have instructions that control the element and element values

- End of stylesheet declaration, `</xsl:stylesheet2>`

## XSL Transformation (XSLT)

XSLT is designed to be used as part of XSL. In addition to XSLT, XSL includes an XML vocabulary for specifying formatting. XSL specifies the styling of an XML document by using XSLT to describe how the document is transformed into another XML document that uses the formatting vocabulary.

Meanwhile the second part is concerned with the XSL formatting objects, their attributes, and how they can be combined.

See Also: Chapter 20, "Using XML Parser for Java"

### XSLT 1.1 Specification

The W3C Working Group on XSL has just released a document describing the requirements for the XSLT 1.1 specification. The primary goal of the XSLT 1.1 specification is to improve stylesheet portability. The new draft is available at `http://www.w3.org/TR/xslt11req`

In addition to supporting user-derocessors have exploited the XSLT 1.0 extension mechanism to provide additional built-in transformation functionality. As useful built-in extensions have emerged, users have embraced them and have begun to rely on them.

However the benefits of these extensions come at the price of portability. Since XSLT 1.0 provides no details or guidance on the implementation of extensions, today any user-written or built-in extensions are inevitably tied to a single XSLT processor.

#### Goal 1. Improve Stylesheet Portability

The primary goal of the XSLT 1.1 specification is to improve stylesheet portability. This goal will be achieved by standardizing the mechanism for implementing extension functions, and by including in the core XSLT specification two of the built-in extensions that many existing vendors XSLT processors have added due to user demand:

- Support for multiple output documents from a transformation

- Support for converting a result tree fragment to a nodeset for further processing By standardizing these extension-related aspects which multiple vendor implementations already provide, the ability to create stylesheets that work across multiple XSLT processors should improve dramatically.

#### Goal 2. Support the New XML Specification

A secondary goal of the XSLT 1.1 specification is to support the new XML base specification.

The XSLT 1.1 specification proposal provides the requirements that will achieve these goals. The working group has decided to limit the scope of XSLT 1.1 to the standardization of features already implemented in several XSLT 1.0 processors, and concentrate first on standardizing the implementation of extension functions.

Standardization of extension elements and support for new XML Schema data type aware facilities are planned for XSLT 2.0.

## XML Path Language (Xpath)

A separate, related specification is published as the XML Path Language (XPath) Version 1.0. XPath is a language for addressing parts of an XML document, essential for cases where you want to specify exactly which parts of a document are to be transformed by XSL. For example, XPath lets you select all paragraphs belonging to the chapter element, or select the elements called special notes. XPath is designed to be used by both XSLT and XPointer. XPath is the result of an effort to provide a common syntax and semantics for functionality shared between XSL transformations and XPointer.

## CSS Versus XSL

W3C is working to ensure that interoperable implementations of the formatting model is available.

#### Cascading Stylesheets (CSS)

Cascading Stylesheets (CSS) can be used to style HTML documents. CSS were developed by the W3C Style Working Group. CSS2 is a style sheet language that allows authors and users to attach styles (for example, fonts, spacing, or aural cues) to structured documents, such as HTML documents and XML applications.

By separating the presentation style of documents from the content of documents, CSS2 simplifies Web authoring and site maintenance.

#### XSL

XSL, on the other hand, is able to tranform documents. For example, XSL can be used to transform XML data into HTML/CSS documents on the Web server. This way, the two languages complement each other and can be used together. Both languages can be used to style XML documents. CSS and XSL will use the same underlying formatting model and designers will therefore have access to the same formatting features in both languages.

The model used by XSL for rendering documents on the screen builds on years of work on a complex ISO-standard style language called DSSSL. Aimed mainly at complex documentation projects, XSL also has many uses in automatic generation of tables of contents, indexes, reports, and other more complex publishing tasks.

## XSL References

Examples on using XSL can be found throughout this manual. In particular, refer to the following chapters in Oracle9i Case Studies - XML Applications:

- "Customizing Content with XML: Dynamic News Application"

- "OracleAS Wireless Edition and XML"

- "Customizing Presentation with XML and XSQL: Flight Finder"

  See Also: http://www.mulberrytech.com/xsl/xsl-list/ http://www.builder.com/Authoring/XmlSpot/?tag=st.cn.sr1.ssr.bl_xml

## Frequently Asked Questions: XSL and XSLT

### How Do I Write an IF Statement in XSL That Tests for Values Within Tags?

What is the syntax to compare not an element but the value of the element? So far, the documentation I have read tests for tags but not values within the tags. Here is a portion of my XSL document:

    <xsl:template match="EmployeeList">
        <xsl:for-each select="employee">
             <xsl:value-of select="name"/>
             <xsl:value-of select="sal"/>
        </xsl:for-each>
    <xsl:template>

I want to construct an `IF` statement that will display the information of employees with salaries greater than 5000 in red. How do I insert the value of `sal` in the `IF` statement?

#### Answer

Here is the `IF` statement:

      <xsl:if expr="this.nodeTypedValue == 'INIZIATIVE'">
        .........
      </xsl:if>

### In an XSL Document, How Can We Select Specific Attributes?

We are merging an XML document with its XSL stylesheet. However the child attributes are not being returned when we use syntax of type:

    <xsl:value-of select="Foo/Bar"/>

in the XSL document. Why not? This seems to work fine in other XML parsers.

#### Answer

The XPath expression, `Foo/Bar`, is only designed to select the value of the `<Bar>` element contained in the `<Foo>` element. It will return the concatenation of all text nodes in the nested content of that `<Bar>` element, but certainly is not designed to select any text values in attributes.

For this, you would need the syntax: `Foo/Bar/@SomeAttr`

to select one attribute and...

`Foo/Bar/@*`

to select all the attributes of `<Bar>`

### When Converting XML to HTML, Why Do I get "Unexpected EOF"?

I am trying to render a simple XML document to an HTML form, using the following XML and XSLT. The transformation fails with the message "Unexpected EOF" using the `XSLSample.java` provided with the XML parser for Java V2. When I remove the `<td></td>` from the transformation (which contains the XPath expression of the type`{ELEMENT}`, the transformation is fine.

Here is the XML:

    <ROWSET>
       <ROW>
             <ELEM0>Al</ELEM0>
             <ELEM1>Gore</ELEM1>
             <ELEM2></ELEM2>
             <ELEM3></ELEM3>
             <ELEM4></ELEM4>
       </ROW>
    .....

Here is the XSLT:

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/">
    <html>
     <head>
       <title>Value Upload</title>
     </head>
       <body bgcolor="#FFFFFF">
         <form method="post" action="">
         <xsl:for-each select="ROWSET">
           <table border="1" cellspacing="0" cellpadding="0">
              <xsl:for-each select="ROW">
                <tr>
              <td><input type="text" name="elem0" value="{ELEM0}" size="10"
                    maxlength="20"></td>
              <td><input type="text" name="elem1" value="{ELEM1}" size="10"
                    maxlength="20"></td>
              ...
              </xsl:for-each>
         </form>
       </body>
     </html>
     </xsl:template>
     </xsl:stylesheet>

#### Answer

You need to put a slash (/) for the input element, as follows:

    <td> <input xxxx /> </td>

### Whitespace: Why are my Resulting Values Multiplied by 2?

Is there a syntax error in the following code?

Here is `djia.xml`:

    <?xml version="1.0" encoding="Shift_JIS"?>
    <?xml-stylesheet type="text/xsl" href="djia.xsl"?>
    <djia>
      <company>ALCOA</company>
      <company>ExxonMobil</company>
      <company>McDonalds</company>
      <company>American Express</company>
    </djia>

Here is `djia.xsl`:

    <?xml version="1.0" encoding="Shift_JIS"?>
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"version="1.0">
    <xsl:output method="xml" encoding="Shift_JIS"/>
    <xsl:template match="/djia">
    <page>
         <xsl:apply-templates/>
    </page>
    </xsl:template>
    <xsl:template match="company">
         <xsl:value-of select="current()"/>
         <xsl:value-of select="position()"/>:
         <xsl:if test="current()=../company[last()]"> last one!
         </xsl:if>
    </xsl:template>
    </xsl:stylesheet>

yields the following:

    <?xml version="1.0" encoding="Shift_JIS" ?>
    <page>ALCOA2: ExxonMobil4: McDonalds6: American Express8: last one!</page>

Why the resulting numbers are multiplied by 2?

#### Answer

The answer is whitespace. When your `/djia` template does `<xsl:apply-templates/>` it selects all child nodes of `<djia>`. Since your `djia.xml` is nicely indented, that means that child nodes of `<djia>` are:

1. TextNode containing CR + spaces to make next element look indented

2. <company> (with value ALCOA)

3. TextNode containing CR + spaces to make next element look indented

4. <company> (with value ExxonMobil)

5. TextNode containing CR + spaces to make next element look indented

6. <company> (with value McDonalds)

7. TextNode containing CR + spaces to make next element look indented

8. <company> (with value American Express)

9. TextNode containing CR + spaces to put </djia> on next line.

So as the XSLT processor is processing this current node list, the `position()` function is the position in the current node list, which are 2, 4, 6, 8 for the `<company>` element.

You should be able to fix the problem by adding a top level:

     <xsl:strip-space elements="*"/>

However, a bug in XDK for Java currently prevents this from working correctly. One workaround is to use:

    <xsl:apply-templates select="company"/>

instead of only:

    <xsl:apply-templates/>

### How Can I Specify a NULL Indicator in XSL?

I want my XSLT to output `<mytag null="yes"/>` when my corresponding source XML is `<mytag />` or`<mytag NULL="YES"/>`. How do I specify that within my XSLT?

#### Answer

Use the following syntax:

    <xsl:template match="mytag">
      <!-- If there are no child nodes -->
      <xsl:if test="not(node())">
        <mytag null="yes"/>
      </xsl:if>
    </xsl:template>

### How Can Transfer Tag Names in XSLT?

I need to use XSLT to change my XML code from:

    <REF_STATUS>
     ...
    </REF_STATUS>

to:

    <REF index="STATUS">
    ...
    </REF>

and similar code for `REF_VATCODE` and `REF_USFLG`. Here is the first attempt I wrote, which works:

    <!-- fix REF_STATUS nodes -->
    <xsl:template priority="1" match="REF_STATUS">
      <xsl:element name="REF">
       <xsl:attribute name="index">STATUS</xsl:attribute>
        <xsl:apply-templates/>
      </xsl:element>
    </xsl:template>

    <!-- fix REF_USFLG nodes -->
    <xsl:template priority="1" match="REF_USFLG">
      <xsl:element name="REF">
       <xsl:attribute name="index">USFLG</xsl:attribute>
        <xsl:apply-templates/>
      </xsl:element>
    </xsl:template>

    <!-- fix REF_VATCODE nodes -->
    <xsl:template priority="1" match="REF_VATCODE">
      <xsl:element name="REF">
       <xsl:attribute name="index">VATCODE</xsl:attribute>
        <xsl:apply-templates/>
     </xsl:element>
    </xsl:template>

There are three tag names all beginning with `REF_`, that are changed into the `REF` tagname with and index attribute equal to the remainder of the original tag name. I'd like to make one rule which matches all of these and does the correct transformation. Here is one attempt:

    <xsl:template priority="1" match="starts-with(local-name(),'REF_')">
      <xsl:element name="REF">
       <xsl:attribute name="index">
        <xsl:value-of select="substring-after(local-name(),'REF_')"/>
       </xsl:attribute>
        <xsl:apply-templates/>
      </xsl:element>
    </xsl:template>

Unfortunately, I get this error message:

    Error occurred while processing elName.xsl: XSL-1013: Error in expression:
    'starts-with(local-name(),'REF_')'.

What is wrong with the above expression?

#### Answer

The following works for me:

Note the `match="starts-with(..)"` is illegal because it is not a valid match pattern. You will need:

    match="*[starts-with(local-name(.),'REF_')]"

as shown below:

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
      <!-- Identity Transform -->
      <xsl:template match="node()|@*">
        <!-- Copy the current node -->
        <xsl:copy>
          <!-- Including any attributes it has and any child nodes -->
          <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
     </xsl:template>

    <xsl:template priority="2" match="*[starts-with(local-name(),'REF_')]">
      <REF index="{substring-after(local-name(.),'REF_')}">
        <xsl:apply-templates/>
      </REF>
     </xsl:template>
    </xsl:stylesheet>

This transforms a document like:

    <foo>
       <bar>
         <REF_STATUS>
            <baz/>
         </REF_STATUS>
         <zoo>
            <REF_USFLG>
               <boo/>
            </REF_USFLG>
         </zoo>
       </bar>
    </foo>

into the result:

    <foo>
       <bar>
         <REF index="STATUS">
            <baz/>
         </REF>
         <zoo>
            <REF index="USFLG">
               <boo/>
            </REF>
         </zoo>
       </bar>
    </foo>

### How Do I Convert A String to a Nodeset in XSL?

#### Question 1

The XML we receive is wrapped with extra code using CDATA notation. My XSL is not picking up the elements in the CDATA section. What do I need to do?

#### Answer 1

Inside a `<![CDATA[ ]]>` are not elements and attributes for querying with XPath. They are just literal characters (angle brackets, names, and quotes) that look like elements and attributes, but are not in the infoset tree as separate nodes.

Inside a CDATA there is just a single text node. XSL will not pick up elements in the CDATA. The best you can do is:

- Match on string content of the CDATA

- Programmatically parse the document and programmatically replace the CDATA node by the result of parsing the CDATA node's content as an XML document.

- Extract and parse the string-content of the CDATA and process that with XSLT

#### Question 2

In one of your examples, I found an XSL file, `toolbar.xsl`, that does what appears to be converting strings to a nodeset by doing the following XSL:

    <xsl:variable name="barns"select="my:nodeset($bar)"/>
    <xsl:stylesheet version="1.0"xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:my="http://www.oracle.com/XSL/Transform/java/oracle.xml.parser.v2.Extensio
    ns"exclude-result-prefixes="my">
        <xsl:template match="/">
          <xsl:call-template name="toolbar">
            <xsl:with-param name="bar">
              <toolbar>
                 <button name="xxx" url="www.oracle.com"/>
              </toolbar>
            </xsl:with-param>
          </xsl:call-template>
        </xsl:template>
    ...

Is my observation correct? I have extracted the CDATA section into a variable, but I think I need to convert it to a nodeset. When I tried it using `AsyncTransformSample.java` in TransView bean, I get the error:

    XSL-1045: Extension function error: Class not found
    'oracle.xml.parser.v2.Extensions'

Is this part of the standard packages or do I need to import it. The import statement:

    import oracle.xml.parser.v2.*;

is already in AsyncTransformSample.

#### Answer 2

No. The `ora:node-set()` converts result tree fragments to nodesets, not strings to nodesets. To convert strings to nodesets you have to parse the string. XSLT does not have a built-in `parse-string()` function, so we can build one as a Java extension function. See Chapter 16 in Developing Oracle XML Applications by Steve Muench (O'Reilly) for details on developing and debugging Java XSLT extension functions.

Here is an example Java class that parses a string and returns a nodeset containing the root node of the parsed XML document in a string. If there is an error during parsing, it returns an empty nodeset.

    import org.w3c.dom.*;
    import org.xml.sax.SAXException;
    import oracle.xml.parser.v2.*;
    import java.io.StringReader;
    public class Util {
      public static NodeList parse (String s) {
        // Create a new parser
        DOMParser d = new DOMParser();
        try {
          // Parse the string into an in-memory DOM tree
          d.parse( new StringReader(s) );
          // Return a node list containing the root node
          return ((XMLDocument)d.getDocument()).selectNodes("/");
        }
        catch (Exception e) {
          // Return an empty nodelist in case of an error.
          return (new XMLDocument()).getChildNodes();
        }
      }
    }

Here is a sample `message.xml` file that simulates the scenario you are in with some XML in the body of an XML document enclosed in a CDATA section.

    <message>
      <from>Steve</from>
      <to>Albee</to>
      <body><![CDATA[
        <order id="101">
          <item id="12" qty="10"/>
          <item id="13" qty="3"/>
        </order>
      ]]></body>
    </message>

Here is a sample stylesheet that processes the `<message>` document, parses and captures the subdocument (that is encoded as a CDATA text node in the `<body>`) in an XSL variable, and then uses `<xsl:for-each>` to select information out of the `$body` variable containing the now-parsed message body. Here we just print out the identifiers of the `<order>`, but this will give you a general idea.

    <xsl:stylesheet  version="1.0"
      xmlns:util="http://www.oracle.com/XSL/Transform/java/Util"
      xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
      <!--
       | Above, we've associated the "util" namespace prefix
       | with the appropriate namespace URI that maps to
       | the "Util" class. The Util.java class is not in any
       | package, otherwise the URI would have looked like
       | http://www.oracle.com/XSL/Transform/java/my.pkg.Util
       +-->

      <xsl:template match="message">
        <!--
         | Use the parse() function in the util namespace
         | to parse the string value of the <body> child
         | element of the current <message> element, and
         | return the root node of the document
         +-->
        <xsl:variable name="body" select="util:parse(body)"/>
        <xsl:text>Items Ordered</xsl:text><xsl:text>&#xa;</xsl:text>
        <xsl:for-each select="$body/order/item">
          <xsl:value-of select="@id"/><xsl:text>&#xa;</xsl:text>
        </xsl:for-each>
      </xsl:template>
    </xsl:stylesheet>

### In XSL, How Can I Correctly Convert an XML Document Tag to a Link in HTML?

I have a question about XSL. My XML document is similar to the following:

    <ROW num="1">
      <TITLE>New Java Classes</TITLE>
       <URL>/products/intermedia/</URL>
       <DESCRIPTION>&#60;a href=\"/products/intermedia/\">Java classes for
       Servlets and JSPs&#60;/a>are available.
       </DESCRIPTION>
    </ROW>

When I use XSL to display the XML document in HTML, the description is not displaying as a link eventhough I am specifying it as `"&#60;a href=\"/products/intermedia/\">"` in XML.

My XSL file is:

    <xsl:template>
      <P><FONT face="arial" size="4"><B>
      <xsl:value-of disable-output-escaping="yes" select="TITLE"/>
      </B> </FONT><BR></BR><FONT size="2">
      <xsl:value-of disable-output-escaping="yes" select="DESCRIPTION"/></FONT>
      </P>
    </xsl:template>

#### Answer

You can simply build the `<a>` tag in your XSL transform. Do something like this:

    <?xml version="1.0"?>
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="html"/>
     <xsl:template match="/">
      <xsl:for-each select="rowset">
       <table border="1">
          <th>Category</th>
     <th>ID</th>
     <th>Title</th>
     <th>Thumbnail</th>
      <xsl:for-each select="row">
       <tr>
       <td><xsl:value-of select="category"/> </td>
       <td><xsl:value-of select="id"/> </td>
       <td><a href="Present.jsp?page=PRES_VIEW_SINGLE&amp;id={id}"><xsl:value-of
    select="title"/> </a></td>
       <td><img src="/servlets/thumb?presentation={id}&amp;slide=0" /></td>
      </tr>
     </xsl:for-each>
     </table>
    </xsl:for-each>
    </xsl:template>
    </xsl:stylesheet>

### Am I Using the Correct XSL Headers for my WML Transformation?

I am using `oracle.xml.async.XSLTransformer` included in XDK for Java v2 to perform an XSL transformation on an XML document. I need a WML output. My stylesheet contains the following code:

    <?xml version="1.0" encoding="ISO-8859-1"?>
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" omit-xml-declaration="no" encoding="ISO-8859-1"/>
    <xsl:output doctype-system="http://www.wapforum.org/DTD/wml_1.1.xml"
    doctype-public="-//WAPFORUM//DTD WML 1.1//EN"/>

...

When I check the transformation using a servlet, I get the following error in my WAP emulator:

    "Received HTTP status: 502 - WML Encoding Error, 1:com.sun.xml.parser/P-076
    Malformed UTF-8 char

Is an XML encoding declaration missing? In fact, the WML generated is not including any XML header information. The output starts like this:

     <wml>
     <card id="gastronomia" title="Mis direcciones de gastronomia"><p>Mis
    direcciones de gastronomia</p>
    ...

How do I get the transformer to output the XML header:

`"<?xml version="1.0" encoding="ISO-8859-1"?>"`

#### Answer

Use `oracle.xml.parser.v2.XSLProcessor`. Also ensure your stylesheet has:

    <xsl:output method="xml"/>

just inside the `<xsl:stylesheet>`, and outside of any `<xsl:template>`

Also ensure that you're using the following API:

`processXSL(stylesheet,source,printwriter)`

### In an XSL Transformation, How Do I Ensure that the DTD File Can be Located?

My BC4J source XML file has the following line that refers to the DTD:

    <!DOCTYPE ViewObject SYSTEM "jbo_03_01.dtd">

When transforming the file, this line results in an error, saying it cannot find `jbo_03_01.dtd`. The DTD file is in my classpath.

#### Answer

There are two solutions to this.

- Extract`jbo_03_01.dtd` from `jbomt.zip` and put it in the same directory as your VO files. This is complicated if you have VO files at several different directory levels.

- Use the trick that BC4J itself uses when parsing its own XML metadata files when parsing in your program:

      DOMParser d = new DOMParser();
             // read DTD as a resource from the classpath
             InputStream is = ...getResourceAsStream("/jbo_03_01.dtd");
             d.parseDTD( is );
             DTD dtd = d.getDoctype();

d.setDoctype( dtd ); // set and cache the DTD to use.

// Now, subsequences calls to d.parse() will

           // use the cached version of jbo_03_01.dtd

Then transform the result using XSLStylesheet and `XSLProcessor.process(style,source,printwriter)`.

### In XSL, How to Prevent the Namespace Definition from Being Repeated

My second question relates to namespaces. I have the following piece of code in my stylesheet:

    <xsl:attribute name="data:text">
      <xsl:value-of select="@Name"/>@ipet:dataBindingObject
    </xsl:attribute>

At the top of my stylesheet, I have defined the `marlin` namespace:

    xmlns:data="http://xxx.us.yyy.com/cabo/marlin"

In the resulting XML file (the `marlin` UIX file), the namespace definition is repeated for each element:

    <messageTextInput id="Status" name="Status" prompt="Status"
    required="yes"xmlns:data="http://xxx.us.yyy.com/cabo/marlin"
    data:text="Status@ipet:dataBindingObject" rows="1" maximumLength="3"
    columns="3"/>

#### Answer

Try defining the data namespace prefix on the document element in your XSLT root template. If it is defined at a higher level in the result tree we may notice that and not output it on each lower level element.

JDeveloper9i has virtual Virtual Objects (VOs) that expose the metadata of aVO kind of like the database `X$` views. This means that you could use the normal `VO.writeXML()` method against one of these virtual metadata views to perform operations like I think you are trying to do to render a data-driven output based on the structure of a given VO.

### How Do I Pass a Parameter from a Java Program to an XSL Stylesheet?

Is there a way to pass a parameter from a Java program to an XSLT stylesheet using Oracle XSL processor? The XSLT standard states that "...XSLT does not define the mechanism by which parameters arepassed to the stylesheet." (see `http://www.w3.org/TR/xslt#variable-values`). This is possible, but is a vendor-dependant implementation. However, none of the XSL constructors in the `OracleXSLprocessor` seems to allow for this.

We need to pass in an integer to a stylesheet and use the `xsl:position()` function to extract a document fragmentfrom an XML doc. For example:

    <xsl:templatematch="ROW">
    <xsl:if test="position()=1">
      SELECT DISTINCT sp.site_datatype_id
      FROM ref_hm_site_pcode sp
      WHERE sp.hm_site_code = '<xsl:value-ofselect='HM_SITE_CODE'/>'
      AND sp.hm_pcode = '<xsl:value-ofselect='HM_PCODE'/>'
    </xsl:if>
    </xsl:template>

However, instead of `position()=1`, we need to substitute a parameter, such as `$1`.

How can we do this?

#### Answer

If you have a top-level parameter declared in your stylesheet, such as:

    <xsl:stylesheet ... >
       <!-- declare top-level $foo parameter, default value to 5 -->
       <xsl:param name="foo" select="5"/>
       <xsl:template match="/">
       <xsl:if test="$foo=10">
         :

Then you can use the following methods on `oracle.xml.parser.v2.XSLStylesheet` to control parameters:

- `resetParams()`

- `setParam()`

To set the parameter named `foo` to the number 10, use the following:

    myStylesheet.setParam("foo","10");

To set `foo` to the string `ten`, you need to quote it:

    myStylesheet.setParam("foo","'ten'");

#### Question 2

If I need to pass parameters to the stylesheet in a Java program, what Java class must I use?

Currently, we use:

    processXSL(XSLStylesheet xsl,XMLDocument xml)

What method canI use to pass the parameters?

#### Answer 2

See:

- `XSLStylesheet.setParam()`

- `XSLStylesheet.resetParams()`

### How Can I Resolve the Error XSL-1009 Attribute 'XSL Version' Not Found in HTML?

We used `Note:104675.1` from `http://metalink.oracle.com`, that explains how to use the XDK to retrieve XML data from Oracle and transform it to HTML.

We can generate the XML output file but when we try to generate the HTML output by using the file, `Emp.xsl`, which has the following argument:

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

it shows error XSL-1009 ATTRIBUTE 'XSL VERSION' NOT FOUND IN 'HTML'

- What is the right argument for the XSL file? We tried `<xsl:stylesheet xmlns:xsl="http://www.w3.org/XSL/Transform/1.0" version="1.0">` and it works but the HTML output does not have any HTML tag at all, just pure data.

- I have never seen the HTML output generated from the XMLParser so I do not know whether it will generate HTML tags for me automatically or not.

What should the HTML output file look like?

#### Answer

You must add `xsl:version="1.0"` attribute to your `<html>` element.

### What XPath Expression Will Retrieve Only Terminal Child Elements?

Can you tell me what XPath expression I should use to retrieve only terminal child elements (that is, elements which don't have any child elements) from a specified element. For example, I want to use an XPath expression to return only the `TABLE` child elements highlighted in red below:

    <TABLE>
         <ID>1</ID>
         <NAME>1</NAME>
         <SIZE>1</SIZE>
         <COLUMNS>
            <COLUMN>
                <ID>1</ID>
                <NAME>Customers</NAME>
            <COLUMN>
            <COLUMN>
                <ID>c</ID>
                <NAME>Categories</NAME>
            <COLUMN>
         <COLUMNS>
         <DATE_CREATED>01/10/2000</DATE_CREATED>
      </TABLE>

#### Answer 1

A possible solution is the following:

    <?xml version='1.0'?>
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:template match="TABLE">
      <xsl:apply-templates select="child::*[not(child::*)]"/>
    </xsl:template>
    </xsl:stylesheet>

#### Answer 2

The expression you want is:

    /TABLE/*[count(child::*) = 0]

or

    /TABLE/*[not (child::*)]

You can omit the child axis, so above expression is the same as:

    /TABLE/*[count(*) = 0]

or

    /TABLE/*[not (*)]

### Child Attributes are Not Returned After Applying XSL Stylesheet

We are merging an XML document with its XSL stylesheet. Child attributes are not being returned when they are using syntax of type:

    <xsl:value-of select="Foo/Bar"/>

in the XSL document. This seems to work fine in other XML parsers including XML Spy and Stylus.

#### Answer

The XPath expression `Foo/Bar` is only designed to select the value of the `<Bar>` element contained in the `<Foo>` element. It will return the concatenation of all text nodes in the nested content of that `<Bar>` element, but certainly is not designed to select any text values in attributes. For this, you'd need the syntax: Foo/Bar/@SomeAttr to select one attribute and...

    Foo/Bar/@*    to select all the attributes of <Bar>.

| Copyright © 2001, 2003 Oracle Corporation. All Rights Reserved. |
Home | Contents | Index