Ravana Home

RAVScript

UserGuide

Example

Download

Contact

 

 

scriptlogo.gif - 3243 Bytes

Usage

From command line

runscript inputFileNAme outputFileName scriptFileName

From the API

The bsh.Transformer class is a helper class to invoke a transformation from within Java Applications.

Create a new Transformer object, and call transform():

import org.jdom.Document;

Document in = ..// input document
Reader script = ..// reader for script
Transformer t = new Transformer();
Document out = t.transform(in, script);

Dependencies

RAV Script is an extension of Beanshell, hence the syntax is a superset of Beanshell. Beanshell has syntax very similar to Java, but if you want to learn more, Visit www.beanshell.org to learn more.

RAV Script uses JDOM for the XML document model. It is not necessary to be a JDOM expert to use RAV Script, but for advanced users, visit www.jdom.org to learn about JDOM.

Scripting

When used for general scripting, Ravscript is basically a BeanShell script, with the extensions explained below. However, remember that unlike BeanShell, local variables in the calling context are made available to declared methods that are called.

Transformations

A RAV Script Transformation converts an input JDOM Document to an output JDOM Document using rules in a script.

The script should have one call to root(), to initialize the output document. The rest of the script is all about adding children to this document.

The script has two context variables, $input and $output, which are fundamental for how RAV Script works. These variables need not be referred directly in the script, as they are used behind the scenes.

$input is initialized with the root element of the input document, and changes when the processing context changes. The processing context changes inside a foreach(String xpath) statement (the syntax is explained later). Inside the foreach statement loop, the $input context variable takes the value of each XML node matched by the XPath string. The idea is similar to match() in XSLT.

$output has to be initialized by calling root(Element r) once within the script. This sets a JDOM Element as the initial parent. After the call, addelem statements are used to add children to the parent. If there is a block defined with the addelem statement, the $output context variable takes the value of the element just added, and becomes the new parent. So within the block, any use of addelem will result in adding children to the new parent (not the root).

Changes to BeanShell

Unlike Java or Beanshell, RAVScript makes local variables available to called methods which are declared in the script. (For those familiar with Beanshell, the NameSpace of the method is a child of calling context's Namespace). So you can declare methods and call them within the main script, and $input and $output will be propogated behind the scenes. This is similar in principle to apply-templates in XSLT.

$input can be accessed anywhere in the script, and $output can be accessed anywhere after the call to root(). However this is not necessary for most purposes.

Extensions to BeanShell syntax

1. Element initialization
XML Elements can be created using XML-like syntax:
   x = <x att1="y"> "my text" </x>;
   y = <y att1="x"/>;
   z = <z> <x> "some more text" </x> <x> "foo" </x> </z>;

This syntax is merely a shortcut for creating Elements. So although they can appear to be empty, you can add children to them later. Note the nested children in the 'z' Element. The syntax is quite flexible. You could get the same results as above with:

   String xtext = "my text";
   x = <x att1 = "y">xtext </x>; // text set from a variable
   String att1text = "x";
   y = <y att1=att1text/>;  // attribute set from avariable
   String more = " more ";
   z = <z> <x> "some" + more + "text" </x> <x> "foo" </x> </z>; // text is 
                                    // a combination of string literals and a variable

Note that this is not pure XML, but designed to look as close to XML as possible.
For places where arbitrary text can go (ie. attribute values and text), you can use one of :
     a. A String literal (eg: "my text")
     b. A variable identifier (eg: xtext)
     c. An expression which contains additions of the above (eg: "some" + more)
     d. If the text is too complex to be created by any of the above (it really shouldn't
       be), then you can enter an arbitrary expression that evaluates to a String within
       <% ... %>  (like in JSPs)
         eg: m = <m> <% "e = " + (m * c * c ) + " j" %> </m>;

You can also specify a NameSpace for Elements or Attributes.
The NameSpace has to be defined in a variable prior to usage.
eg:

    NameSpace ns = Namespace.getNamespace("ns","http://xxx/xxx");
    e = <ns:e> "element with namespace" </ns:e>;
    a = <a ns:att="attribute with namespace" />;

2. foreach
Used to match nodes in the input document using XPath expressions, and act upon them. foreach statements can be nested. In nested foreach statements, XPath is applied to the matching Nodes of the enclosing foreach statement.
eg:
   foreach ("x")
   {
      print( "found an x" ); // print is a Beanshell shortcut to print to console
      foreach ("y")
      {
         print( "found an x/y");
      }
   }

When foreach is used in the above example, the XPath expression “x” is applied on $input, and the results are assigned to $input in each iteration.

It is also possible to match nodes in documents (or elements) other than the input document. This effectively enables multiple input documents, something not possible with XSLT (at least with version 1.0).

   z = <z> <x> "some more text" </x> <x> "foo" </x> </z>;

   foreach ("x" in z) // Xpath applied on the variable z, not on $input
   {
      print( "found an x" );
      foreach ("y/z")  // This time Xpath is applied on $input
      {
         print( "found an x/y/z");
      }
   }

In the final variation, foreach can assign the result of foreach to a variable other than $input

   z = <z> <x> "some more text" </x> <x> "foo" </x> </z>;

   foreach foo ("x" in z) // Xpath applied on the variable z, result assigned to foo
   {
      print( "found an x" );
      foreach ("y/z" in foo)  // Xpath is applied on foo
      {
         print( "found an x/y/z");
      }
   }

3. addelem
addelem is used to add child Elements to the current output context.
addelem statements can have a block, so that subsequent addelem statements create children for the new output context.
eg:
   Converting <root> <x> <y> foo </y> <y> bar </y> </x> </root>
   to <root> <xx> <yy> foo </yy> <yy> bar </yy> </xx> </root>

   foreach ("x")
   {
      addelem <xx/>
      {
         foreach ("y")
         {
            addelem <yy> text() </yy>; // See below for explanation of text()
         }
      }
   }

In the above example, addelem adds children to $output. It is also possible to add children to other elements using the following syntax:

y = <y> “the root” </y>;

addelem <x> to y;

4. root
root has to be called once before any addelem statements, to initialize the root element of the output document.
eg:
   Element e = new Element("root");
   root(e);
or
   root(<root/>);
   
root should not be called more than once, as this will cause an error.

5. Helper functions: text, attribute, evaluate, valueOf, copy, compare
These functions are implemented as scripted commands, not extensions to the BeanShell Grammar. You can define similar commands in the src/bsh/commands directory.
   text() returns the text of the current input context Element.
   attribute(String attributeName) returns an attribute value of the current input context  ($input).
   evaluate(String xpath) returns the list of nodes matched by evaluating the xpath expression on the current input context.
   valueOf(String xpath) returns the String value of the first node selected by the xpath expression being evaluated on $input.
   copy() returns a copy of the input context (using clone()).
   compare(String xpath, String value) returns the boolean result of comparing valueOf(xpath) to value
.

 

template provided by:
 
A+ Templates

Copyright © 2002 ravana.com. All rights reserved