Пример #1
0
  /**
   * Show how to run two queries in tandem. The second query is applied to the results of the first.
   */
  public static void examplePipeline() throws XPathException {
    final Configuration config = new Configuration();

    // Compile the first query
    final StaticQueryContext sqc1 = config.newStaticQueryContext();
    final XQueryExpression exp1 =
        sqc1.compileQuery(
            "declare variable $in as xs:integer external;" + "document{ <a>{$in * $in}</a> }");

    // Compile the second query (each query should have its own static context)
    final StaticQueryContext sqc2 = config.newStaticQueryContext();
    final XQueryExpression exp2 = sqc2.compileQuery("/a + 5");

    // Run the first query
    final DynamicQueryContext dynamicContext = new DynamicQueryContext(config);
    dynamicContext.setParameterValue("in", Int64Value.makeIntegerValue(3));
    final NodeInfo doc = (NodeInfo) exp1.evaluateSingle(dynamicContext);

    // Run the second query
    dynamicContext.clearParameters();
    dynamicContext.setContextItem(doc);
    final Object result = exp2.evaluateSingle(dynamicContext);
    System.out.println("3*3 + 5 = " + result);
    // The result is actually a java.lang.Double
  }
 /**
  * Construct an atomic value given its lexical representation and the name of the required
  * built-in atomic type.
  *
  * <p>This method cannot be used to construct values that are namespace-sensitive (QNames and
  * Notations)
  *
  * @param lexicalForm the value in the lexical space of the target data type. More strictly, the
  *     input value before the actions of the whitespace facet for the target data type are
  *     applied.
  * @param type the required atomic type. This must either be one of the built-in atomic types
  *     defined in XML Schema, or a user-defined type whose definition appears in a schema that is
  *     known to the Processor. It must not be an abstract type.
  * @throws SaxonApiException if the type is unknown, or is not atomic, or is namespace-sensitive;
  *     or if the value supplied in <tt>lexicalForm</tt> is not in the lexical space of the
  *     specified atomic type.
  */
 public XdmAtomicValue(String lexicalForm, ItemType type) throws SaxonApiException {
   net.sf.saxon.type.ItemType it = type.getUnderlyingItemType();
   if (!it.isAtomicType()) {
     throw new SaxonApiException("Requested type is not atomic");
   }
   if (((AtomicType) it).isAbstract()) {
     throw new SaxonApiException("Requested type is an abstract type");
   }
   if (((AtomicType) it).isNamespaceSensitive()) {
     throw new SaxonApiException("Requested type is namespace-sensitive");
   }
   if (((AtomicType) it).isBuiltInType()) {
     ConversionResult cv =
         StringValue.convertStringToBuiltInType(
             lexicalForm, (BuiltInAtomicType) it, new Name11Checker());
     try {
       setValue(cv.asAtomic());
     } catch (ValidationException e) {
       throw new SaxonApiException(e);
     }
   } else {
     Configuration config =
         ((ConstructedItemType) type).getProcessor().getUnderlyingConfiguration();
     ConversionResult result =
         new StringValue(lexicalForm)
             .convert((AtomicType) it, true, config.getConversionContext());
     try {
       setValue(result.asAtomic());
     } catch (ValidationException e) {
       throw new SaxonApiException(e);
     }
   }
 }
Пример #3
0
  /**
   * Show a query producing a single atomic value as its result and returning the value to the Java
   * application
   */
  public static void exampleToSingleton() throws XPathException {
    final Configuration config = new Configuration();
    final StaticQueryContext sqc = config.newStaticQueryContext();
    final XQueryExpression exp = sqc.compileQuery("avg(for $i in 1 to 10 return $i*$i)");

    final DynamicQueryContext dynamicContext = new DynamicQueryContext(config);
    final BigDecimal result = (BigDecimal) exp.evaluateSingle(dynamicContext);
    System.out.println(result);
  }
Пример #4
0
 /**
  * Show how to run a query that is read from a file and that serializes its output as HTML to
  * another file. The input to the query (the initial value of the context node) is supplied as the
  * content of another file.
  */
 public static void exampleToHTMLFile() throws XPathException, IOException {
   final Configuration config = new Configuration();
   final StaticQueryContext sqc = config.newStaticQueryContext();
   final XQueryExpression exp = sqc.compileQuery(new FileReader("query/books-to-html.xq"));
   final DynamicQueryContext dynamicContext = new DynamicQueryContext(config);
   dynamicContext.setContextItem(config.buildDocument(new StreamSource("data/books.xml")));
   final Properties props = new Properties();
   props.setProperty(OutputKeys.METHOD, "html");
   props.setProperty(OutputKeys.DOCTYPE_PUBLIC, "-//W3C//DTD HTML 4.01 Transitional//EN");
   exp.run(dynamicContext, new StreamResult(new File("booklist.html")), props);
 }
Пример #5
0
  /** Show a query producing a document as its result and serializing this directly to System.out */
  public static void exampleToStreamResult() throws XPathException {
    final Configuration config = new Configuration();
    final StaticQueryContext sqc = config.newStaticQueryContext();
    final XQueryExpression exp = sqc.compileQuery("<a b='c'>{5+2}</a>");

    final DynamicQueryContext dynamicContext = new DynamicQueryContext(config);
    final Properties props = new Properties();
    props.setProperty(OutputKeys.METHOD, "xml");
    props.setProperty(OutputKeys.INDENT, "yes");
    exp.run(dynamicContext, new StreamResult(System.out), props);
  }
Пример #6
0
  /**
   * Show a query that takes a parameter (external variable) as input. The query produces a single
   * atomic value as its result and returns the value to the Java application. For the types of
   * value that may be returned, and their mapping to XPath data types, see {@link
   * XPathEvaluator#evaluate}
   */
  public static void exampleWithParam() throws XPathException {
    final Configuration config = new Configuration();
    final StaticQueryContext sqc = config.newStaticQueryContext();
    final XQueryExpression exp =
        sqc.compileQuery("declare variable $in as xs:integer external;" + "$in * $in");

    final DynamicQueryContext dynamicContext = new DynamicQueryContext(config);
    dynamicContext.setParameterValue("in", Int64Value.makeIntegerValue(17));
    final Long result = (Long) exp.evaluateSingle(dynamicContext);
    System.out.println("17 * 17 = " + result);
  }
Пример #7
0
 public XQueryExecutor(TraceExtension traceExtension) {
   this.traceExtension = traceExtension;
   Configuration configuration = Configuration.newConfiguration();
   if (!traceExtension.allowsOptimization()) {
     configuration.setConfigurationProperty(OPTIMIZATION_LEVEL, String.valueOf(NO_OPTIMIZATION));
   }
   configuration.setModuleURIResolver(new ClasspathModuleUriResolver());
   Processor processor = new Processor(configuration);
   xQueryCompiler = processor.newXQueryCompiler();
   StaticQueryContext staticQueryContext = xQueryCompiler.getUnderlyingStaticContext();
   staticQueryContext.setCodeInjector(traceExtension.getTraceCodeInjector());
 }
Пример #8
0
  /**
   * Show a query producing a sequence as its result and returning the sequence to the Java
   * application in the form of an iterator. The sequence is treated as if it were the content of a
   * document{...} constructor. Note that it must not contain free-standing attribute nodes.
   */
  public static void exampleToSerializedSequence() throws XPathException {
    final Configuration config = new Configuration();
    final StaticQueryContext sqc = config.newStaticQueryContext();
    final XQueryExpression exp =
        sqc.compileQuery("<doc><chap><a>3</a></chap></doc>//a, <b>4</b>, 19");
    Properties props = new Properties();
    props.setProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");

    final DynamicQueryContext dynamicContext = new DynamicQueryContext(config);
    final SequenceIterator iter = exp.iterator(dynamicContext);
    QueryResult.serializeSequence(iter, config, System.out, props);
  }
  /**
   * Set the expression defining the value of the attribute. If this is a constant, and if
   * validation against a schema type was requested, the validation is done immediately.
   *
   * @param select The expression defining the content of the attribute
   * @param config
   * @throws StaticError if the expression is a constant, and validation is requested, and the
   *     constant doesn't match the required type.
   */
  public void setSelect(Expression select, Configuration config) throws StaticError {
    super.setSelect(select, config);

    // Attempt early validation if possible
    if (select instanceof AtomicValue && schemaType != null && !schemaType.isNamespaceSensitive()) {
      CharSequence value = ((AtomicValue) select).getStringValueCS();
      XPathException err =
          schemaType.validateContent(
              value, DummyNamespaceResolver.getInstance(), config.getNameChecker());
      if (err != null) {
        StaticError se =
            new StaticError(
                "Attribute value "
                    + Err.wrap(value, Err.VALUE)
                    + " does not the match the required type "
                    + schemaType.getDescription()
                    + ". "
                    + err.getMessage());
        se.setErrorCode("XTTE1540");
        throw se;
      }
    }

    // If value is fixed, test whether there are any special characters that might need to be
    // escaped when the time comes for serialization
    if (select instanceof StringValue) {
      boolean special = false;
      CharSequence val = ((StringValue) select).getStringValueCS();
      for (int k = 0; k < val.length(); k++) {
        char c = val.charAt(k);
        if ((int) c < 33 || (int) c > 126 || c == '<' || c == '>' || c == '&' || c == '\"') {
          special = true;
          break;
        }
      }
      if (!special) {
        this.options |= ReceiverOptions.NO_SPECIAL_CHARS;
      }
    }

    // If attribute name is xml:id, add whitespace normalization
    if ((nameCode & NamePool.FP_MASK) == StandardNames.XML_ID) {
      Expression[] args = {select};
      FunctionCall fn =
          SystemFunction.makeSystemFunction("normalize-space", 1, config.getNamePool());
      fn.setArguments(args);
      select = fn;
      super.setSelect(select, config);
    }
  }
Пример #10
0
  /**
   * Show a query producing a sequence as its result and returning the sequence to the Java
   * application in the form of an iterator. The sequence is then output by wrapping the items in a
   * document, with wrapping elements indicating the type of each item, and serializing the
   * resulting document.
   */
  public static void exampleToWrappedSequence() throws XPathException {
    final Configuration config = new Configuration();
    final StaticQueryContext sqc = config.newStaticQueryContext();
    final XQueryExpression exp =
        sqc.compileQuery("<doc><chap><a>3</a></chap></doc>//a, <b>4</b>, attribute c {5}, 19");
    Properties props = new Properties();
    props.setProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
    props.setProperty(OutputKeys.INDENT, "yes");

    final DynamicQueryContext dynamicContext = new DynamicQueryContext(config);
    final SequenceIterator iter = exp.iterator(dynamicContext);
    final DocumentInfo doc = QueryResult.wrap(iter, config);
    QueryResult.serialize(doc, new StreamResult(System.out), props);
  }
Пример #11
0
  /**
   * Show a query producing a DOM as its output. The DOM is then serialized using an identity
   * transform
   */
  public static void exampleToDOM() throws TransformerException {
    final Configuration config = new Configuration();
    final StaticQueryContext sqc = config.newStaticQueryContext();
    final XQueryExpression exp =
        sqc.compileQuery("<a xmlns='http://a/uri' xmlns:a='another.uri'>text</a>");

    final DynamicQueryContext dynamicContext = new DynamicQueryContext(config);
    DOMResult result = new DOMResult();
    exp.run(dynamicContext, result, new Properties());

    // now serialize the DOM

    Transformer identity = TransformerFactory.newInstance().newTransformer();
    identity.transform(new DOMSource(result.getNode()), new StreamResult(System.out));
  }
Пример #12
0
  /**
   * Show a query producing a sequence as its result and returning the sequence to the Java
   * application in the form of an iterator. For each item in the result, its string value is
   * output.
   */
  public static void exampleToSequence() throws XPathException {
    final Configuration config = new Configuration();
    final StaticQueryContext sqc = config.newStaticQueryContext();
    final XQueryExpression exp = sqc.compileQuery("for $i in 1 to 10 return ($i * $i)");

    final DynamicQueryContext dynamicContext = new DynamicQueryContext(config);
    final SequenceIterator iter = exp.iterator(dynamicContext);
    while (true) {
      Item item = iter.next();
      if (item == null) {
        break;
      }
      System.out.println(item.getStringValue());
    }
  }
Пример #13
0
 public static Object getValue(
     Class<?> type, Item colItem, Configuration config, CommandContext context)
     throws XPathException, ValidationException, TransformationException {
   Object value = colItem;
   if (value instanceof AtomicValue) {
     value = getValue((AtomicValue) colItem, context);
   } else if (value instanceof Item) {
     Item i = (Item) value;
     if (XMLSystemFunctions.isNull(i)) {
       return null;
     }
     BuiltInAtomicType bat = typeMapping.get(type);
     if (bat != null) {
       AtomicValue av = new StringValue(i.getStringValueCS());
       ConversionResult cr = Converter.convert(av, bat, config.getConversionRules());
       value = cr.asAtomic();
       value = getValue((AtomicValue) value, context);
       if (value instanceof Item) {
         value = ((Item) value).getStringValue();
       }
     } else {
       value = i.getStringValue();
     }
   }
   return FunctionDescriptor.importValue(value, type);
 }
 /** Display this instruction as an expression, for diagnostics */
 public void display(int level, PrintStream out, Configuration config) {
   out.println(ExpressionTool.indent(level) + "attribute ");
   out.println(
       ExpressionTool.indent(level + 1)
           + "name "
           + (config == null ? nameCode + "" : config.getNamePool().getDisplayName(nameCode)));
   super.display(level + 1, out, config);
 }
Пример #15
0
  /** Create a StandaloneContext using a specific NamePool */
  public StandaloneContext(Configuration config) {
    this.config = config;
    namePool = config.getNamePool();
    stackFrameMap = config.makeSlotManager();
    clearNamespaces();

    // Set up a default function library. This can be overridden using setFunctionLibrary()

    FunctionLibraryList lib = new FunctionLibraryList();
    lib.addFunctionLibrary(new SystemFunctionLibrary(SystemFunctionLibrary.XPATH_ONLY));
    lib.addFunctionLibrary(getConfiguration().getVendorFunctionLibrary());
    lib.addFunctionLibrary(new ConstructorFunctionLibrary(getConfiguration()));
    if (config.isAllowExternalFunctions()) {
      xpathFunctionLibrary = new XPathFunctionLibrary();
      lib.addFunctionLibrary(xpathFunctionLibrary);
      lib.addFunctionLibrary(new JavaExtensionLibrary(getConfiguration()));
    }
    functionLibrary = lib;
  }
 /**
  * Allows the user to set specific attributes on the underlying implementation.
  *
  * @param name The name of the attribute. For Saxon this must be one of the names defined in
  *     {@link FeatureKeys}
  * @param value The value of the attribute.
  * @exception IllegalArgumentException thrown if the underlying implementation doesn't recognize
  *     the attribute.
  */
 public void setAttribute(String name, Object value) {
   if (name.equals(FeatureKeys.CONFIGURATION)) {
     config = (Configuration) value;
   } else {
     if (config == null) {
       config = new Configuration();
     }
     config.setConfigurationProperty(name, value);
   }
 }
 /*@Nullable*/ public Object getAttribute(String name) {
   if (name.equals(FeatureKeys.CONFIGURATION)) {
     return config;
   } else {
     if (config == null) {
       config = new Configuration();
     }
     return config.getConfigurationProperty(name);
   }
 }
Пример #18
0
 private String serialize(final Object o, final String method, final boolean includeProlog)
     throws XPathException {
   if (o instanceof NodeInfo) {
     final NodeInfo nodeInfo = ((NodeInfo) o);
     final Configuration config = nodeInfo.getConfiguration();
     final StringWriter sw = new StringWriter();
     final Properties props = new Properties();
     props.setProperty("method", method);
     props.setProperty("indent", "no");
     if (!includeProlog) {
       props.setProperty("omit-xml-declaration", "yes");
     } else {
       props.setProperty("omit-xml-declaration", "no");
     }
     final Receiver serializer =
         config
             .getSerializerFactory()
             .getReceiver(new StreamResult(sw), config.makePipelineConfiguration(), props);
     nodeInfo.copy(serializer, NodeInfo.ALL_NAMESPACES, true, 0);
     return sw.toString();
   }
   return null;
 }
Пример #19
0
  /** Supporting routine to load one external file given a URI (href) and a baseURI */
  public CharSequence readFile(String href, String baseURI, String encoding, XPathContext context)
      throws XPathException {

    final Configuration config = context.getConfiguration();
    NameChecker checker = config.getNameChecker();

    // Use the URI machinery to validate and resolve the URIs

    URI absoluteURI = getAbsoluteURI(href, baseURI);

    Reader reader;
    try {
      reader =
          context
              .getController()
              .getUnparsedTextURIResolver()
              .resolve(absoluteURI, encoding, config);
    } catch (XPathException err) {
      err.maybeSetErrorCode("XTDE1170");
      err.maybeSetLocation(this);
      throw err;
    }
    try {
      return readFile(checker, reader);
    } catch (java.io.UnsupportedEncodingException encErr) {
      XPathException e = new XPathException("Unknown encoding " + Err.wrap(encoding), encErr);
      e.setErrorCode("XTDE1190");
      throw e;
    } catch (java.io.IOException ioErr) {
      //            System.err.println("ProxyHost: " + System.getProperty("http.proxyHost"));
      //            System.err.println("ProxyPort: " + System.getProperty("http.proxyPort"));
      XPathException e = handleIOError(absoluteURI, ioErr);
      e.setLocator(this);
      throw e;
    }
  }
Пример #20
0
  /**
   * Show a direct call from the Java application to a function defined in the Query. This is a very
   * efficient way of invoking a query, but it does minimal checking of the supplied arguments
   */
  public static void exampleDirectFunction() throws XPathException {
    final Configuration config = new Configuration();
    final StaticQueryContext sqc = config.newStaticQueryContext();
    final XQueryExpression exp1 =
        sqc.compileQuery(
            "declare namespace f='f.ns';"
                + "declare function f:t1($v1 as xs:integer, $v2 as xs:untypedAtomic*) { "
                + "   $v1 div $v2"
                + "};"
                + "10");

    final UserFunction fn1 = exp1.getStaticContext().getUserDefinedFunction("f.ns", "t1", 2);
    if (fn1 == null) {
      throw new IllegalStateException("Function f:t1() not found");
    }
    final Controller controller = exp1.newController();
    final Value[] arglist = new Value[2];
    arglist[0] = new Int64Value(10);
    for (int i = 3; i < 10; i++) {
      arglist[1] = new Int64Value(i);
      final ValueRepresentation result = fn1.call(arglist, controller);
      System.out.println(arglist[0] + " div " + arglist[1] + " = " + result);
    }
  }
Пример #21
0
 private static Source wrapStax(Source value, Configuration config)
     throws TeiidProcessingException {
   if (value instanceof StAXSource) {
     // saxon doesn't like staxsources
     StaxToEventBridge sb = new StaxToEventBridge();
     sb.setPipelineConfiguration(config.makePipelineConfiguration());
     StAXSource staxSource = (StAXSource) value;
     if (staxSource.getXMLEventReader() != null) {
       try {
         sb.setXMLStreamReader(new XMLEventStreamReader(staxSource.getXMLEventReader()));
       } catch (XMLStreamException e) {
         // should not happen as the StAXSource already peeked
         throw new TeiidProcessingException(e);
       }
     } else {
       sb.setXMLStreamReader(staxSource.getXMLStreamReader());
     }
     value = new PullEventSource(sb);
   }
   return value;
 }
  /** Allocate a Comparator to perform the comparisons described by this sort key component */
  public Comparator makeComparator(XPathContext context) throws XPathException {

    String orderX = order.evaluateAsString(context);

    final Configuration config = context.getConfiguration();
    final TypeHierarchy th = config.getTypeHierarchy();

    Comparator comp;
    if (collation != null) {
      comp = collation;
    } else if (collationName != null) {
      String cname = collationName.evaluateAsString(context);
      URI collationURI;
      try {
        collationURI = new URI(cname);
        if (!collationURI.isAbsolute()) {
          if (baseURI == null) {
            throw new DynamicError("Collation URI is relative, and base URI is unknown");
          } else {
            URI base = new URI(baseURI);
            collationURI = base.resolve(collationURI);
          }
        }
      } catch (URISyntaxException err) {
        throw new DynamicError("Collation name " + cname + " is not a valid URI: " + err);
      }
      try {
        comp = context.getCollation(collationURI.toString());
      } catch (XPathException e) {
        if ("FOCH0002".equals(e.getErrorCodeLocalPart())) {
          e.setErrorCode("XTDE1035");
        }
        throw e;
      }
    } else {
      String caseOrderX = caseOrder.evaluateAsString(context);
      String languageX = language.evaluateAsString(context);
      Properties props = new Properties();
      if (!languageX.equals("")) {
        props.setProperty("lang", languageX);
      }
      if (!caseOrderX.equals("#default")) {
        props.setProperty("case-order", caseOrderX);
      }
      comp = config.getPlatform().makeCollation(config, props);
    }

    if (dataTypeExpression == null) {
      int type = sortKey.getItemType(th).getAtomizedItemType().getPrimitiveType();
      comp = AtomicSortComparer.makeSortComparer(comp, type, context);
      if (!emptyLeast) {
        comp = new EmptyGreatestComparer((AtomicComparer) comp);
      }
    } else {
      String dataType = dataTypeExpression.evaluateAsString(context);
      if (dataType.equals("text")) {
        comp = new TextComparer(comp);
      } else if (dataType.equals("number")) {
        comp = NumericComparer.getInstance();
      } else {
        DynamicError err = new DynamicError("data-type on xsl:sort must be 'text' or 'number'");
        err.setErrorCode("XTDE0030");
        throw err;
      }
    }

    if (stable != null) {
      StringValue stableVal = (StringValue) stable.evaluateItem(context);
      String s = stableVal.getStringValue().trim();
      if (s.equals("yes") || s.equals("no")) {
        // no action
      } else {
        DynamicError err = new DynamicError("Value of 'stable' on xsl:sort must be 'yes' or 'no'");
        err.setErrorCode("XTDE0030");
        throw err;
      }
    }

    if (orderX.equals("ascending")) {
      return comp;
    } else if (orderX.equals("descending")) {
      return new DescendingComparer(comp);
    } else {
      DynamicError err1 = new DynamicError("order must be 'ascending' or 'descending'");
      err1.setErrorCode("XTDE0030");
      throw err1;
    }
  }
 public DocumentBuilderFactoryImpl() {
   this(Configuration.newConfiguration());
 }
Пример #24
0
  /**
   * Evaluate expression and return opaque type
   *
   * @param cexp cexp
   * @param ctx ctx
   * @param type type
   * @return type
   * @throws FaultException FaultException
   * @throws EvaluationException EvaluationException
   */
  private Object evaluate(OExpression cexp, EvaluationContext ctx, QName type)
      throws FaultException, EvaluationException {
    try {
      OXQuery10ExpressionBPEL20 oxquery10 = ((OXQuery10ExpressionBPEL20) cexp);

      XQDataSource xqds = new SaxonXQDataSource();
      XQConnection xqconn = xqds.getConnection();

      Configuration configuration = ((SaxonXQConnection) xqconn).getConfiguration();
      configuration.setAllNodesUntyped(true);
      configuration.setHostLanguage(Configuration.XQUERY);

      XQStaticContext staticEnv = xqconn.getStaticContext();

      NSContext nsContext = oxquery10.getNamespaceCtx();
      Set<String> prefixes = nsContext.getPrefixes();
      for (String prefix : prefixes) {
        String uri = nsContext.getNamespaceURI(prefix);
        staticEnv.declareNamespace(prefix, uri);
      }

      configuration.setSchemaValidationMode(Validation.SKIP);
      xqconn.setStaticContext(staticEnv);

      // Prepare expression, for starters
      String xquery =
          oxquery10
              .getXquery()
              .replaceFirst(
                  Constants.XQUERY_FUNCTION_HANDLER_COMPILER,
                  Constants.XQUERY_FUNCTION_HANDLER_RUNTIME);
      XQPreparedExpression exp = xqconn.prepareExpression(xquery);

      JaxpFunctionResolver funcResolver = new JaxpFunctionResolver(ctx, oxquery10);
      JaxpVariableResolver variableResolver =
          new JaxpVariableResolver(ctx, oxquery10, configuration);
      // Bind external variables to runtime values
      for (QName variable : exp.getAllUnboundExternalVariables()) {
        // Evaluate referenced variable
        Object value = variableResolver.resolveVariable(variable);

        if (value instanceof Value) {
          SaxonXQConnection saxonConn = (SaxonXQConnection) xqconn;
          try {
            Item item = ((Value) value).asItem();
            if (item == null) {
              exp.bindSequence(variable, xqconn.createSequence(Collections.EMPTY_LIST.iterator()));
            } else {
              XQItem item2 = new SaxonXQItem(item, saxonConn);
              exp.bindItem(variable, item2);
            }
          } catch (XPathException e) {
            __log.warn("", e);
          }
        } else {

          if (value instanceof Date) {
            Date d = (Date) value;
            value = org.apache.ode.utils.ISO8601DateParser.format(d);
          }

          // Figure out type of variable
          XQSequenceType xqType = getItemType(xqconn, value);

          // Saxon doesn't like binding sequences to variables
          if (value instanceof Node) {
            // a node is a node-list, but the inverse isn't true.
            // so, if the value is truly a node, leave it alone.
          } else if (value instanceof NodeList) {
            // So extract the first item from the node list
            NodeList nodeList = (NodeList) value;
            ArrayList nodeArray = new ArrayList();
            for (int i = 0; i < nodeList.getLength(); i++) {
              nodeArray.add(nodeList.item(i));
            }
            value = xqconn.createSequence(nodeArray.iterator());
          }

          // Bind value with external variable
          if (value != null && xqType != null) {
            if (value instanceof XQSequence) {
              exp.bindSequence(variable, (XQSequence) value);
            } else {
              if (xqType instanceof XQItemType) {
                exp.bindObject(variable, value, (XQItemType) xqType);
              }
            }
          }
        }
      }

      // Set context node
      Node contextNode = (ctx.getRootNode() == null) ? DOMUtils.newDocument() : ctx.getRootNode();
      contextNode.setUserData(
          XQuery10BpelFunctions.USER_DATA_KEY_FUNCTION_RESOLVER, funcResolver, null);
      exp.bindItem(
          XQConstants.CONTEXT_ITEM,
          xqconn.createItemFromNode(contextNode, xqconn.createNodeType()));

      // Execute query
      XQResultSequence result = exp.executeQuery();

      // Cast Saxon result to Java result
      Object evalResult = getResultValue(type, result);

      if ((evalResult != null) && __log.isDebugEnabled()) {
        __log.debug(
            "Expression "
                + cexp.toString()
                + " generated result "
                + evalResult
                + " - type="
                + evalResult.getClass().getName());

        if (ctx.getRootNode() != null) {
          __log.debug("Was using context node " + DOMUtils.domToString(ctx.getRootNode()));
        }
      }

      return evalResult;
    } catch (XQException xqe) {
      // Extracting the real cause from all this wrapping isn't a simple task
      Throwable cause = (xqe.getCause() != null) ? xqe.getCause() : xqe;

      if (cause instanceof DynamicError) {
        Throwable th = ((DynamicError) cause).getException();

        if (th != null) {
          cause = th;

          if (cause.getCause() != null) {
            cause = cause.getCause();
          }
        }
      }

      throw new EvaluationException(
          "Error while executing an XQuery expression: " + cause.toString(), cause);
    } catch (WrappedResolverException wre) {
      __log.debug("Could not evaluate expression because of ", wre);
      throw (FaultException) wre.getCause();
    }
  }