You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@xalan.apache.org by dl...@apache.org on 2002/03/22 15:54:58 UTC
cvs commit: xml-xalan/java/src/org/apache/xalan/lib ExsltCommon.java ExsltMath.java ExsltSets.java package.html
dleslie 02/03/22 06:54:58
Modified: java/src/org/apache/xalan/lib package.html
Added: java/src/org/apache/xalan/lib ExsltCommon.java
ExsltMath.java ExsltSets.java
Log:
Preliminary set of EXSLT extension implementations.
Revision Changes Path
1.5 +2 -2 xml-xalan/java/src/org/apache/xalan/lib/package.html
Index: package.html
===================================================================
RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/lib/package.html,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- package.html 2 Jan 2001 03:36:37 -0000 1.4
+++ package.html 22 Mar 2002 14:54:58 -0000 1.5
@@ -1,7 +1,7 @@
<html>
- <title>Xalan Extensions.</title>
+ <title>Xalan and EXSLT Extensions.</title>
<body>
- <p>Extension elements and functions shipped with Xalan-Java</p>
+ <p>Extension elements and functions shipped with Xalan-Java, including EXSLT functions.</p>
<p>We are adding extensions to this package.<p>
</body>
</html>
1.1 xml-xalan/java/src/org/apache/xalan/lib/ExsltCommon.java
Index: ExsltCommon.java
===================================================================
package org.apache.xalan.lib;
import org.w3c.dom.Node;
import org.w3c.dom.Document;
import org.w3c.dom.DocumentFragment;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
import org.w3c.dom.traversal.NodeIterator;
import org.apache.xpath.NodeSet;
import org.apache.xpath.objects.XObject;
import org.apache.xpath.objects.XBoolean;
import org.apache.xpath.objects.XNumber;
import org.apache.xpath.objects.XRTreeFrag;
import org.apache.xpath.XPath;
import org.apache.xpath.XPathContext;
import org.apache.xpath.DOMHelper;
import org.apache.xml.dtm.DTMIterator;
import org.apache.xml.dtm.ref.DTMNodeIterator;
import org.apache.xml.utils.XMLString;
import org.xml.sax.SAXNotSupportedException;
import java.util.Hashtable;
import java.util.StringTokenizer;
import org.apache.xalan.extensions.ExpressionContext;
import org.apache.xalan.res.XSLMessages;
import org.apache.xalan.res.XSLTErrorResources;
import org.apache.xalan.xslt.EnvironmentCheck;
import javax.xml.parsers.*;
/**
* <meta name="usage" content="general"/>
* This class contains EXSLT common extension functions.
* It is accessed by specifying a namespace URI as follows:
* <pre>
* xmlns:exslt="http://exslt.org/xalan/common"
* </pre>
*
* The documentation for each function has been copied from the relevant
* EXSLT Implementer page.
*
* @see <a href="http://www.exslt.org/">EXSLT</a>
*/
public class ExsltCommon
{
/**
* The exsl:object-type function returns a string giving the type of the object passed
* as the argument. The possible object types are: 'string', 'number', 'boolean',
* 'node-set', 'RTF', or 'external'.
*
* Most XSLT object types can be coerced to each other without error. However, there are
* certain coercions that raise errors, most importantly treating anything other than a
* node set as a node set. Authors of utilities such as named templates or user-defined
* extension functions may wish to give some flexibility in the parameter and argument values
* that are accepted by the utility; the exsl:object-type function enables them to do so.
*
* The Xalan extensions MethodResolver converts 'object-type' to 'objectType'.
*
* @param obj The object to be typed.
* @return objectType 'string', 'number', 'boolean', 'node-set', 'RTF', or 'external'.
*
* @see <a href="http://www.exslt.org/">EXSLT</a>
*/
public static String objectType (Object obj)
{
if (obj instanceof String)
return "string";
else if (obj instanceof Boolean)
return "boolean";
else if (obj instanceof Number)
return "number";
else if (obj instanceof DTMNodeIterator)
{
DTMIterator dtmI = ((DTMNodeIterator)obj).getDTMIterator();
// Need to verify that OneStepIteratorForward is consistently the DTM iterator
// for rtfs and only rtfs.
if (dtmI.getClass().getName().equals("org.apache.xpath.axes.OneStepIteratorForward"))
return "RTF";
else
return "node-set";
}
else
return "external";
}
/**
* The exsl:node-set function converts a result tree fragment (which is what you get
* when you use the content of xsl:variable rather than its select attribute to give
* a variable value) into a node set. This enables you to process the XML that you create
* within a variable, and therefore do multi-step processing.
*
* You can also use this function to turn a string into a text node, which is helpful
* if you want to pass a string to a function that only accepts a node set.
*
* The Xalan extensions MethodResolver converts 'node-set' to 'nodeSet'.
*
* @param myProcesser is passed in by the Xalan extension processor
* @param rtf The result tree fragment to be converted to a node-set.
*
* @returns node-set with the contents of the result tree fragment.
*
* Note: Already implemented in the xalan namespace as nodeset.
*
* @see <a href="http://www.exslt.org/">EXSLT</a>
*/
public static NodeSet nodeSet(ExpressionContext myProcessor, Object rtf)
{
return Extensions.nodeset(myProcessor, rtf);
}
public static NodeSet intersection(NodeIterator ni1, NodeIterator ni2)
throws javax.xml.transform.TransformerException
{
return Extensions.intersection(ni1, ni2);
}
public static NodeSet difference(NodeIterator ni1, NodeIterator ni2)
throws javax.xml.transform.TransformerException
{
return Extensions.difference(ni1, ni2);
}
public static NodeSet distinct(ExpressionContext myContext, NodeIterator ni)
throws javax.xml.transform.TransformerException
{
return Extensions.distinct(myContext, ni);
}
public static boolean hasSameNodes(NodeIterator ni1, NodeIterator ni2)
{
return Extensions.hasSameNodes(ni1, ni2);
}
}
1.1 xml-xalan/java/src/org/apache/xalan/lib/ExsltMath.java
Index: ExsltMath.java
===================================================================
package org.apache.xalan.lib;
import org.w3c.dom.Node;
import org.w3c.dom.Document;
import org.w3c.dom.DocumentFragment;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
import org.w3c.dom.traversal.NodeIterator;
import org.apache.xpath.NodeSet;
import org.apache.xpath.objects.XObject;
import org.apache.xpath.objects.XBoolean;
import org.apache.xpath.objects.XNumber;
import org.apache.xpath.objects.XRTreeFrag;
import org.apache.xpath.XPath;
import org.apache.xpath.XPathContext;
import org.apache.xpath.DOMHelper;
import org.apache.xml.dtm.DTMIterator;
import org.apache.xml.dtm.ref.DTMNodeIterator;
import org.apache.xml.utils.XMLString;
import org.xml.sax.SAXNotSupportedException;
import java.util.Hashtable;
import java.util.StringTokenizer;
import org.apache.xalan.extensions.ExpressionContext;
import org.apache.xalan.res.XSLMessages;
import org.apache.xalan.res.XSLTErrorResources;
import org.apache.xalan.xslt.EnvironmentCheck;
import javax.xml.parsers.*;
/**
* <meta name="usage" content="general"/>
* This class contains EXSLT math extension functions.
* It is accessed by specifying a namespace URI as follows:
* <pre>
* xmlns:exslt="http://exslt.org/math"
* </pre>
*
* The documentation for each function has been copied from the relevant
* EXSLT Implementer page.
*
* @see <a href="http://www.exslt.org/">EXSLT</a>
*/
public class ExsltMath
{
/**
* The math:max function returns the maximum value of the nodes passed as the argument.
* The maximum value is defined as follows. The node set passed as an argument is sorted
* in descending order as it would be by xsl:sort with a data type of number. The maximum
* is the result of converting the string value of the first node in this sorted list to
* a number using the number function.
*
* If the node set is empty, or if the result of converting the string values of any of the
* nodes to a number is NaN, then NaN is returned.
*
* @param expCon is passed in by the Xalan extension processor
* @param ni The NodeIterator for the node-set to be evaluated.
*
* @return String representation of the maximum value found, NaN if any node cannot be
* converted to a number.
*
* @see <a href="http://www.exslt.org/">EXSLT</a>
*/
public static String max (ExpressionContext expCon, NodeIterator ni)
{
NodeSet ns = new NodeSet(ni);
Node maxNode = null;
double m = Double.MIN_VALUE;
for (int i = 0; i < ns.getLength(); i++)
{
Node n = ns.elementAt(i);
double d = expCon.toNumber(n);
if (Double.isNaN(d))
return "NaN";
else if (d > m)
{
m = d;
maxNode = n;
}
}
return expCon.toString(maxNode);
}
/**
* The math:min function returns the minimum value of the nodes passed as the argument.
* The minimum value is defined as follows. The node set passed as an argument is sorted
* in ascending order as it would be by xsl:sort with a data type of number. The minimum
* is the result of converting the string value of the first node in this sorted list to
* a number using the number function.
*
* If the node set is empty, or if the result of converting the string values of any of
* the nodes to a number is NaN, then NaN is returned.
*
* @param expCon is passed in by the Xalan extension processor
* @param ni The NodeIterator for the node-set to be evaluated.
*
* @return String representation of the minimum value found, NaN if any node cannot be
* converted to a number.
*
* @see <a href="http://www.exslt.org/">EXSLT</a>
*/
public static String min (ExpressionContext expCon, NodeIterator ni)
{
NodeSet ns = new NodeSet(ni);
Node minNode = null;
double m = Double.MAX_VALUE;
for (int i = 0; i < ns.getLength(); i++)
{
Node n = ns.elementAt(i);
double d = expCon.toNumber(n);
if (Double.isNaN(d))
return "NaN";
else if (d < m)
{
m = d;
minNode = n;
}
}
return expCon.toString(minNode);
}
/**
* The math:highest function returns the nodes in the node set whose value is the maximum
* value for the node set. The maximum value for the node set is the same as the value as
* calculated by math:max. A node has this maximum value if the result of converting its
* string value to a number as if by the number function is equal to the maximum value,
* where the equality comparison is defined as a numerical comparison using the = operator.
*
* If any of the nodes in the node set has a non-numeric value, the math:max function will
* return NaN. The definition numeric comparisons entails that NaN != NaN. Therefore if any
* of the nodes in the node set has a non-numeric value, math:highest will return an empty
* node set.
*
* @param expCon is passed in by the Xalan extension processor
* @param ni The NodeIterator for the node-set to be evaluated.
*
* @return node-set with nodes containing the minimum value found, an empty node-set
* if any node cannot be converted to a number.
*/
public static NodeSet highest (ExpressionContext expCon, NodeIterator ni)
throws java.lang.CloneNotSupportedException
{
NodeSet ns = new NodeSet(ni);
NodeIterator niClone = ns.cloneWithReset();
double high = new Double(max(expCon, niClone)).doubleValue();
NodeSet highNodes = new NodeSet();
highNodes.setShouldCacheNodes(true);
if (Double.isNaN(high))
return highNodes; // empty Nodeset
for (int i = 0; i < ns.getLength(); i++)
{
Node n = ns.elementAt(i);
double d = expCon.toNumber(n);
if (d == high)
highNodes.addElement(n);
}
return highNodes;
}
/**
* The math:lowest function returns the nodes in the node set whose value is the minimum value
* for the node set. The minimum value for the node set is the same as the value as calculated
* by math:min. A node has this minimum value if the result of converting its string value to
* a number as if by the number function is equal to the minimum value, where the equality
* comparison is defined as a numerical comparison using the = operator.
*
* If any of the nodes in the node set has a non-numeric value, the math:min function will return
* NaN. The definition numeric comparisons entails that NaN != NaN. Therefore if any of the nodes
* in the node set has a non-numeric value, math:lowest will return an empty node set.
*
* @param expCon is passed in by the Xalan extension processor
* @param ni The NodeIterator for the node-set to be evaluated.
*
* @return node-set with nodes containing the maximum value found, an empty node-set
* if any node cannot be converted to a number.
*
*/
public static NodeSet lowest (ExpressionContext expCon, NodeIterator ni)
throws java.lang.CloneNotSupportedException
{
NodeSet ns = new NodeSet(ni);
NodeIterator niClone = ns.cloneWithReset();
double low = new Double(min(expCon, niClone)).doubleValue();
NodeSet lowNodes = new NodeSet();
lowNodes.setShouldCacheNodes(true);
if (Double.isNaN(low))
return lowNodes; // empty Nodeset
for (int i = 0; i < ns.getLength(); i++)
{
Node n = ns.elementAt(i);
double d = expCon.toNumber(n);
if (d == low)
lowNodes.addElement(n);
}
return lowNodes;
}
}
1.1 xml-xalan/java/src/org/apache/xalan/lib/ExsltSets.java
Index: ExsltSets.java
===================================================================
package org.apache.xalan.lib;
import org.w3c.dom.Node;
import org.w3c.dom.Document;
import org.w3c.dom.DocumentFragment;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
import org.w3c.dom.traversal.NodeIterator;
import org.apache.xpath.NodeSet;
import org.apache.xpath.objects.XObject;
import org.apache.xpath.objects.XBoolean;
import org.apache.xpath.objects.XNumber;
import org.apache.xpath.objects.XRTreeFrag;
import org.apache.xpath.XPath;
import org.apache.xpath.XPathContext;
import org.apache.xpath.DOMHelper;
import org.apache.xml.dtm.DTMIterator;
import org.apache.xml.dtm.ref.DTMNodeIterator;
import org.apache.xml.utils.XMLString;
import org.xml.sax.SAXNotSupportedException;
import java.util.Hashtable;
import java.util.StringTokenizer;
import org.apache.xalan.extensions.ExpressionContext;
import org.apache.xalan.res.XSLMessages;
import org.apache.xalan.res.XSLTErrorResources;
import org.apache.xalan.xslt.EnvironmentCheck;
import javax.xml.parsers.*;
/**
* <meta name="usage" content="general"/>
* This class contains EXSLT set extension functions.
* It is accessed by specifying a namespace URI as follows:
* <pre>
* xmlns:exslt="http://exslt.org/xalan/sets"
* </pre>
*
* The documentation for each function has been copied from the relevant
* EXSLT Implementer page.
*
* @see <a href="http://www.exslt.org/">EXSLT</a>
*/
public class ExsltSets
{
/**
* The set:leading function returns the nodes in the node set passed as the first argument that
* precede, in document order, the first node in the node set passed as the second argument. If
* the first node in the second node set is not contained in the first node set, then an empty
* node set is returned. If the second node set is empty, then the first node set is returned.
*
* @param ni1 NodeIterator for first node-set.
* @param ni2 NodeIterator for second node-set.
* @return a node-set containing the nodes in ni1 that precede in document order the first
* node in ni2; an empty node-set if the first node in ni2 is not in ni1; all of ni1 if n12
* is empty.
*
* @see <a href="http://www.exslt.org/">EXSLT</a>
*/
public static NodeSet leading (NodeIterator ni1, NodeIterator ni2)
{
NodeSet ns1 = new NodeSet(ni1);
NodeSet ns2 = new NodeSet(ni2);
NodeSet leadNodes = new NodeSet();
if (ns2.getLength() == 0)
return ns1;
Node endNode = ns2.elementAt(0);
if (!ns1.contains(endNode))
return leadNodes; // empty NodeSet
for (int i = 0; i < ns1.getLength(); i++)
{
Node testNode = ns1.elementAt(i);
if (DOMHelper.isNodeAfter(testNode, endNode)
&& !(DOMHelper.isNodeTheSame(testNode, endNode)))
leadNodes.addElement(testNode);
}
return leadNodes;
}
/**
* The set:trailing function returns the nodes in the node set passed as the first argument that
* follow, in document order, the first node in the node set passed as the second argument. If
* the first node in the second node set is not contained in the first node set, then an empty
* node set is returned. If the second node set is empty, then the first node set is returned.
*
* @param ni1 NodeIterator for first node-set.
* @param ni2 NodeIterator for second node-set.
* @return a node-set containing the nodes in ni1 that precede in document order the first
* node in ni2; an empty node-set if the first noe in ni2 is not in ni1; all of ni1 if ni2
* is empty.
*
* @see <a href="http://www.exslt.org/">EXSLT</a>
*/
public static NodeSet trailing (NodeIterator ni1, NodeIterator ni2)
{
NodeSet ns1 = new NodeSet(ni1);
NodeSet ns2 = new NodeSet(ni2);
NodeSet trailNodes = new NodeSet();
if (ns2.getLength() == 0)
return ns1;
Node startNode = ns2.elementAt(0);
if (!ns1.contains(startNode))
return trailNodes; // empty NodeSet
for (int i = 0; i < ns1.getLength(); i++)
{
Node testNode = ns1.elementAt(i);
if (DOMHelper.isNodeAfter(startNode, testNode)
&& !(DOMHelper.isNodeTheSame(startNode, testNode)))
trailNodes.addElement(testNode);
}
return trailNodes;
}
/**
* The set:intersection function returns a node set comprising the nodes that are within
* both the node sets passed as arguments to it.
*
* @param ni1 NodeIterator for first node-set.
* @param ni2 NodeIterator for second node-set.
* @return a NodeSet containing the nodes in ni1 that are also
* in ni2.
*
* Note: Already implemented in the xalan namespace.
*
* @see <a href="http://www.exslt.org/">EXSLT</a>
*/
public static NodeSet intersection(NodeIterator ni1, NodeIterator ni2)
throws javax.xml.transform.TransformerException
{
return Extensions.intersection(ni1, ni2);
}
/**
* The set:difference function returns the difference between two node sets - those nodes that
* are in the node set passed as the first argument that are not in the node set passed as the
* second argument.
*
* @param ni1 NodeIterator for first node-set.
* @param ni2 NodeIterator for second node-set.
* @return a NodeSet containing the nodes in ni1 that are not
* in ni2.
*
* Note: Already implemented in the xalan namespace.
*
* @see <a href="http://www.exslt.org/">EXSLT</a>
*/
public static NodeSet difference(NodeIterator ni1, NodeIterator ni2)
throws javax.xml.transform.TransformerException
{
return Extensions.difference(ni1, ni2);
}
/**
* The set:distinct function returns a subset of the nodes contained in the node-set NS passed
* as the first argument. Specifically, it selects a node N if there is no node in NS that has
* the same string value as N, and that precedes N in document order.
*
* @param myContext Passed in by Xalan extension processor.
* @param ni NodeIterator for node-set.
* @return a NodeSet with nodes from ni containing distinct string values.
* In other words, if more than one node in ni contains the same string value,
* only include the first such node found.
*
* Note: Already implemented in the xalan namespace.
*
* @see <a href="http://www.exslt.org/">EXSLT</a>
*/
public static NodeSet distinct(ExpressionContext myContext, NodeIterator ni)
throws javax.xml.transform.TransformerException
{
return Extensions.distinct(myContext, ni);
}
/**
* The set:has-same-node function returns true if the node set passed as the first argument shares
* any nodes with the node set passed as the second argument. If there are no nodes that are in both
* node sets, then it returns false.
*
* The Xalan extensions MethodResolver converts 'has-same-node' to 'hasSameNode'.
*
* Note: Not to be confused with hasSameNodes in the Xalan namespace, which returns true if
* the two node sets contain the exactly the same nodes (perhaps in a different order),
* otherwise false.
*
* @see <a href="http://www.exslt.org/">EXSLT</a>
*/
public static boolean hasSameNode(NodeIterator ni1, NodeIterator ni2)
{
NodeSet ns1 = new NodeSet(ni1);
NodeSet ns2 = new NodeSet(ni2);
for (int i = 0; i < ns1.getLength(); i++)
{
if (ns2.contains(ns1.elementAt(i)))
return true;
}
return false;
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: xalan-cvs-unsubscribe@xml.apache.org
For additional commands, e-mail: xalan-cvs-help@xml.apache.org