More Examples

In this section we provide a few more examples of server functions. We have implemented:

  • some of the XPath functions that did not find their way into X-Query;

  • particular string functions which might prove useful in both X-Query and XQuery 4;

  • a function similar to the XSLT document() function.

We call this server extension module xqx and name the package accordingly tamino.sxs.xqx. The complete source code, including the file Install.xml and the Javadoc HTML file, is contained in the directory sxsjxqx in the documentation set.


concat

Concatenates strings.

Syntax

public String concat (String op1, String op2)
public String concat3 (String op1, String op2, String op3)
public String concat4 (String op1, String op2, String op3, String op4)

Description

The original XPath concat() string function allows any number of arguments (at least 2). We have implemented the functions concat, concat3, and concat4 to cover cases with two, three, and four arguments. The implementation could hardly be simpler:

public String concat (String op1, String op2) {
  return op1+op2;
}
public String concat3 (String op1, String op2, String op3) {
  StringBuffer sb = new StringBuffer(op1);
  sb.append(op2);
  sb.append(op3);
  return sb.toString();
}
public String concat4 (String op1, String op2, 
                       String op3, String op4) {
  StringBuffer sb = new StringBuffer(op1);
  sb.append(op2);
  sb.append(op3);
  sb.append(op4);  
  return sb.toString();
}

Examples

xqx.concat(name/last, name/first)

constructs an ID from last name and first name.

xqx.concat3(birthDate,"T","04:30:00")

appends a time to a date.


contains

True if op1 contains op2.

Syntax

public boolean contains (String op1, String op2)

Description

The string function contains() is a bit more demanding:

public boolean contains (String op1, String op2) {
  return (op1.indexOf(op2) >= 0);
}

Examples

xqx.contains(title,"Moon in June")

is true for all titles containing "Moon in June". In contrast to the X-Query contains-operator (~=), this function is case sensitive.


substringBefore

Returns substring before op2.

Syntax

public String substringBefore (String op1, String op2)

Description

The original XPath name is substring-before().

public String substringBefore (String op1, String op2) {
  int i = op1.indexOf(op2);
  if (i > 0) return op1.substring(0,i);
  return "";
}

Examples

xqx.substringBefore(performedAt/time,"T")

returns the date part of dateTime element performedAt/time.

 
                   
                 

substringAfter

Returns substring after op2.

Syntax

public String substringAfter (String op1, String op2)

Description

The original XPath name is substring-after().

public String substringAfter (String op1, String op2) {
  int i = op1.indexOf(op2);
  if (i >= 0) {
    int b = op2.length()+i;
    if (b < op1.length()) return op1.substring(b);
  }
  return "";
}

Examples

xqx.substringAfter(performedAt/time,"T")

returns the time part of dateTime element performedAt/time.


substring

Returns substring from position p with length l.

Syntax

public String substring (String s, int p, int l)

Description

Two substring functions are provided in XPath:

  • substring(s, p, l) returns a substring of s starting at position p with length l.

  • substring(s, p) returns a substring of s starting at position p up to the end of the string.

Because Tamino server extensions do not support method overloading, we implement only the three-argument form. The length -1 indicates the two-argument version (substring up to end of string).

public String substring (String s, int p, int l) {
  p--;          // Java counts from 0, Xpath from 1
  if (l < 0) return s.substring(p);
  return s.substring(p,p+l);
}

Examples

xqx.substring(1999-05-01,6,2)

returns the month ("05").

xqx.substring(1999-05-01,6,-1)

returns the month and the day ("05-01").


trim

Removes white space from beginning and end.

Syntax

public String trim (String s)

Description

Here we implement a function that is not available in XPath but works similarly to the XPath string function normalize-space(). However, trim() only removes leading and trailing white space from a string, leaving white space in the interior of the string intact. Again, the implementation is trivial:

public String trim (String s) {
  return s.trim();
}

Examples

If a document instance of document type style contains an element:

<name>
    swing
</name>

then the simple path expression:

style/name

returns "swing" with leading and trailing carriage-return characters and blanks. In many cases this is unwanted, for example if we want to use the string as a search string or concatenate it with other strings.

xqx.trim(style/name)

removes these unwanted white space characters.


normalizeSpace

Normalizes white space.

Syntax

public String normalizeSpace (String s)

Description

The full implementation of normalize-space() requires a bit more coding:

public String normalizeSpace (String s) {
  StringBuffer sb = new StringBuffer(s.length());
  boolean whiteSpace = true;
  for (int i=0; i < s.length(); i++) {
    char c = s.charAt(i);
    if ((c==' ')||(c==13)||(c==10)||(c==9)) {
      if (!whiteSpace) {
        whiteSpace = true;
        sb.append(' ');
      }
    } else {
      sb.append(c);
      whiteSpace = false;
    }
  }
  if (whiteSpace) {
    sb.deleteCharAt(sb.length()-1);
  }
  return sb.toString();
}

Examples

If a document instance of document type album contains an element:

<title>
    Open Up 
    (Whatcha gonna do for the rest of your     life?)
</title>

then the simple path expression:

album/title

returns the title with all carriage-return, linefeed, tab, and blank characters.

xqx.normalizeSpace(album/title)

normalizes this string to:

    Open Up (Whatcha gonna do for the rest of your life?)

stringLength

Returns length of string.

Syntax

public int stringLength (String s)

Description

The original XPath name is string-length(). The implementation is trivial:

public int stringLength (String s) {
  return s.length();
}

Examples

xqx.stringLength(name/last)

returns the length of the element name/last including white space characters.

jazzMusician[xqx.stringLength(./name/last)=9]

returns all jazz musicians whose last name is 9 characters long.


qdoc

Fetches document specified by path.

Syntax

public String qdoc (String qpath)

Description

Finally, here is a function that is similar to the document() function in XPath, but constrains itself to documents stored in the same database. This allows us to implement the retrieval of the document via a Tamino callback function, instead of retrieving the document via an HTTP request.

The function takes one argument, namely an X-Query expression that identifies the document (or document part). This expression must include the collection name. Before returning a result, it strips off all of Tamino's packaging for query results and returns the data as a vanilla XML node (or node list).

public String qdoc (String qpath) 
                   throws java.lang.Exception {
  // split operand into collection and relative path
  int p = qpath.indexOf("/", 0);
  if (p<0) 
   throw(new Exception("Proper syntax is collection/path"));
  StringBuffer response = new StringBuffer(1024);
  // do query to Tamino via SXS callback
  int ret = SxsXMLXql (qpath.substring(0,p), 
                       qpath.substring(p+1), response);
  if (ret != 0)
    // Error handling as shown in section Derived elements
    // ....
  }
  // Create document string
  String  docstr = response.toString();
  // We have to isolate the returned node(s)
  int t = docstr.indexOf("<xql:result>", 0)+12;
  if (t >= 12) {
    int e = docstr.indexOf("</xql:result>", t);
    return docstr.substring(t,e);
  }
  return "";
}

Examples

Since qdoc() – in contrast to document() – does not require the full specification of a URL and removes the Tamino response wrapping, queries using qdoc() are significantly simpler. The following query finds all collaborations in which jazz musicians whose last name is "Parker" participated:

collaboration[jazzMusician/@ID=xqx.qdoc(
             "encyclopedia/jazzMusician[name/last='Parker']"
             )/@ID]

The next query finds all jazz musician documents taking part in such collaborations. We see that qdoc() can be nested. Note that we have to use the &quot; notation for the innermost level of string demarcations.

jazzMusician[@ID = xqx.qdoc(
  "encyclopedia/collaboration[jazzMusician/@ID=xqx.qdoc(
   'encyclopedia/jazzMusician[name/last=&quot;Parker&quot;]'
  )/@ID]")/jazzMusician/@ID]

Similarly, the following query returns all album documents that are the result of such a collaboration:

album[@albumNo = xqx.qdoc(
  "encyclopedia/collaboration[jazzMusician/@ID=xqx.qdoc(
   'encyclopedia/jazzMusician[name/last=&quot;Parker&quot;]'
  )/@ID]")/result/@albumNo]