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: ExsltDynamic.java,v 1.1.2.1 2005/08/01 02:08:51 jeffsuttor Exp $
286N/A */
286N/Apackage com.sun.org.apache.xalan.internal.lib;
286N/A
286N/Aimport javax.xml.parsers.DocumentBuilder;
286N/Aimport javax.xml.parsers.DocumentBuilderFactory;
286N/Aimport javax.xml.transform.TransformerException;
286N/A
286N/Aimport com.sun.org.apache.xalan.internal.extensions.ExpressionContext;
286N/Aimport com.sun.org.apache.xalan.internal.res.XSLMessages;
286N/Aimport com.sun.org.apache.xalan.internal.res.XSLTErrorResources;
286N/Aimport com.sun.org.apache.xpath.internal.NodeSet;
286N/Aimport com.sun.org.apache.xpath.internal.NodeSetDTM;
286N/Aimport com.sun.org.apache.xpath.internal.XPath;
286N/Aimport com.sun.org.apache.xpath.internal.XPathContext;
286N/Aimport com.sun.org.apache.xpath.internal.objects.XBoolean;
286N/Aimport com.sun.org.apache.xpath.internal.objects.XNodeSet;
286N/Aimport com.sun.org.apache.xpath.internal.objects.XNumber;
286N/Aimport com.sun.org.apache.xpath.internal.objects.XObject;
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/Aimport org.xml.sax.SAXNotSupportedException;
286N/A
286N/A/**
286N/A * This class contains EXSLT dynamic extension functions.
286N/A *
286N/A * It is accessed by specifying a namespace URI as follows:
286N/A * <pre>
286N/A * xmlns:dyn="http://exslt.org/dynamic"
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 ExsltDynamic extends ExsltBase
286N/A{
286N/A
286N/A public static final String EXSL_URI = "http://exslt.org/common";
286N/A
286N/A /**
286N/A * The dyn:max function calculates the maximum value for the nodes passed as
286N/A * the first argument, where the value of each node is calculated dynamically
286N/A * using an XPath expression passed as a string as the second argument.
286N/A * <p>
286N/A * The expressions are evaluated relative to the nodes passed as the first argument.
286N/A * In other words, the value for each node is calculated by evaluating the XPath
286N/A * expression with all context information being the same as that for the call to
286N/A * the dyn:max function itself, except for the following:
286N/A * <p>
286N/A * <ul>
286N/A * <li>the context node is the node whose value is being calculated.</li>
286N/A * <li>the context position is the position of the node within the node set passed as
286N/A * the first argument to the dyn:max function, arranged in document order.</li>
286N/A * <li>the context size is the number of nodes passed as the first argument to the
286N/A * dyn:max function.</li>
286N/A * </ul>
286N/A * <p>
286N/A * The dyn:max function returns the maximum of these values, calculated in exactly
286N/A * the same way as for math:max.
286N/A * <p>
286N/A * If the expression string passed as the second argument is an invalid XPath
286N/A * expression (including an empty string), this function returns NaN.
286N/A * <p>
286N/A * This function must take a second argument. To calculate the maximum of a set of
286N/A * nodes based on their string values, you should use the math:max function.
286N/A *
286N/A * @param myContext The ExpressionContext passed by the extension processor
286N/A * @param nl The node set
286N/A * @param expr The expression string
286N/A *
286N/A * @return The maximum evaluation value
286N/A */
286N/A public static double max(ExpressionContext myContext, NodeList nl, String expr)
286N/A throws SAXNotSupportedException
286N/A {
286N/A
286N/A XPathContext xctxt = null;
286N/A if (myContext instanceof XPathContext.XPathExpressionContext)
286N/A xctxt = ((XPathContext.XPathExpressionContext) myContext).getXPathContext();
286N/A else
286N/A throw new SAXNotSupportedException(XSLMessages.createMessage(XSLTErrorResources.ER_INVALID_CONTEXT_PASSED, new Object[]{myContext }));
286N/A
286N/A if (expr == null || expr.length() == 0)
286N/A return Double.NaN;
286N/A
286N/A NodeSetDTM contextNodes = new NodeSetDTM(nl, xctxt);
286N/A xctxt.pushContextNodeList(contextNodes);
286N/A
286N/A double maxValue = - Double.MAX_VALUE;
286N/A for (int i = 0; i < contextNodes.getLength(); i++)
286N/A {
286N/A int contextNode = contextNodes.item(i);
286N/A xctxt.pushCurrentNode(contextNode);
286N/A
286N/A double result = 0;
286N/A try
286N/A {
286N/A XPath dynamicXPath = new XPath(expr, xctxt.getSAXLocator(),
286N/A xctxt.getNamespaceContext(),
286N/A XPath.SELECT);
286N/A result = dynamicXPath.execute(xctxt, contextNode, xctxt.getNamespaceContext()).num();
286N/A }
286N/A catch (TransformerException e)
286N/A {
286N/A xctxt.popCurrentNode();
286N/A xctxt.popContextNodeList();
286N/A return Double.NaN;
286N/A }
286N/A
286N/A xctxt.popCurrentNode();
286N/A
286N/A if (result > maxValue)
286N/A maxValue = result;
286N/A }
286N/A
286N/A xctxt.popContextNodeList();
286N/A return maxValue;
286N/A
286N/A }
286N/A
286N/A /**
286N/A * The dyn:min function calculates the minimum value for the nodes passed as the
286N/A * first argument, where the value of each node is calculated dynamically using
286N/A * an XPath expression passed as a string as the second argument.
286N/A * <p>
286N/A * The expressions are evaluated relative to the nodes passed as the first argument.
286N/A * In other words, the value for each node is calculated by evaluating the XPath
286N/A * expression with all context information being the same as that for the call to
286N/A * the dyn:min function itself, except for the following:
286N/A * <p>
286N/A * <ul>
286N/A * <li>the context node is the node whose value is being calculated.</li>
286N/A * <li>the context position is the position of the node within the node set passed
286N/A * as the first argument to the dyn:min function, arranged in document order.</li>
286N/A * <li>the context size is the number of nodes passed as the first argument to the
286N/A * dyn:min function.</li>
286N/A * </ul>
286N/A * <p>
286N/A * The dyn:min function returns the minimum of these values, calculated in exactly
286N/A * the same way as for math:min.
286N/A * <p>
286N/A * If the expression string passed as the second argument is an invalid XPath expression
286N/A * (including an empty string), this function returns NaN.
286N/A * <p>
286N/A * This function must take a second argument. To calculate the minimum of a set of
286N/A * nodes based on their string values, you should use the math:min function.
286N/A *
286N/A * @param myContext The ExpressionContext passed by the extension processor
286N/A * @param nl The node set
286N/A * @param expr The expression string
286N/A *
286N/A * @return The minimum evaluation value
286N/A */
286N/A public static double min(ExpressionContext myContext, NodeList nl, String expr)
286N/A throws SAXNotSupportedException
286N/A {
286N/A
286N/A XPathContext xctxt = null;
286N/A if (myContext instanceof XPathContext.XPathExpressionContext)
286N/A xctxt = ((XPathContext.XPathExpressionContext) myContext).getXPathContext();
286N/A else
286N/A throw new SAXNotSupportedException(XSLMessages.createMessage(XSLTErrorResources.ER_INVALID_CONTEXT_PASSED, new Object[]{myContext }));
286N/A
286N/A if (expr == null || expr.length() == 0)
286N/A return Double.NaN;
286N/A
286N/A NodeSetDTM contextNodes = new NodeSetDTM(nl, xctxt);
286N/A xctxt.pushContextNodeList(contextNodes);
286N/A
286N/A double minValue = Double.MAX_VALUE;
286N/A for (int i = 0; i < nl.getLength(); i++)
286N/A {
286N/A int contextNode = contextNodes.item(i);
286N/A xctxt.pushCurrentNode(contextNode);
286N/A
286N/A double result = 0;
286N/A try
286N/A {
286N/A XPath dynamicXPath = new XPath(expr, xctxt.getSAXLocator(),
286N/A xctxt.getNamespaceContext(),
286N/A XPath.SELECT);
286N/A result = dynamicXPath.execute(xctxt, contextNode, xctxt.getNamespaceContext()).num();
286N/A }
286N/A catch (TransformerException e)
286N/A {
286N/A xctxt.popCurrentNode();
286N/A xctxt.popContextNodeList();
286N/A return Double.NaN;
286N/A }
286N/A
286N/A xctxt.popCurrentNode();
286N/A
286N/A if (result < minValue)
286N/A minValue = result;
286N/A }
286N/A
286N/A xctxt.popContextNodeList();
286N/A return minValue;
286N/A
286N/A }
286N/A
286N/A /**
286N/A * The dyn:sum function calculates the sum for the nodes passed as the first argument,
286N/A * where the value of each node is calculated dynamically using an XPath expression
286N/A * passed as a string as the second argument.
286N/A * <p>
286N/A * The expressions are evaluated relative to the nodes passed as the first argument.
286N/A * In other words, the value for each node is calculated by evaluating the XPath
286N/A * expression with all context information being the same as that for the call to
286N/A * the dyn:sum function itself, except for the following:
286N/A * <p>
286N/A * <ul>
286N/A * <li>the context node is the node whose value is being calculated.</li>
286N/A * <li>the context position is the position of the node within the node set passed as
286N/A * the first argument to the dyn:sum function, arranged in document order.</li>
286N/A * <li>the context size is the number of nodes passed as the first argument to the
286N/A * dyn:sum function.</li>
286N/A * </ul>
286N/A * <p>
286N/A * The dyn:sum function returns the sumimum of these values, calculated in exactly
286N/A * the same way as for sum.
286N/A * <p>
286N/A * If the expression string passed as the second argument is an invalid XPath
286N/A * expression (including an empty string), this function returns NaN.
286N/A * <p>
286N/A * This function must take a second argument. To calculate the sumimum of a set of
286N/A * nodes based on their string values, you should use the sum function.
286N/A *
286N/A * @param myContext The ExpressionContext passed by the extension processor
286N/A * @param nl The node set
286N/A * @param expr The expression string
286N/A *
286N/A * @return The sum of the evaluation value on each node
286N/A */
286N/A public static double sum(ExpressionContext myContext, NodeList nl, String expr)
286N/A throws SAXNotSupportedException
286N/A {
286N/A XPathContext xctxt = null;
286N/A if (myContext instanceof XPathContext.XPathExpressionContext)
286N/A xctxt = ((XPathContext.XPathExpressionContext) myContext).getXPathContext();
286N/A else
286N/A throw new SAXNotSupportedException(XSLMessages.createMessage(XSLTErrorResources.ER_INVALID_CONTEXT_PASSED, new Object[]{myContext }));
286N/A
286N/A if (expr == null || expr.length() == 0)
286N/A return Double.NaN;
286N/A
286N/A NodeSetDTM contextNodes = new NodeSetDTM(nl, xctxt);
286N/A xctxt.pushContextNodeList(contextNodes);
286N/A
286N/A double sum = 0;
286N/A for (int i = 0; i < nl.getLength(); i++)
286N/A {
286N/A int contextNode = contextNodes.item(i);
286N/A xctxt.pushCurrentNode(contextNode);
286N/A
286N/A double result = 0;
286N/A try
286N/A {
286N/A XPath dynamicXPath = new XPath(expr, xctxt.getSAXLocator(),
286N/A xctxt.getNamespaceContext(),
286N/A XPath.SELECT);
286N/A result = dynamicXPath.execute(xctxt, contextNode, xctxt.getNamespaceContext()).num();
286N/A }
286N/A catch (TransformerException e)
286N/A {
286N/A xctxt.popCurrentNode();
286N/A xctxt.popContextNodeList();
286N/A return Double.NaN;
286N/A }
286N/A
286N/A xctxt.popCurrentNode();
286N/A
286N/A sum = sum + result;
286N/A
286N/A }
286N/A
286N/A xctxt.popContextNodeList();
286N/A return sum;
286N/A }
286N/A
286N/A /**
286N/A * The dyn:map function evaluates the expression passed as the second argument for
286N/A * each of the nodes passed as the first argument, and returns a node set of those values.
286N/A * <p>
286N/A * The expressions are evaluated relative to the nodes passed as the first argument.
286N/A * In other words, the value for each node is calculated by evaluating the XPath
286N/A * expression with all context information being the same as that for the call to
286N/A * the dyn:map function itself, except for the following:
286N/A * <p>
286N/A * <ul>
286N/A * <li>The context node is the node whose value is being calculated.</li>
286N/A * <li>the context position is the position of the node within the node set passed
286N/A * as the first argument to the dyn:map function, arranged in document order.</li>
286N/A * <li>the context size is the number of nodes passed as the first argument to the
286N/A * dyn:map function.</li>
286N/A * </ul>
286N/A * <p>
286N/A * If the expression string passed as the second argument is an invalid XPath
286N/A * expression (including an empty string), this function returns an empty node set.
286N/A * <p>
286N/A * If the XPath expression evaluates as a node set, the dyn:map function returns
286N/A * the union of the node sets returned by evaluating the expression for each of the
286N/A * nodes in the first argument. Note that this may mean that the node set resulting
286N/A * from the call to the dyn:map function contains a different number of nodes from
286N/A * the number in the node set passed as the first argument to the function.
286N/A * <p>
286N/A * If the XPath expression evaluates as a number, the dyn:map function returns a
286N/A * node set containing one exsl:number element (namespace http://exslt.org/common)
286N/A * for each node in the node set passed as the first argument to the dyn:map function,
286N/A * in document order. The string value of each exsl:number element is the same as
286N/A * the result of converting the number resulting from evaluating the expression to
286N/A * a string as with the number function, with the exception that Infinity results
286N/A * in an exsl:number holding the highest number the implementation can store, and
286N/A * -Infinity results in an exsl:number holding the lowest number the implementation
286N/A * can store.
286N/A * <p>
286N/A * If the XPath expression evaluates as a boolean, the dyn:map function returns a
286N/A * node set containing one exsl:boolean element (namespace http://exslt.org/common)
286N/A * for each node in the node set passed as the first argument to the dyn:map function,
286N/A * in document order. The string value of each exsl:boolean element is 'true' if the
286N/A * expression evaluates as true for the node, and '' if the expression evaluates as
286N/A * false.
286N/A * <p>
286N/A * Otherwise, the dyn:map function returns a node set containing one exsl:string
286N/A * element (namespace http://exslt.org/common) for each node in the node set passed
286N/A * as the first argument to the dyn:map function, in document order. The string
286N/A * value of each exsl:string element is the same as the result of converting the
286N/A * result of evaluating the expression for the relevant node to a string as with
286N/A * the string function.
286N/A *
286N/A * @param myContext The ExpressionContext passed by the extension processor
286N/A * @param nl The node set
286N/A * @param expr The expression string
286N/A *
286N/A * @return The node set after evaluation
286N/A */
286N/A public static NodeList map(ExpressionContext myContext, NodeList nl, String expr)
286N/A throws SAXNotSupportedException
286N/A {
286N/A XPathContext xctxt = null;
286N/A Document lDoc = null;
286N/A
286N/A if (myContext instanceof XPathContext.XPathExpressionContext)
286N/A xctxt = ((XPathContext.XPathExpressionContext) myContext).getXPathContext();
286N/A else
286N/A throw new SAXNotSupportedException(XSLMessages.createMessage(XSLTErrorResources.ER_INVALID_CONTEXT_PASSED, new Object[]{myContext }));
286N/A
286N/A if (expr == null || expr.length() == 0)
286N/A return new NodeSet();
286N/A
286N/A NodeSetDTM contextNodes = new NodeSetDTM(nl, xctxt);
286N/A xctxt.pushContextNodeList(contextNodes);
286N/A
286N/A NodeSet resultSet = new NodeSet();
286N/A resultSet.setShouldCacheNodes(true);
286N/A
286N/A for (int i = 0; i < nl.getLength(); i++)
286N/A {
286N/A int contextNode = contextNodes.item(i);
286N/A xctxt.pushCurrentNode(contextNode);
286N/A
286N/A XObject object = null;
286N/A try
286N/A {
286N/A XPath dynamicXPath = new XPath(expr, xctxt.getSAXLocator(),
286N/A xctxt.getNamespaceContext(),
286N/A XPath.SELECT);
286N/A object = dynamicXPath.execute(xctxt, contextNode, xctxt.getNamespaceContext());
286N/A
286N/A if (object instanceof XNodeSet)
286N/A {
286N/A NodeList nodelist = null;
286N/A nodelist = ((XNodeSet)object).nodelist();
286N/A
286N/A for (int k = 0; k < nodelist.getLength(); k++)
286N/A {
286N/A Node n = nodelist.item(k);
286N/A if (!resultSet.contains(n))
286N/A resultSet.addNode(n);
286N/A }
286N/A }
286N/A else
286N/A {
286N/A if (lDoc == null)
286N/A {
286N/A DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
286N/A dbf.setNamespaceAware(true);
286N/A DocumentBuilder db = dbf.newDocumentBuilder();
286N/A lDoc = db.newDocument();
286N/A }
286N/A
286N/A Element element = null;
286N/A if (object instanceof XNumber)
286N/A element = lDoc.createElementNS(EXSL_URI, "exsl:number");
286N/A else if (object instanceof XBoolean)
286N/A element = lDoc.createElementNS(EXSL_URI, "exsl:boolean");
286N/A else
286N/A element = lDoc.createElementNS(EXSL_URI, "exsl:string");
286N/A
286N/A Text textNode = lDoc.createTextNode(object.str());
286N/A element.appendChild(textNode);
286N/A resultSet.addNode(element);
286N/A }
286N/A }
286N/A catch (Exception e)
286N/A {
286N/A xctxt.popCurrentNode();
286N/A xctxt.popContextNodeList();
286N/A return new NodeSet();
286N/A }
286N/A
286N/A xctxt.popCurrentNode();
286N/A
286N/A }
286N/A
286N/A xctxt.popContextNodeList();
286N/A return resultSet;
286N/A }
286N/A
286N/A /**
286N/A * The dyn:evaluate function evaluates a string as an XPath expression and returns
286N/A * the resulting value, which might be a boolean, number, string, node set, result
286N/A * tree fragment or external object. The sole argument is the string to be evaluated.
286N/A * <p>
286N/A * If the expression string passed as the second argument is an invalid XPath
286N/A * expression (including an empty string), this function returns an empty node set.
286N/A * <p>
286N/A * You should only use this function if the expression must be constructed dynamically,
286N/A * otherwise it is much more efficient to use the expression literally.
286N/A *
286N/A * @param myContext The ExpressionContext passed by the extension processor
286N/A * @param xpathExpr The XPath expression string
286N/A *
286N/A * @return The evaluation result
286N/A */
286N/A public static XObject evaluate(ExpressionContext myContext, String xpathExpr)
286N/A throws SAXNotSupportedException
286N/A {
286N/A if (myContext instanceof XPathContext.XPathExpressionContext)
286N/A {
286N/A XPathContext xctxt = null;
286N/A try
286N/A {
286N/A xctxt = ((XPathContext.XPathExpressionContext) myContext).getXPathContext();
286N/A XPath dynamicXPath = new XPath(xpathExpr, xctxt.getSAXLocator(),
286N/A xctxt.getNamespaceContext(),
286N/A XPath.SELECT);
286N/A
286N/A return dynamicXPath.execute(xctxt, myContext.getContextNode(),
286N/A xctxt.getNamespaceContext());
286N/A }
286N/A catch (TransformerException e)
286N/A {
286N/A return new XNodeSet(xctxt.getDTMManager());
286N/A }
286N/A }
286N/A else
286N/A throw new SAXNotSupportedException(XSLMessages.createMessage(XSLTErrorResources.ER_INVALID_CONTEXT_PASSED, new Object[]{myContext })); //"Invalid context passed to evaluate "
286N/A }
286N/A
286N/A /**
286N/A * The dyn:closure function creates a node set resulting from transitive closure of
286N/A * evaluating the expression passed as the second argument on each of the nodes passed
286N/A * as the first argument, then on the node set resulting from that and so on until no
286N/A * more nodes are found. For example:
286N/A * <pre>
286N/A * dyn:closure(., '*')
286N/A * </pre>
286N/A * returns all the descendant elements of the node (its element children, their
286N/A * children, their children's children and so on).
286N/A * <p>
286N/A * The expression is thus evaluated several times, each with a different node set
286N/A * acting as the context of the expression. The first time the expression is
286N/A * evaluated, the context node set is the first argument passed to the dyn:closure
286N/A * function. In other words, the node set for each node is calculated by evaluating
286N/A * the XPath expression with all context information being the same as that for
286N/A * the call to the dyn:closure function itself, except for the following:
286N/A * <p>
286N/A * <ul>
286N/A * <li>the context node is the node whose value is being calculated.</li>
286N/A * <li>the context position is the position of the node within the node set passed
286N/A * as the first argument to the dyn:closure function, arranged in document order.</li>
286N/A * <li>the context size is the number of nodes passed as the first argument to the
286N/A * dyn:closure function.</li>
286N/A * <li>the current node is the node whose value is being calculated.</li>
286N/A * </ul>
286N/A * <p>
286N/A * The result for a particular iteration is the union of the node sets resulting
286N/A * from evaluting the expression for each of the nodes in the source node set for
286N/A * that iteration. This result is then used as the source node set for the next
286N/A * iteration, and so on. The result of the function as a whole is the union of
286N/A * the node sets generated by each iteration.
286N/A * <p>
286N/A * If the expression string passed as the second argument is an invalid XPath
286N/A * expression (including an empty string) or an expression that does not return a
286N/A * node set, this function returns an empty node set.
286N/A *
286N/A * @param myContext The ExpressionContext passed by the extension processor
286N/A * @param nl The node set
286N/A * @param expr The expression string
286N/A *
286N/A * @return The node set after evaluation
286N/A */
286N/A public static NodeList closure(ExpressionContext myContext, NodeList nl, String expr)
286N/A throws SAXNotSupportedException
286N/A {
286N/A XPathContext xctxt = null;
286N/A if (myContext instanceof XPathContext.XPathExpressionContext)
286N/A xctxt = ((XPathContext.XPathExpressionContext) myContext).getXPathContext();
286N/A else
286N/A throw new SAXNotSupportedException(XSLMessages.createMessage(XSLTErrorResources.ER_INVALID_CONTEXT_PASSED, new Object[]{myContext }));
286N/A
286N/A if (expr == null || expr.length() == 0)
286N/A return new NodeSet();
286N/A
286N/A NodeSet closureSet = new NodeSet();
286N/A closureSet.setShouldCacheNodes(true);
286N/A
286N/A NodeList iterationList = nl;
286N/A do
286N/A {
286N/A
286N/A NodeSet iterationSet = new NodeSet();
286N/A
286N/A NodeSetDTM contextNodes = new NodeSetDTM(iterationList, xctxt);
286N/A xctxt.pushContextNodeList(contextNodes);
286N/A
286N/A for (int i = 0; i < iterationList.getLength(); i++)
286N/A {
286N/A int contextNode = contextNodes.item(i);
286N/A xctxt.pushCurrentNode(contextNode);
286N/A
286N/A XObject object = null;
286N/A try
286N/A {
286N/A XPath dynamicXPath = new XPath(expr, xctxt.getSAXLocator(),
286N/A xctxt.getNamespaceContext(),
286N/A XPath.SELECT);
286N/A object = dynamicXPath.execute(xctxt, contextNode, xctxt.getNamespaceContext());
286N/A
286N/A if (object instanceof XNodeSet)
286N/A {
286N/A NodeList nodelist = null;
286N/A nodelist = ((XNodeSet)object).nodelist();
286N/A
286N/A for (int k = 0; k < nodelist.getLength(); k++)
286N/A {
286N/A Node n = nodelist.item(k);
286N/A if (!iterationSet.contains(n))
286N/A iterationSet.addNode(n);
286N/A }
286N/A }
286N/A else
286N/A {
286N/A xctxt.popCurrentNode();
286N/A xctxt.popContextNodeList();
286N/A return new NodeSet();
286N/A }
286N/A }
286N/A catch (TransformerException e)
286N/A {
286N/A xctxt.popCurrentNode();
286N/A xctxt.popContextNodeList();
286N/A return new NodeSet();
286N/A }
286N/A
286N/A xctxt.popCurrentNode();
286N/A
286N/A }
286N/A
286N/A xctxt.popContextNodeList();
286N/A
286N/A iterationList = iterationSet;
286N/A
286N/A for (int i = 0; i < iterationList.getLength(); i++)
286N/A {
286N/A Node n = iterationList.item(i);
286N/A if (!closureSet.contains(n))
286N/A closureSet.addNode(n);
286N/A }
286N/A
286N/A } while(iterationList.getLength() > 0);
286N/A
286N/A return closureSet;
286N/A
286N/A }
286N/A
286N/A}