286N/A/*
286N/A * reserved comment block
286N/A * DO NOT REMOVE OR ALTER!
286N/A */
286N/A/*
286N/A * Copyright 1999-2004 The Apache Software Foundation.
286N/A *
286N/A * Licensed under the Apache License, Version 2.0 (the "License");
286N/A * you may not use this file except in compliance with the License.
286N/A * You may obtain a copy of the License at
286N/A *
286N/A * http://www.apache.org/licenses/LICENSE-2.0
286N/A *
286N/A * Unless required by applicable law or agreed to in writing, software
286N/A * distributed under the License is distributed on an "AS IS" BASIS,
286N/A * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
286N/A * See the License for the specific language governing permissions and
286N/A * limitations under the License.
286N/A */
286N/A/*
286N/A * $Id: ExsltStrings.java,v 1.1.2.1 2005/08/01 02:08:48 jeffsuttor Exp $
286N/A */
286N/Apackage com.sun.org.apache.xalan.internal.lib;
286N/A
286N/Aimport java.util.StringTokenizer;
286N/A
286N/Aimport javax.xml.parsers.DocumentBuilderFactory;
286N/Aimport javax.xml.parsers.FactoryConfigurationError;
286N/Aimport javax.xml.parsers.ParserConfigurationException;
286N/A
286N/Aimport com.sun.org.apache.xpath.internal.NodeSet;
286N/A
286N/Aimport org.w3c.dom.Document;
286N/Aimport org.w3c.dom.Element;
286N/Aimport org.w3c.dom.Node;
286N/Aimport org.w3c.dom.NodeList;
286N/Aimport org.w3c.dom.Text;
286N/A
286N/A/**
286N/A * This class contains EXSLT strings extension functions.
286N/A *
286N/A * It is accessed by specifying a namespace URI as follows:
286N/A * <pre>
286N/A * xmlns:str="http://exslt.org/strings"
286N/A * </pre>
286N/A * The documentation for each function has been copied from the relevant
286N/A * EXSLT Implementer page.
286N/A *
286N/A * @see <a href="http://www.exslt.org/">EXSLT</a>
286N/A
286N/A * @xsl.usage general
286N/A */
286N/Apublic class ExsltStrings extends ExsltBase
286N/A{
286N/A /**
286N/A * The str:align function aligns a string within another string.
286N/A * <p>
286N/A * The first argument gives the target string to be aligned. The second argument gives
286N/A * the padding string within which it is to be aligned.
286N/A * <p>
286N/A * If the target string is shorter than the padding string then a range of characters
286N/A * in the padding string are repaced with those in the target string. Which characters
286N/A * are replaced depends on the value of the third argument, which gives the type of
286N/A * alignment. It can be one of 'left', 'right' or 'center'. If no third argument is
286N/A * given or if it is not one of these values, then it defaults to left alignment.
286N/A * <p>
286N/A * With left alignment, the range of characters replaced by the target string begins
286N/A * with the first character in the padding string. With right alignment, the range of
286N/A * characters replaced by the target string ends with the last character in the padding
286N/A * string. With center alignment, the range of characters replaced by the target string
286N/A * is in the middle of the padding string, such that either the number of unreplaced
286N/A * characters on either side of the range is the same or there is one less on the left
286N/A * than there is on the right.
286N/A * <p>
286N/A * If the target string is longer than the padding string, then it is truncated to be
286N/A * the same length as the padding string and returned.
286N/A *
286N/A * @param targetStr The target string
286N/A * @param paddingStr The padding string
286N/A * @param type The type of alignment
286N/A *
286N/A * @return The string after alignment
286N/A */
286N/A public static String align(String targetStr, String paddingStr, String type)
286N/A {
286N/A if (targetStr.length() >= paddingStr.length())
286N/A return targetStr.substring(0, paddingStr.length());
286N/A
286N/A if (type.equals("right"))
286N/A {
286N/A return paddingStr.substring(0, paddingStr.length() - targetStr.length()) + targetStr;
286N/A }
286N/A else if (type.equals("center"))
286N/A {
286N/A int startIndex = (paddingStr.length() - targetStr.length()) / 2;
286N/A return paddingStr.substring(0, startIndex) + targetStr + paddingStr.substring(startIndex + targetStr.length());
286N/A }
286N/A // Default is left
286N/A else
286N/A {
286N/A return targetStr + paddingStr.substring(targetStr.length());
286N/A }
286N/A }
286N/A
286N/A /**
286N/A * See above
286N/A */
286N/A public static String align(String targetStr, String paddingStr)
286N/A {
286N/A return align(targetStr, paddingStr, "left");
286N/A }
286N/A
286N/A /**
286N/A * The str:concat function takes a node set and returns the concatenation of the
286N/A * string values of the nodes in that node set. If the node set is empty, it returns
286N/A * an empty string.
286N/A *
286N/A * @param nl A node set
286N/A * @return The concatenation of the string values of the nodes in that node set
286N/A */
286N/A public static String concat(NodeList nl)
286N/A {
286N/A StringBuffer sb = new StringBuffer();
286N/A for (int i = 0; i < nl.getLength(); i++)
286N/A {
286N/A Node node = nl.item(i);
286N/A String value = toString(node);
286N/A
286N/A if (value != null && value.length() > 0)
286N/A sb.append(value);
286N/A }
286N/A
286N/A return sb.toString();
286N/A }
286N/A
286N/A /**
286N/A * The str:padding function creates a padding string of a certain length.
286N/A * The first argument gives the length of the padding string to be created.
286N/A * The second argument gives a string to be used to create the padding. This
286N/A * string is repeated as many times as is necessary to create a string of the
286N/A * length specified by the first argument; if the string is more than a character
286N/A * long, it may have to be truncated to produce the required length. If no second
286N/A * argument is specified, it defaults to a space (' '). If the second argument is
286N/A * an empty string, str:padding returns an empty string.
286N/A *
286N/A * @param length The length of the padding string to be created
286N/A * @param pattern The string to be used as pattern
286N/A *
286N/A * @return A padding string of the given length
286N/A */
286N/A public static String padding(double length, String pattern)
286N/A {
286N/A if (pattern == null || pattern.length() == 0)
286N/A return "";
286N/A
286N/A StringBuffer sb = new StringBuffer();
286N/A int len = (int)length;
286N/A int numAdded = 0;
286N/A int index = 0;
286N/A while (numAdded < len)
286N/A {
286N/A if (index == pattern.length())
286N/A index = 0;
286N/A
286N/A sb.append(pattern.charAt(index));
286N/A index++;
286N/A numAdded++;
286N/A }
286N/A
286N/A return sb.toString();
286N/A }
286N/A
286N/A /**
286N/A * See above
286N/A */
286N/A public static String padding(double length)
286N/A {
286N/A return padding(length, " ");
286N/A }
286N/A
286N/A /**
286N/A * The str:split function splits up a string and returns a node set of token
286N/A * elements, each containing one token from the string.
286N/A * <p>
286N/A * The first argument is the string to be split. The second argument is a pattern
286N/A * string. The string given by the first argument is split at any occurrence of
286N/A * this pattern. For example:
286N/A * <pre>
286N/A * str:split('a, simple, list', ', ') gives the node set consisting of:
286N/A *
286N/A * <token>a</token>
286N/A * <token>simple</token>
286N/A * <token>list</token>
286N/A * </pre>
286N/A * If the second argument is omitted, the default is the string '&#x20;' (i.e. a space).
286N/A *
286N/A * @param str The string to be split
286N/A * @param pattern The pattern
286N/A *
286N/A * @return A node set of split tokens
286N/A */
286N/A public static NodeList split(String str, String pattern)
286N/A {
286N/A
286N/A
286N/A NodeSet resultSet = new NodeSet();
286N/A resultSet.setShouldCacheNodes(true);
286N/A
286N/A boolean done = false;
286N/A int fromIndex = 0;
286N/A int matchIndex = 0;
286N/A String token = null;
286N/A
286N/A while (!done && fromIndex < str.length())
286N/A {
286N/A matchIndex = str.indexOf(pattern, fromIndex);
286N/A if (matchIndex >= 0)
286N/A {
286N/A token = str.substring(fromIndex, matchIndex);
286N/A fromIndex = matchIndex + pattern.length();
286N/A }
286N/A else
286N/A {
286N/A done = true;
286N/A token = str.substring(fromIndex);
286N/A }
286N/A
286N/A Document doc = DocumentHolder.m_doc;
286N/A synchronized (doc)
286N/A {
286N/A Element element = doc.createElement("token");
286N/A Text text = doc.createTextNode(token);
286N/A element.appendChild(text);
286N/A resultSet.addNode(element);
286N/A }
286N/A }
286N/A
286N/A return resultSet;
286N/A }
286N/A
286N/A /**
286N/A * See above
286N/A */
286N/A public static NodeList split(String str)
286N/A {
286N/A return split(str, " ");
286N/A }
286N/A
286N/A /**
286N/A * The str:tokenize function splits up a string and returns a node set of token
286N/A * elements, each containing one token from the string.
286N/A * <p>
286N/A * The first argument is the string to be tokenized. The second argument is a
286N/A * string consisting of a number of characters. Each character in this string is
286N/A * taken as a delimiting character. The string given by the first argument is split
286N/A * at any occurrence of any of these characters. For example:
286N/A * <pre>
286N/A * str:tokenize('2001-06-03T11:40:23', '-T:') gives the node set consisting of:
286N/A *
286N/A * <token>2001</token>
286N/A * <token>06</token>
286N/A * <token>03</token>
286N/A * <token>11</token>
286N/A * <token>40</token>
286N/A * <token>23</token>
286N/A * </pre>
286N/A * If the second argument is omitted, the default is the string '&#x9;&#xA;&#xD;&#x20;'
286N/A * (i.e. whitespace characters).
286N/A * <p>
286N/A * If the second argument is an empty string, the function returns a set of token
286N/A * elements, each of which holds a single character.
286N/A * <p>
286N/A * Note: This one is different from the tokenize extension function in the Xalan
286N/A * namespace. The one in Xalan returns a set of Text nodes, while this one wraps
286N/A * the Text nodes inside the token Element nodes.
286N/A *
286N/A * @param toTokenize The string to be tokenized
286N/A * @param delims The delimiter string
286N/A *
286N/A * @return A node set of split token elements
286N/A */
286N/A public static NodeList tokenize(String toTokenize, String delims)
286N/A {
286N/A
286N/A
286N/A NodeSet resultSet = new NodeSet();
286N/A
286N/A if (delims != null && delims.length() > 0)
286N/A {
286N/A StringTokenizer lTokenizer = new StringTokenizer(toTokenize, delims);
286N/A
286N/A Document doc = DocumentHolder.m_doc;
286N/A synchronized (doc)
286N/A {
286N/A while (lTokenizer.hasMoreTokens())
286N/A {
286N/A Element element = doc.createElement("token");
286N/A element.appendChild(doc.createTextNode(lTokenizer.nextToken()));
286N/A resultSet.addNode(element);
286N/A }
286N/A }
286N/A }
286N/A // If the delimiter is an empty string, create one token Element for
286N/A // every single character.
286N/A else
286N/A {
286N/A
286N/A Document doc = DocumentHolder.m_doc;
286N/A synchronized (doc)
286N/A {
286N/A for (int i = 0; i < toTokenize.length(); i++)
286N/A {
286N/A Element element = doc.createElement("token");
286N/A element.appendChild(doc.createTextNode(toTokenize.substring(i, i+1)));
286N/A resultSet.addNode(element);
286N/A }
286N/A }
286N/A }
286N/A
286N/A return resultSet;
286N/A }
286N/A
286N/A /**
286N/A * See above
286N/A */
286N/A public static NodeList tokenize(String toTokenize)
286N/A {
286N/A return tokenize(toTokenize, " \t\n\r");
286N/A }
286N/A /**
286N/A * This class is not loaded until first referenced (see Java Language
286N/A * Specification by Gosling/Joy/Steele, section 12.4.1)
286N/A *
286N/A * The static members are created when this class is first referenced, as a
286N/A * lazy initialization not needing checking against null or any
286N/A * synchronization.
286N/A *
286N/A */
286N/A private static class DocumentHolder
286N/A {
286N/A // Reuse the Document object to reduce memory usage.
286N/A private static final Document m_doc;
286N/A static {
286N/A try
286N/A {
286N/A m_doc =DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
286N/A }
286N/A
286N/A catch(ParserConfigurationException pce)
286N/A {
286N/A throw new com.sun.org.apache.xml.internal.utils.WrappedRuntimeException(pce);
286N/A }
286N/A
286N/A }
286N/A }
286N/A
286N/A}