[teiid-commits] teiid SVN: r2107 - in trunk: connector-api/src/main/java/org/teiid/connector/api and 13 other directories.

teiid-commits at lists.jboss.org teiid-commits at lists.jboss.org
Fri May 7 17:35:46 EDT 2010


Author: shawkins
Date: 2010-05-07 17:35:44 -0400 (Fri, 07 May 2010)
New Revision: 2107

Removed:
   trunk/engine/src/main/java/com/metamatrix/internal/core/xml/XPathHelper.java
   trunk/engine/src/test/java/com/metamatrix/internal/core/xml/TestXPathHelper.java
Modified:
   trunk/common-core/src/main/java/com/metamatrix/common/types/XMLType.java
   trunk/connector-api/src/main/java/org/teiid/connector/api/SourceSystemFunctions.java
   trunk/documentation/reference/src/main/docbook/en-US/content/scalar_functions.xml
   trunk/engine/src/main/java/com/metamatrix/query/function/source/SystemSource.java
   trunk/engine/src/main/java/com/metamatrix/query/function/source/XMLSystemFunctions.java
   trunk/engine/src/main/java/com/metamatrix/query/resolver/util/ResolverVisitor.java
   trunk/engine/src/main/java/com/metamatrix/query/sql/visitor/SQLStringVisitor.java
   trunk/engine/src/main/java/com/metamatrix/query/validator/ValidationVisitor.java
   trunk/engine/src/main/resources/com/metamatrix/query/i18n.properties
   trunk/engine/src/test/java/com/metamatrix/query/function/TestFunctionLibrary.java
   trunk/engine/src/test/java/com/metamatrix/query/function/source/TestXMLSystemFunctions.java
   trunk/engine/src/test/java/com/metamatrix/query/parser/TestParser.java
   trunk/engine/src/test/java/com/metamatrix/query/resolver/TestResolver.java
   trunk/engine/src/test/java/com/metamatrix/query/validator/TestValidator.java
Log:
TEIID-1087: added support xpathquery that returns a full result (as opposed to xpathvalue) and allowed both functions to be namespace aware.  

Modified: trunk/common-core/src/main/java/com/metamatrix/common/types/XMLType.java
===================================================================
--- trunk/common-core/src/main/java/com/metamatrix/common/types/XMLType.java	2010-05-07 20:25:05 UTC (rev 2106)
+++ trunk/common-core/src/main/java/com/metamatrix/common/types/XMLType.java	2010-05-07 21:35:44 UTC (rev 2107)
@@ -46,7 +46,7 @@
 public final class XMLType extends Streamable<SQLXML> implements SQLXML {
 	
 	public enum Type {
-		UNKNOWN, DOCUMENT, FRAGMENT, SIBLINGS, COMMENT, PI
+		UNKNOWN, DOCUMENT, FRAGMENT, SIBLINGS, COMMENT, PI, TEXT
 	}
 	
 	private static final long serialVersionUID = -7922647237095135723L;

Modified: trunk/connector-api/src/main/java/org/teiid/connector/api/SourceSystemFunctions.java
===================================================================
--- trunk/connector-api/src/main/java/org/teiid/connector/api/SourceSystemFunctions.java	2010-05-07 20:25:05 UTC (rev 2106)
+++ trunk/connector-api/src/main/java/org/teiid/connector/api/SourceSystemFunctions.java	2010-05-07 21:35:44 UTC (rev 2107)
@@ -136,6 +136,7 @@
 	
 	//xml
 	public static final String XPATHVALUE = "xpathvalue"; //$NON-NLS-1$
+	public static final String XPATHQUERY = "xpathquery"; //$NON-NLS-1$
 	public static final String XSLTRANSFORM = "xsltransform"; //$NON-NLS-1$
 	public static final String XMLELEMENT = "xmlelement"; //$NON-NLS-1$
 	public static final String XMLCONCAT = "xmlconcat"; //$NON-NLS-1$

Modified: trunk/documentation/reference/src/main/docbook/en-US/content/scalar_functions.xml
===================================================================
--- trunk/documentation/reference/src/main/docbook/en-US/content/scalar_functions.xml	2010-05-07 20:25:05 UTC (rev 2106)
+++ trunk/documentation/reference/src/main/docbook/en-US/content/scalar_functions.xml	2010-05-07 21:35:44 UTC (rev 2107)
@@ -1932,25 +1932,38 @@
         <tbody>
           <row>
             <entry>
-              <para><code>XPATHVALUE(doc, xpath)</code></para>
+              <para><code>XPATHVALUE(doc, xpath [, namepaces])</code></para>
             </entry>
             <entry>
-              <para>Takes a document and an XPATH query and returns a
-                string value for the result. An attempt is made to provide a
+              <para>Applies the XPATH query to the document and returns a
+                string value for the first matching result. An attempt is made to provide a
                 meaningful result for non-text nodes.</para>
+              <para>The optional namespaces string is used to provide default and prefix to uri mappings for the given xpath. The format is the same as namespace declarations in an xml element: xmlns:foo="uri"</para>
             </entry>
             <entry>
-              <para>Doc in {string, xml} and xpath in {string}. Return value is a string.
+              <para>Doc in {string, xml} and xpath, namespaces in {string}. Return value is a string.
               </para>
             </entry>
           </row>
           <row>
             <entry>
+              <para><code>XPATHQUERY(doc, xpath [, namepaces])</code></para>
+            </entry>
+            <entry>
+              <para>Takes a document and an XPATH query and returns a SQL/XML of the result.</para>
+              <para>The optional namespaces string is used to provide default and prefix to uri mappings for the given xpath. The format is the same as namespace declarations in an xml element: xmlns:foo="uri"</para>
+            </entry>
+            <entry>
+              <para>Doc in {string, xml} and xpath, namespaces in {string}. Return value is a string.
+              </para>
+            </entry>
+          </row>
+          <row>
+            <entry>
               <para><code>XSLTRANSFORM(doc, xsl)</code></para>
             </entry>
             <entry>
-              <para>Takes a document and an xsl stylesheet and returns a
-                clob of the result.  If either argument is null, the result is null.</para>
+              <para>Applies an xsl stylesheet to the given document.  If either argument is null, the result is null.</para>
             </entry>
             <entry>
               <para>Doc, xsl in {string, xml}. Return value is a clob.

Deleted: trunk/engine/src/main/java/com/metamatrix/internal/core/xml/XPathHelper.java
===================================================================
--- trunk/engine/src/main/java/com/metamatrix/internal/core/xml/XPathHelper.java	2010-05-07 20:25:05 UTC (rev 2106)
+++ trunk/engine/src/main/java/com/metamatrix/internal/core/xml/XPathHelper.java	2010-05-07 21:35:44 UTC (rev 2107)
@@ -1,117 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * See the COPYRIGHT.txt file distributed with this work for information
- * regarding copyright ownership.  Some portions may be licensed
- * to Red Hat, Inc. under one or more contributor license agreements.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301 USA.
- */
-
-package com.metamatrix.internal.core.xml;
-
-import java.io.IOException;
-import java.io.Reader;
-
-import javax.xml.transform.Source;
-import javax.xml.transform.stream.StreamSource;
-
-import net.sf.saxon.om.Item;
-import net.sf.saxon.sxpath.XPathEvaluator;
-import net.sf.saxon.sxpath.XPathExpression;
-import net.sf.saxon.trans.XPathException;
-
-import com.metamatrix.core.util.ArgCheck;
-
-
-/** 
- * A collection of methods to help with evaluating an XPath against a document.  These
- * utilities currently use Jaxen for XPath implementation.
- * @since 4.2
- */
-public class XPathHelper {
-
-    /**
-     * Get the first XPath match when evaluating an XPath on a document.  If nothing is
-     * matched, null is returned.
-     * @param documentReader A reader for the XML document.  The reader will always be closed by this method.
-     * @param xpath An xpath expression, for example: a/b/c/getText()
-     * @return String representation of the first matching item or null if none
-     * @throws IllegalArgumentException If <code>documentReader</code> or <code>xpath</code> is null
-     * @throws XPathException If an error occurs evaluating the XPath
-     * @throws IOException If an error occurs closing the reader
-     * @since 4.2
-     */
-    public static String getSingleMatchAsString(Reader documentReader, String xpath) throws XPathException, IOException {        
-        Object o = getSingleMatch(documentReader, xpath);
-        
-        if(o == null) {
-            return null;
-        }
-        
-        // Return string value of node type
-        if(o instanceof Item) {
-            return ((Item)o).getStringValue();
-        }  
-        
-        // Return string representation of non-node value
-        return o.toString();
-    }
-
-    /**
-     * Get the first XPath match when evaluating an XPath on a document.  If nothing is
-     * matched, null is returned.
-     * @param documentReader A reader for the XML document.  The reader will always be closed by this method.
-     * @param xpath An xpath expression, for example: a/b/c/getText()
-     * @return String representation of the first matching item or null if none
-     * @throws IllegalArgumentException If <code>documentReader</code> or <code>xpath</code> is null
-     * @throws XPathException If an error occurs evaluating the XPath
-     * @throws IOException If an error occurs closing the reader
-     * @since 4.2
-     */
-    public static Object getSingleMatch(Reader documentReader, String xpath) throws XPathException, IOException {
-        ArgCheck.isNotNull(documentReader);
-        ArgCheck.isNotNull(xpath);
-
-        try {
-            Source s = new StreamSource(documentReader);
-            XPathEvaluator eval = new XPathEvaluator();
-            
-            // Wrap the string() function to force a string return             
-            XPathExpression expr = eval.createExpression(xpath);
-            return expr.evaluateSingle(s);
-            
-        } finally {
-            // Always close the reader
-            documentReader.close();
-        }
-    }
-    
-    /**
-     * Validate whether the XPath is a valid XPath.  If not valid, an XPathException will be thrown.
-     * @param xpath An xpath expression, for example: a/b/c/getText()
-     * @throws XPathException If an error occurs parsing the xpath
-     * @since 4.2
-     */
-    public static void validateXpath(String xpath) throws XPathException {
-        if(xpath == null) { 
-            return;
-        }
-        
-        XPathEvaluator eval = new XPathEvaluator();
-        eval.createExpression(xpath);       // throws XPathException
-    }
-
-}

Modified: trunk/engine/src/main/java/com/metamatrix/query/function/source/SystemSource.java
===================================================================
--- trunk/engine/src/main/java/com/metamatrix/query/function/source/SystemSource.java	2010-05-07 20:25:05 UTC (rev 2106)
+++ trunk/engine/src/main/java/com/metamatrix/query/function/source/SystemSource.java	2010-05-07 21:35:44 UTC (rev 2107)
@@ -166,7 +166,8 @@
 		addParseNumberFunctions();
         
         // xml functions
-        addXpathFunction();
+        addXpathQueryFunction();
+        addXpathValueFunction();
         addXslTransformFunction();
         addXmlElement();
         addXmlConcat();
@@ -881,25 +882,64 @@
         );
     }
     
-    /** 
-     * 
-     * @since 4.2
-     */
-    private void addXpathFunction() {
-        functions.add(new FunctionMethod(SourceSystemFunctions.XPATHVALUE, QueryPlugin.Util.getString("SystemSource.xpath_description"), XML, XML_FUNCTION_CLASS, "xpathValue", //$NON-NLS-1$ //$NON-NLS-2$ 
+    private void addXpathValueFunction() {
+        functions.add(new FunctionMethod(SourceSystemFunctions.XPATHVALUE, QueryPlugin.Util.getString("SystemSource.xpathvalue_description"), XML, XML_FUNCTION_CLASS, "xpathValue", //$NON-NLS-1$ //$NON-NLS-2$ 
                             new FunctionParameter[] { 
                                 new FunctionParameter("document", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.xpath_param1")), //$NON-NLS-1$ //$NON-NLS-2$
                                 new FunctionParameter("xpath", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.xpath_param2"))}, //$NON-NLS-1$ //$NON-NLS-2$ 
-                            new FunctionParameter("result", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.xpath_result")) ) );       //$NON-NLS-1$ //$NON-NLS-2$
+                            new FunctionParameter("result", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.xpathvalue_result")) ) );       //$NON-NLS-1$ //$NON-NLS-2$
 
-        functions.add(new FunctionMethod(SourceSystemFunctions.XPATHVALUE, QueryPlugin.Util.getString("SystemSource.xpath_description"), XML, XML_FUNCTION_CLASS, "xpathValue", //$NON-NLS-1$ //$NON-NLS-2$ 
+        functions.add(new FunctionMethod(SourceSystemFunctions.XPATHVALUE, QueryPlugin.Util.getString("SystemSource.xpathvalue_description"), XML, XML_FUNCTION_CLASS, "xpathValue", //$NON-NLS-1$ //$NON-NLS-2$ 
                                          new FunctionParameter[] { 
                                              new FunctionParameter("document", DataTypeManager.DefaultDataTypes.XML, QueryPlugin.Util.getString("SystemSource.xpath_param1")), //$NON-NLS-1$ //$NON-NLS-2$
                                              new FunctionParameter("xpath", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.xpath_param2"))}, //$NON-NLS-1$ //$NON-NLS-2$ 
-                                         new FunctionParameter("result", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.xpath_result")) ) );       //$NON-NLS-1$ //$NON-NLS-2$
+                                         new FunctionParameter("result", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.xpathvalue_result")) ) );       //$NON-NLS-1$ //$NON-NLS-2$
+        
+        functions.add(new FunctionMethod(SourceSystemFunctions.XPATHVALUE, QueryPlugin.Util.getString("SystemSource.xpathvalue_description"), XML, XML_FUNCTION_CLASS, "xpathValue", //$NON-NLS-1$ //$NON-NLS-2$ 
+                new FunctionParameter[] { 
+                    new FunctionParameter("document", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.xpath_param1")), //$NON-NLS-1$ //$NON-NLS-2$
+                    new FunctionParameter("xpath", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.xpath_param2")), //$NON-NLS-1$ //$NON-NLS-2$
+                    new FunctionParameter("namespace", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.xpath_param3"))}, //$NON-NLS-1$ //$NON-NLS-2$
+                new FunctionParameter("result", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.xpathvalue_result")) ) );       //$NON-NLS-1$ //$NON-NLS-2$
 
+        functions.add(new FunctionMethod(SourceSystemFunctions.XPATHVALUE, QueryPlugin.Util.getString("SystemSource.xpathvalue_description"), XML, XML_FUNCTION_CLASS, "xpathValue", //$NON-NLS-1$ //$NON-NLS-2$ 
+                             new FunctionParameter[] { 
+                                 new FunctionParameter("document", DataTypeManager.DefaultDataTypes.XML, QueryPlugin.Util.getString("SystemSource.xpath_param1")), //$NON-NLS-1$ //$NON-NLS-2$
+                                 new FunctionParameter("xpath", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.xpath_param2")), //$NON-NLS-1$ //$NON-NLS-2$
+                                 new FunctionParameter("namespace", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.xpath_param3"))}, //$NON-NLS-1$ //$NON-NLS-2$
+                             new FunctionParameter("result", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.xpathvalue_result")) ) );       //$NON-NLS-1$ //$NON-NLS-2$
+
     }
     
+    private void addXpathQueryFunction() {
+        functions.add(new FunctionMethod(SourceSystemFunctions.XPATHQUERY, QueryPlugin.Util.getString("SystemSource.xpath_description"), XML, XML_FUNCTION_CLASS, "xpathQuery", //$NON-NLS-1$ //$NON-NLS-2$ 
+                            new FunctionParameter[] { 
+                                new FunctionParameter("document", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.xpath_param1")), //$NON-NLS-1$ //$NON-NLS-2$
+                                new FunctionParameter("xpath", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.xpath_param2"))}, //$NON-NLS-1$ //$NON-NLS-2$ 
+                            new FunctionParameter("result", DataTypeManager.DefaultDataTypes.XML, QueryPlugin.Util.getString("SystemSource.xpath_result")) ) );       //$NON-NLS-1$ //$NON-NLS-2$
+
+        functions.add(new FunctionMethod(SourceSystemFunctions.XPATHQUERY, QueryPlugin.Util.getString("SystemSource.xpath_description"), XML, XML_FUNCTION_CLASS, "xpathQuery", //$NON-NLS-1$ //$NON-NLS-2$ 
+                                         new FunctionParameter[] { 
+                                             new FunctionParameter("document", DataTypeManager.DefaultDataTypes.XML, QueryPlugin.Util.getString("SystemSource.xpath_param1")), //$NON-NLS-1$ //$NON-NLS-2$
+                                             new FunctionParameter("xpath", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.xpath_param2"))}, //$NON-NLS-1$ //$NON-NLS-2$ 
+                                         new FunctionParameter("result", DataTypeManager.DefaultDataTypes.XML, QueryPlugin.Util.getString("SystemSource.xpath_result")) ) );       //$NON-NLS-1$ //$NON-NLS-2$
+
+        functions.add(new FunctionMethod(SourceSystemFunctions.XPATHQUERY, QueryPlugin.Util.getString("SystemSource.xpath_description"), XML, XML_FUNCTION_CLASS, "xpathQuery", //$NON-NLS-1$ //$NON-NLS-2$ 
+                new FunctionParameter[] { 
+                    new FunctionParameter("document", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.xpath_param1")), //$NON-NLS-1$ //$NON-NLS-2$
+                    new FunctionParameter("xpath", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.xpath_param2")), //$NON-NLS-1$ //$NON-NLS-2$ 
+                    new FunctionParameter("namespaces", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.xpath_param3"))}, //$NON-NLS-1$ //$NON-NLS-2$
+                new FunctionParameter("result", DataTypeManager.DefaultDataTypes.XML, QueryPlugin.Util.getString("SystemSource.xpath_result")) ) );       //$NON-NLS-1$ //$NON-NLS-2$
+
+        functions.add(new FunctionMethod(SourceSystemFunctions.XPATHQUERY, QueryPlugin.Util.getString("SystemSource.xpath_description"), XML, XML_FUNCTION_CLASS, "xpathQuery", //$NON-NLS-1$ //$NON-NLS-2$ 
+                             new FunctionParameter[] { 
+                                 new FunctionParameter("document", DataTypeManager.DefaultDataTypes.XML, QueryPlugin.Util.getString("SystemSource.xpath_param1")), //$NON-NLS-1$ //$NON-NLS-2$
+                                 new FunctionParameter("xpath", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.xpath_param2")), //$NON-NLS-1$ //$NON-NLS-2$ 
+                                 new FunctionParameter("namespaces", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.xpath_param3"))}, //$NON-NLS-1$ //$NON-NLS-2$
+                             new FunctionParameter("result", DataTypeManager.DefaultDataTypes.XML, QueryPlugin.Util.getString("SystemSource.xpath_result")) ) );       //$NON-NLS-1$ //$NON-NLS-2$
+
+    }
+    
     private void addXslTransformFunction() {
         functions.add(new FunctionMethod(SourceSystemFunctions.XSLTRANSFORM, QueryPlugin.Util.getString("SystemSource.xsltransform_description"), XML, XML_FUNCTION_CLASS, "xslTransform", //$NON-NLS-1$ //$NON-NLS-2$  
                             new FunctionParameter[] { 
@@ -1008,7 +1048,7 @@
      * Get all function signatures for this metadata source.
      * @return Unordered collection of {@link FunctionMethod}s
      */
-    public Collection getFunctionMethods() {
+    public Collection<FunctionMethod> getFunctionMethods() {
         return this.functions;
 	}
     

Modified: trunk/engine/src/main/java/com/metamatrix/query/function/source/XMLSystemFunctions.java
===================================================================
--- trunk/engine/src/main/java/com/metamatrix/query/function/source/XMLSystemFunctions.java	2010-05-07 20:25:05 UTC (rev 2106)
+++ trunk/engine/src/main/java/com/metamatrix/query/function/source/XMLSystemFunctions.java	2010-05-07 21:35:44 UTC (rev 2107)
@@ -27,11 +27,13 @@
 import java.io.Reader;
 import java.io.StringReader;
 import java.io.Writer;
+import java.sql.Clob;
 import java.sql.SQLException;
 import java.sql.SQLXML;
 import java.sql.Timestamp;
 import java.util.Calendar;
 
+import javax.xml.namespace.NamespaceContext;
 import javax.xml.namespace.QName;
 import javax.xml.stream.EventFilter;
 import javax.xml.stream.FactoryConfigurationError;
@@ -41,15 +43,24 @@
 import javax.xml.stream.XMLInputFactory;
 import javax.xml.stream.XMLOutputFactory;
 import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
 import javax.xml.stream.events.XMLEvent;
+import javax.xml.transform.OutputKeys;
 import javax.xml.transform.Source;
 import javax.xml.transform.Transformer;
 import javax.xml.transform.TransformerException;
 import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
 import javax.xml.transform.stream.StreamResult;
 import javax.xml.transform.stream.StreamSource;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathExpressionException;
+import javax.xml.xpath.XPathFactory;
 
-import net.sf.saxon.trans.XPathException;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.InputSource;
 
 import com.metamatrix.api.exception.MetaMatrixComponentException;
 import com.metamatrix.api.exception.MetaMatrixProcessingException;
@@ -62,7 +73,6 @@
 import com.metamatrix.common.types.XMLTranslator;
 import com.metamatrix.common.types.XMLType;
 import com.metamatrix.common.types.XMLType.Type;
-import com.metamatrix.internal.core.xml.XPathHelper;
 import com.metamatrix.query.QueryPlugin;
 import com.metamatrix.query.function.FunctionMethods;
 import com.metamatrix.query.processor.xml.XMLUtil;
@@ -99,31 +109,7 @@
         }
         YEAR_ZERO = cal.getTimeInMillis();
     }
-
-    public static Object xpathValue(Object document, Object xpathStr) throws FunctionExecutionException {
-        Reader stream = null;
-        
-        if (document instanceof SQLXML) {
-            try {
-                stream = ((SQLXML)document).getCharacterStream();
-            } catch (SQLException e) {
-                throw new FunctionExecutionException(QueryPlugin.Util.getString("XMLSystemFunctions.xpathvalue_takes_only_string", document.getClass().getName())); //$NON-NLS-1$
-            }
-        } else if(document instanceof String) {
-            stream = new StringReader((String)document);
-        } else {
-            throw new FunctionExecutionException(QueryPlugin.Util.getString("XMLSystemFunctions.xpathvalue_takes_only_string", document.getClass().getName())); //$NON-NLS-1$
-        }
-        
-        try {
-            return XPathHelper.getSingleMatchAsString(stream, (String) xpathStr);
-        } catch(IOException e) {
-            throw new FunctionExecutionException(QueryPlugin.Util.getString("XMLSystemFunctions.wrap_exception", xpathStr, e.getMessage())); //$NON-NLS-1$
-        } catch(XPathException e) {
-            throw new FunctionExecutionException(QueryPlugin.Util.getString("XMLSystemFunctions.wrap_exception", xpathStr, e.getMessage())); //$NON-NLS-1$
-        }
-    }
-
+    
 	public static ClobType xslTransform(CommandContext context, String xmlResults, String styleSheet) throws Exception {
 		return xslTransform(context, DataTypeManager.transformValue(xmlResults, DataTypeManager.DefaultDataClasses.XML), DataTypeManager.transformValue(styleSheet, DataTypeManager.DefaultDataClasses.XML));
 	}
@@ -313,52 +299,62 @@
 		if (object == null) {
 			return;
 		}
-		if (object instanceof XMLType) {
-			XMLType xml = (XMLType)object;
-			Reader r = null;
-			try {
+		Reader r = null;
+		try {
+			if (object instanceof XMLType) {
+				XMLType xml = (XMLType)object;
 				r = xml.getCharacterStream();
-				if (!(r instanceof BufferedReader)) {
-					r = new BufferedReader(r);
-				}
-				switch(xml.getType()) {
-				case FRAGMENT:
-				case SIBLINGS: 
-				case PI:
-				case COMMENT: //write the value directly to the writer
-					eventWriter.flush();
-					int chr = -1;
-					while ((chr = r.read()) != -1) {
-						writer.write(chr);
-					}
-					break;
-				case UNKNOWN:  //assume a document
-				case DOCUMENT: //filter the doc declaration
-					XMLInputFactory inputFactory = XMLInputFactory.newInstance();
-					XMLEventReader eventReader = inputFactory.createXMLEventReader(r);
-		        	eventReader = inputFactory.createFilteredReader(eventReader, new EventFilter() {
-						@Override
-						public boolean accept(XMLEvent event) {
-							return !event.isStartDocument() && !event.isEndDocument();
-						}
-					});
-		        	eventWriter.add(eventReader);
-		        	break;
-				}
-			} catch (SQLException e) {
-				throw new IOException(e);
-			} finally {
-				if (r != null) {
-					r.close();
-				}
+				Type type = xml.getType();
+				convertReader(writer, eventWriter, r, type);
+			} else if (object instanceof Clob) {
+				Clob clob = (Clob)object;
+				r = clob.getCharacterStream();
+				convertReader(writer, eventWriter, r, Type.TEXT);
+			} else {
+				String val = getStringValue(object);
+				eventWriter.add(eventFactory.createCharacters(val));
 			}
-		} else {
-			String val = getStringValue(object);
-			eventWriter.add(eventFactory.createCharacters(val));
+		} catch (SQLException e) {
+			throw new IOException(e);
+		} finally {
+			if (r != null) {
+				r.close();
+			}
 		}
 		//TODO: blob - with base64 encoding
-		//TODO: full clob?
 	}
+
+	private static void convertReader(Writer writer,
+			XMLEventWriter eventWriter, Reader r, Type type)
+			throws XMLStreamException, IOException, FactoryConfigurationError {
+		if (!(r instanceof BufferedReader)) {
+			r = new BufferedReader(r);
+		}
+		switch(type) {
+		case FRAGMENT:
+		case SIBLINGS: 
+		case PI:
+		case COMMENT: //write the value directly to the writer
+			eventWriter.flush();
+			int chr = -1;
+			while ((chr = r.read()) != -1) {
+				writer.write(chr);
+			}
+			break;
+		case UNKNOWN:  //assume a document
+		case DOCUMENT: //filter the doc declaration
+			XMLInputFactory inputFactory = XMLInputFactory.newInstance();
+			XMLEventReader eventReader = inputFactory.createXMLEventReader(r);
+			eventReader = inputFactory.createFilteredReader(eventReader, new EventFilter() {
+				@Override
+				public boolean accept(XMLEvent event) {
+					return !event.isStartDocument() && !event.isEndDocument();
+				}
+			});
+			eventWriter.add(eventReader);
+			break;
+		}
+	}
 	
 	public static XMLType xmlComment(String comment) {
 		return new XMLType(new SQLXMLImpl("<!--" + comment + "-->")); //$NON-NLS-1$ //$NON-NLS-2$
@@ -401,5 +397,131 @@
 	    return resultBuffer.toString();
 	    
 	}
+
+    public static String xpathValue(XMLType document, String xpathStr, String namespaces) throws IOException, XPathExpressionException, SQLException, FunctionExecutionException {
+    	Reader stream = document.getCharacterStream();
+        return xpathValue(stream, xpathStr, namespaces);
+    }
 	
+    public static String xpathValue(String document, String xpathStr, String namespaces) throws IOException, XPathExpressionException, FunctionExecutionException {
+    	return xpathValue(new StringReader(document), xpathStr, namespaces);	
+    }
+    
+    public static String xpathValue(String document, String xpathStr) throws IOException, XPathExpressionException, FunctionExecutionException {
+    	return xpathValue(document, xpathStr, null);
+    }
+    
+    public static String xpathValue(XMLType document, String xpathStr) throws IOException, SQLException, XPathExpressionException, FunctionExecutionException {
+    	return xpathValue(document, xpathStr, null);
+    }
+
+    public static XMLType xpathQuery(CommandContext context, String document, String xpathStr) throws IOException, MetaMatrixComponentException, MetaMatrixProcessingException, XPathExpressionException {
+    	return xpathQuery(context, document, xpathStr, null);
+    }
+    
+    public static XMLType xpathQuery(CommandContext context, XMLType document, String xpathStr) throws IOException, SQLException, XPathExpressionException, MetaMatrixComponentException, MetaMatrixProcessingException {
+    	return xpathQuery(context, document, xpathStr, null);
+    }
+    
+    public static XMLType xpathQuery(CommandContext context, String document, String xpathStr, String namespaces) throws IOException, MetaMatrixComponentException, MetaMatrixProcessingException, XPathExpressionException {
+    	Reader stream = new StringReader(document);
+    	return xpathQuery(context, xpathStr, stream, namespaces);
+    }
+    
+    public static XMLType xpathQuery(CommandContext context, XMLType document, String xpathStr, String namespaces) throws IOException, SQLException, XPathExpressionException, MetaMatrixComponentException, MetaMatrixProcessingException {
+    	Reader stream = ((SQLXML)document).getCharacterStream();
+    	return xpathQuery(context, xpathStr, stream, namespaces);
+    }
+
+	private static XMLType xpathQuery(CommandContext context, String xpathStr,
+			Reader stream, String namespaces) throws XPathExpressionException,
+			MetaMatrixComponentException, MetaMatrixProcessingException,
+			IOException {
+		try {
+            XPathFactory xpathFactory = XPathFactory.newInstance();
+        	XPath xp = xpathFactory.newXPath();
+        	NamespaceContext nc = getNamespaces(namespaces);
+        	if (nc != null) {
+        		xp.setNamespaceContext(nc);
+        	}
+        	final NodeList nodes = (NodeList)xp.evaluate(xpathStr, new InputSource(stream), XPathConstants.NODESET);
+        	if (nodes.getLength() == 0) {
+        		return null;
+        	}
+        	Type type = nodes.getLength() > 1 ? Type.SIBLINGS : Type.FRAGMENT;
+        	for (int i = 0; i < nodes.getLength(); i++) {
+        		Node node = nodes.item(i);
+        		if (node.getNodeType() == Node.TEXT_NODE) {
+        			type = Type.TEXT;
+        		}
+        	}
+        	SQLXML sqlXml = XMLUtil.saveToBufferManager(context.getBufferManager(), new XMLTranslator() {
+				
+				@Override
+				public void translate(Writer writer) throws TransformerException {
+	                TransformerFactory factory = TransformerFactory.newInstance();
+	                Transformer transformer = factory.newTransformer();
+	                transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); //$NON-NLS-1$
+	                for (int i = 0; i < nodes.getLength(); i++) {
+	            		Node node = nodes.item(i);
+						transformer.transform(new DOMSource(node), new StreamResult(writer));
+	            	}
+				}
+			}, Streamable.STREAMING_BATCH_SIZE_IN_BYTES);
+        	XMLType result = new XMLType(sqlXml);
+        	result.setType(type);
+        	return result;
+        } finally {
+    		stream.close();
+        }
+	}  
+	
+    public static String xpathValue(Reader documentReader, String xpath, String namespaces) throws IOException, XPathExpressionException, FunctionExecutionException {        
+        try {
+            XPathFactory xpathFactory = XPathFactory.newInstance();
+        	XPath xp = xpathFactory.newXPath();
+        	NamespaceContext nc = getNamespaces(namespaces);
+        	if (nc != null) {
+        		xp.setNamespaceContext(nc);
+        	}
+        	Node node = (Node)xp.evaluate(xpath, new InputSource(documentReader), XPathConstants.NODE);
+        	if (node == null) {
+        		return null;
+        	}
+        	return node.getTextContent();
+        } finally {
+            // Always close the reader
+            documentReader.close();
+        }
+    }
+    
+    public static NamespaceContext getNamespaces(String namespaces) throws FunctionExecutionException {
+    	if (namespaces == null) {
+    		return null;
+    	}
+		XMLInputFactory inputFactory = XMLInputFactory.newInstance();
+		try {
+			XMLStreamReader eventReader = inputFactory.createXMLStreamReader(new StringReader("<x " + namespaces + " />")); //$NON-NLS-1$ //$NON-NLS-2$
+			eventReader.next();
+        	return eventReader.getNamespaceContext();
+		} catch (XMLStreamException e) {
+			throw new FunctionExecutionException(e, QueryPlugin.Util.getString("XMLSystemFunctions.invalid_namespaces", namespaces)); //$NON-NLS-1$
+		}
+    }
+
+    /**
+     * Validate whether the XPath is a valid XPath.  If not valid, an XPathExpressionException will be thrown.
+     * @param xpath An xpath expression, for example: a/b/c/getText()
+     * @throws XPathExpressionException 
+     */
+    public static void validateXpath(String xpath) throws XPathExpressionException {
+        if(xpath == null) { 
+            return;
+        }
+        
+        XPathFactory factory = XPathFactory.newInstance();
+        XPath xp = factory.newXPath();
+        xp.compile(xpath);
+    }
+	
 }

Modified: trunk/engine/src/main/java/com/metamatrix/query/resolver/util/ResolverVisitor.java
===================================================================
--- trunk/engine/src/main/java/com/metamatrix/query/resolver/util/ResolverVisitor.java	2010-05-07 20:25:05 UTC (rev 2106)
+++ trunk/engine/src/main/java/com/metamatrix/query/resolver/util/ResolverVisitor.java	2010-05-07 21:35:44 UTC (rev 2107)
@@ -31,17 +31,12 @@
 import java.util.List;
 import java.util.Map;
 
-import org.teiid.connector.api.SourceSystemFunctions;
-
-import net.sf.saxon.trans.XPathException;
-
 import com.metamatrix.api.exception.MetaMatrixComponentException;
 import com.metamatrix.api.exception.query.QueryMetadataException;
 import com.metamatrix.api.exception.query.QueryResolverException;
 import com.metamatrix.api.exception.query.UnresolvedSymbolDescription;
 import com.metamatrix.common.types.DataTypeManager;
 import com.metamatrix.common.types.DataTypeManager.DefaultDataClasses;
-import com.metamatrix.internal.core.xml.XPathHelper;
 import com.metamatrix.query.QueryPlugin;
 import com.metamatrix.query.function.FunctionDescriptor;
 import com.metamatrix.query.function.FunctionForm;
@@ -442,25 +437,8 @@
 	    } else if(fd.getName().equalsIgnoreCase(FunctionLibrary.LOOKUP)) {
 			ResolverUtil.ResolvedLookup lookup = ResolverUtil.resolveLookup(function, metadata);
 			fd = library.copyFunctionChangeReturnType(fd, lookup.getReturnElement().getType());
-	    } else if(fd.getName().equalsIgnoreCase(SourceSystemFunctions.XPATHVALUE)) {
-	        // Validate the xpath value is valid
-	        if(args[1] != null && args[1] instanceof Constant) {
-	            Constant xpathConst = (Constant) args[1];
-	            if(xpathConst.getType().equals(DataTypeManager.DefaultDataClasses.STRING)) {
-	                String value = (String) xpathConst.getValue();
-	                if(value == null) {
-	                    throw new QueryResolverException(QueryPlugin.Util.getString("QueryResolver.invalid_xpath", QueryPlugin.Util.getString("ResolveFunctionsVisitor.xpath_cant_be_null"))); //$NON-NLS-1$ //$NON-NLS-2$                        
-	                } 
+	    } 
 	
-	                try {
-	                    XPathHelper.validateXpath(value);
-	                } catch(XPathException e) {
-	                    throw new QueryResolverException(QueryPlugin.Util.getString("QueryResolver.invalid_xpath", e.getMessage())); //$NON-NLS-1$
-	                }
-	            }                
-	        }
-	    }
-	
 	    // Resolve the function
 	    function.setFunctionDescriptor(fd);
 	    function.setType(fd.getReturnType());

Modified: trunk/engine/src/main/java/com/metamatrix/query/sql/visitor/SQLStringVisitor.java
===================================================================
--- trunk/engine/src/main/java/com/metamatrix/query/sql/visitor/SQLStringVisitor.java	2010-05-07 20:25:05 UTC (rev 2106)
+++ trunk/engine/src/main/java/com/metamatrix/query/sql/visitor/SQLStringVisitor.java	2010-05-07 21:35:44 UTC (rev 2107)
@@ -1243,7 +1243,7 @@
             }
             parts.add(")"); //$NON-NLS-1$
 
-		} else if (name.equalsIgnoreCase(SourceSystemFunctions.XMLELEMENT)){
+		} else if (name.equalsIgnoreCase(SourceSystemFunctions.XMLELEMENT) || name.equalsIgnoreCase(SourceSystemFunctions.XMLPI)){
 			parts.add(name);
 			parts.add("(NAME "); //$NON-NLS-1$
 			outputDisplayName((String)((Constant)args[0]).getValue());

Modified: trunk/engine/src/main/java/com/metamatrix/query/validator/ValidationVisitor.java
===================================================================
--- trunk/engine/src/main/java/com/metamatrix/query/validator/ValidationVisitor.java	2010-05-07 20:25:05 UTC (rev 2106)
+++ trunk/engine/src/main/java/com/metamatrix/query/validator/ValidationVisitor.java	2010-05-07 21:35:44 UTC (rev 2107)
@@ -31,15 +31,21 @@
 import java.util.Map;
 import java.util.Set;
 
+import javax.xml.xpath.XPathExpressionException;
+
+import org.teiid.connector.api.SourceSystemFunctions;
+
 import com.metamatrix.api.exception.MetaMatrixComponentException;
 import com.metamatrix.api.exception.MetaMatrixProcessingException;
 import com.metamatrix.api.exception.query.ExpressionEvaluationException;
+import com.metamatrix.api.exception.query.FunctionExecutionException;
 import com.metamatrix.api.exception.query.QueryMetadataException;
 import com.metamatrix.api.exception.query.QueryValidatorException;
 import com.metamatrix.common.types.DataTypeManager;
 import com.metamatrix.query.QueryPlugin;
 import com.metamatrix.query.eval.Evaluator;
 import com.metamatrix.query.function.FunctionLibrary;
+import com.metamatrix.query.function.source.XMLSystemFunctions;
 import com.metamatrix.query.metadata.SupportConstants;
 import com.metamatrix.query.resolver.util.ResolverUtil;
 import com.metamatrix.query.sql.LanguageObject;
@@ -319,7 +325,25 @@
                 // can't use this pseudo-function in non-XML queries
                 handleValidationError(QueryPlugin.Util.getString("ValidationVisitor.The_rowlimit_function_cannot_be_used_in_a_non-XML_command"), obj); //$NON-NLS-1$
             }
-        }
+        } else if(obj.getFunctionDescriptor().getName().equalsIgnoreCase(SourceSystemFunctions.XPATHVALUE) || obj.getFunctionDescriptor().getName().equalsIgnoreCase(SourceSystemFunctions.XPATHQUERY)) {
+	        // Validate the xpath value is valid
+	        if(obj.getArgs()[1] instanceof Constant) {
+	            Constant xpathConst = (Constant) obj.getArgs()[1];
+                try {
+                    XMLSystemFunctions.validateXpath((String)xpathConst.getValue());
+                } catch(XPathExpressionException e) {
+                	handleValidationError(QueryPlugin.Util.getString("QueryResolver.invalid_xpath", e.getMessage()), obj); //$NON-NLS-1$
+                }
+	        }
+	        if (obj.getArgs().length > 2 && obj.getArgs()[2] instanceof Constant) {
+	            Constant xpathConst = (Constant) obj.getArgs()[2];
+                try {
+                    XMLSystemFunctions.getNamespaces((String)xpathConst.getValue());
+                } catch(FunctionExecutionException e) {
+                	handleValidationError(e.getMessage(), obj);
+                }
+	        }
+	    }
     }
 
     // ############### Visitor methods for stored procedure lang objects ##################

Modified: trunk/engine/src/main/resources/com/metamatrix/query/i18n.properties
===================================================================
--- trunk/engine/src/main/resources/com/metamatrix/query/i18n.properties	2010-05-07 20:25:05 UTC (rev 2106)
+++ trunk/engine/src/main/resources/com/metamatrix/query/i18n.properties	2010-05-07 21:35:44 UTC (rev 2107)
@@ -764,9 +764,12 @@
 SystemSource.Bitfunc2_arg1=First integer
 SystemSource.Bitfunc2_arg2=Second integer
 SystemSource.Convert_desc=Convert from {0} to target type
-SystemSource.xpath_description=Retrieve the first match content for an XPath statement
+SystemSource.xpathvalue_description=Retrieve the first match content for an XPath statement
+SystemSource.xpath_description=Evaluate the XPath expression against a document
 SystemSource.xpath_param1=Source document
 SystemSource.xpath_param2=XPath expression
+SystemSource.xpath_param2=Namespaces
+SystemSource.xpathvalue_result=Single result
 SystemSource.xpath_result=XPath result
 SystemSource.xsltransform_description=Transform the document with the given stylesheet. 
 SystemSource.xsltransform_param1=Source document
@@ -778,10 +781,10 @@
 SystemSource.xmlelement_result=XML result
 SystemSource.xmlconcat_description=Concat XML types. 
 SystemSource.xmlconcat_param1=First element
-SystemSource.xmlcomment_description=Creates an XML comment. 
+SystemSource.xmlcomment_description=Create an XML comment. 
 SystemSource.xmlconcat_param1=String comment
 SystemSource.xmlconcat_result=XML result
-SystemSource.xmlpi_description=Creates an XML processing instruction. 
+SystemSource.xmlpi_description=Create an XML processing instruction. 
 SystemSource.xmlpi_param1=Target
 SystemSource.xmlpi_param2=Content
 SystemSource.xmlpi_result=XML result
@@ -900,4 +903,5 @@
 SetClause.resolvingError=Cannot set symbol ''{1}'' with expected type {2} to expression ''{0}''
 NewCalculateCostUtil.badCost=Unexpected format encountered for max or min value
 
-WorkerPool.Max_thread=Reached maximum thread count "{0}" for worker pool "{1}" with a queue size of "{2}".
\ No newline at end of file
+WorkerPool.Max_thread=Reached maximum thread count "{0}" for worker pool "{1}" with a queue size of "{2}".
+XMLSystemFunctions.invalid_namespaces=Invalid namespaces supplied for XPath expression - ''{0}''
\ No newline at end of file

Deleted: trunk/engine/src/test/java/com/metamatrix/internal/core/xml/TestXPathHelper.java
===================================================================
--- trunk/engine/src/test/java/com/metamatrix/internal/core/xml/TestXPathHelper.java	2010-05-07 20:25:05 UTC (rev 2106)
+++ trunk/engine/src/test/java/com/metamatrix/internal/core/xml/TestXPathHelper.java	2010-05-07 21:35:44 UTC (rev 2107)
@@ -1,185 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * See the COPYRIGHT.txt file distributed with this work for information
- * regarding copyright ownership.  Some portions may be licensed
- * to Red Hat, Inc. under one or more contributor license agreements.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301 USA.
- */
-
-package com.metamatrix.internal.core.xml;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.Reader;
-import java.io.StringReader;
-
-import junit.framework.TestCase;
-
-import net.sf.saxon.trans.XPathException;
-
-import org.jdom.Attribute;
-import org.jdom.Element;
-
-import com.metamatrix.core.util.FileUtil;
-import com.metamatrix.core.util.UnitTestUtil;
-
-
-/** 
- * @since 4.2
- */
-public class TestXPathHelper extends TestCase {
-
-    /**
-     * Constructor for TestXPathHelper.
-     * @param name
-     */
-    public TestXPathHelper(String name) {
-        super(name);
-    }
-    
-    // =========================================================================
-    //                      H E L P E R   M E T H O D S
-    // =========================================================================
-
-    public String getContentOfTestFile( final String testFilePath ) {
-        final File file = UnitTestUtil.getTestDataFile(testFilePath);
-        assertNotNull(file);
-        assertEquals(true,file.exists());
-        final FileUtil util = new FileUtil(file.getAbsolutePath());
-        assertNotNull(util);
-        return util.read();
-    }
-    
-    public String helpTestXpathValue(final String xmlFilePath, final String xpath, 
-                                     final String expected) throws XPathException, IOException {
-        final String actual = helpGetNode(xmlFilePath,xpath);
-        assertEquals(expected,actual);
-        return actual;
-    }
-
-    public String helpGetNode(final String xmlFilePath, final String xpath ) throws XPathException, IOException {
-        final String xmlContent = getContentOfTestFile(xmlFilePath);
-        final Reader docReader = new StringReader(xmlContent);
-        return XPathHelper.getSingleMatchAsString(docReader,xpath);
-    }
-
-    public void helpCheckElement(final Object jdomNode, final String name, final String prefix, final String namespaceUri,
-                                 final String textContent) {
-        assertTrue("Supplied JDOM node is not an Element", jdomNode instanceof Element); //$NON-NLS-1$
-        final Element element = (Element)jdomNode;
-        assertEquals(name, element.getName());
-        assertEquals(prefix, element.getNamespacePrefix());
-        assertEquals(namespaceUri, element.getNamespaceURI());
-
-        final String actualTextContent = element.getText();
-        if (textContent == null) {
-            assertEquals(0, actualTextContent.length());
-        } else {
-            assertEquals(textContent, actualTextContent);
-        }
-    }
-
-    public void helpCheckElement(final Object jdomNode, final String name, final String prefix, final String namespaceUri) {
-        assertTrue("Supplied JDOM node is not an Element", jdomNode instanceof Element); //$NON-NLS-1$
-        final Element element = (Element)jdomNode;
-        assertEquals(name, element.getName());
-        assertEquals(prefix, element.getNamespacePrefix());
-        assertEquals(namespaceUri, element.getNamespaceURI());
-    }
-
-    public void helpCheckAttribute(final Object jdomNode, final String name,
-                                 final String prefix, final String namespaceUri,
-                                 final String value ) {
-       assertTrue("Supplied JDOM node is not an Attribute",jdomNode instanceof Attribute); //$NON-NLS-1$
-       final Attribute attribute = (Attribute)jdomNode;
-       assertEquals(name,attribute.getName());
-       assertEquals(prefix,attribute.getNamespacePrefix());
-       assertEquals(namespaceUri,attribute.getNamespaceURI());
-       
-       final String actualTextContent = attribute.getValue();
-       assertEquals(value,actualTextContent);
-   }
-
-    // =========================================================================
-    //                         T E S T     C A S E S
-    // =========================================================================
-
-    public void testValidateXpath_Defect15088() {
-        // Mismatched tick and quote
-        final String xpath = "//*[local-name()='bookName\"]"; //$NON-NLS-1$       
-        try {
-            XPathHelper.validateXpath(xpath);
-            fail("Expected validation error but got none"); //$NON-NLS-1$
-        } catch(XPathException e) {            
-        }
-    }
-
-    public void testValidateXpath_null() throws Exception {
-        XPathHelper.validateXpath(null);
-    }
-
-    public void testValidateXpath_valid() throws Exception {
-        XPathHelper.validateXpath("//shipTo/@country"); //$NON-NLS-1$
-    }
-
-    public void testGetSingleMatch_01_001() throws Exception {
-        final String xmlFilePath = "testdoc.xml"; //$NON-NLS-1$
-        final String xpath = "//shipTo/@country"; //$NON-NLS-1$
-        final String expectedValue = "US"; //$NON-NLS-1$
-        helpTestXpathValue(xmlFilePath,xpath,expectedValue);
-    }
-
-    public void testGetSingleMatch_01_002() throws Exception {
-        final String xmlFilePath = "testdoc.xml"; //$NON-NLS-1$
-        final String xpath = "//@partNum"; //$NON-NLS-1$
-        final String expectedValue = "872-AA"; //$NON-NLS-1$
-        helpTestXpathValue(xmlFilePath,xpath,expectedValue);
-    }
-
-    public void testGetSingleMatch_01_003() throws Exception {
-        final String xmlFilePath = "testdoc.xml"; //$NON-NLS-1$
-        final String xpath = "//productName"; //$NON-NLS-1$
-        final String expectedValue = "Lawnmower"; //$NON-NLS-1$
-        helpTestXpathValue(xmlFilePath,xpath,expectedValue);
-    }
-
-    public void testGetSingleMatch_01_004() throws Exception {
-        final String xmlFilePath = "testdoc.xml"; //$NON-NLS-1$
-        final String xpath = "/*:Envelope/billTo/zip"; //$NON-NLS-1$
-        final String expectedValue = "95819"; //$NON-NLS-1$
-        helpTestXpathValue(xmlFilePath,xpath,expectedValue);
-    }
-
-    public void testGetSingleMatch_02_001() throws Exception {
-        final String xmlFilePath = "testdoc.xml"; //$NON-NLS-1$
-        final String xpath = "/*:Envelope/*:HEADER/*:RequestID"; //$NON-NLS-1$
-        helpTestXpathValue(xmlFilePath,xpath,null);
-    }
-
-    public void testGetSingleMatch_03() throws Exception {
-        final String xmlFilePath = "testdoc.xml"; //$NON-NLS-1$
-        final String xpath = "//*[local-name()=\"ReadOnly\"]"; //$NON-NLS-1$
-        helpTestXpathValue(xmlFilePath,xpath,"false"); //$NON-NLS-1$
-    }
-    
-    public void testGetSingleMatch_04() throws Exception {
-        final String xmlFilePath = "testdoc.xml"; //$NON-NLS-1$
-        final String xpath = "//*:ReadOnly"; //$NON-NLS-1$
-        helpTestXpathValue(xmlFilePath,xpath,"false"); //$NON-NLS-1$
-    }
-
-}

Modified: trunk/engine/src/test/java/com/metamatrix/query/function/TestFunctionLibrary.java
===================================================================
--- trunk/engine/src/test/java/com/metamatrix/query/function/TestFunctionLibrary.java	2010-05-07 20:25:05 UTC (rev 2106)
+++ trunk/engine/src/test/java/com/metamatrix/query/function/TestFunctionLibrary.java	2010-05-07 21:35:44 UTC (rev 2107)
@@ -1390,4 +1390,15 @@
         String xml = ObjectConverterUtil.convertToString(result.getCharacterStream());
         assertEquals("<!--comment-->", xml);
     }
+	
+	@Test public void testInvokeXpathQuery() throws Exception {
+        CommandContext c = new CommandContext();
+        c.setBufferManager(BufferManagerFactory.getStandaloneBufferManager());
+        XMLType result = (XMLType)helpInvokeMethod("xpathquery", new Class[] {DataTypeManager.DefaultDataClasses.STRING, DataTypeManager.DefaultDataClasses.STRING}, 
+        		new Object[] {"<foo><bar>1</bar><bar>2</bar></foo>", "/foo/bar"}, c);
+        
+        String xml = ObjectConverterUtil.convertToString(result.getCharacterStream());
+        assertEquals("<bar>1</bar><bar>2</bar>", xml);
+    }
+	
 }

Modified: trunk/engine/src/test/java/com/metamatrix/query/function/source/TestXMLSystemFunctions.java
===================================================================
--- trunk/engine/src/test/java/com/metamatrix/query/function/source/TestXMLSystemFunctions.java	2010-05-07 20:25:05 UTC (rev 2106)
+++ trunk/engine/src/test/java/com/metamatrix/query/function/source/TestXMLSystemFunctions.java	2010-05-07 21:35:44 UTC (rev 2107)
@@ -22,86 +22,188 @@
 
 package com.metamatrix.query.function.source;
 
-import junit.framework.TestCase;
+import static org.junit.Assert.*;
 
+import java.io.File;
+import java.io.IOException;
+import java.io.Reader;
+import java.io.StringReader;
+
+import javax.xml.xpath.XPathExpressionException;
+
+import org.jdom.Attribute;
+import org.jdom.Element;
+import org.junit.Test;
+
 import com.metamatrix.api.exception.query.FunctionExecutionException;
 import com.metamatrix.common.types.SQLXMLImpl;
 import com.metamatrix.common.types.XMLType;
+import com.metamatrix.core.util.FileUtil;
+import com.metamatrix.core.util.UnitTestUtil;
 
+ at SuppressWarnings("nls")
+public class TestXMLSystemFunctions {
+	
+    public String getContentOfTestFile( final String testFilePath ) {
+        final File file = UnitTestUtil.getTestDataFile(testFilePath);
+        final FileUtil util = new FileUtil(file.getAbsolutePath());
+        return util.read();
+    }
+    
+    public String helpTestXpathValue(final String xmlFilePath, final String xpath, 
+                                     String namespaces, final String expected) throws IOException, XPathExpressionException, FunctionExecutionException {
+        final String actual = helpGetNode(xmlFilePath,xpath, namespaces);
+        assertEquals(expected,actual);
+        return actual;
+    }
 
-/** 
- * @since 4.2
- */
-public class TestXMLSystemFunctions extends TestCase {
+    public String helpGetNode(final String xmlFilePath, final String xpath, String namespaces ) throws IOException, XPathExpressionException, FunctionExecutionException {
+        final String xmlContent = getContentOfTestFile(xmlFilePath);
+        final Reader docReader = new StringReader(xmlContent);
+        return XMLSystemFunctions.xpathValue(docReader,xpath, namespaces);
+    }
 
-    public void testElement() throws Exception {
+    public void helpCheckElement(final Object jdomNode, final String name, final String prefix, final String namespaceUri,
+                                 final String textContent) {
+        assertTrue("Supplied JDOM node is not an Element", jdomNode instanceof Element); //$NON-NLS-1$
+        final Element element = (Element)jdomNode;
+        assertEquals(name, element.getName());
+        assertEquals(prefix, element.getNamespacePrefix());
+        assertEquals(namespaceUri, element.getNamespaceURI());
+
+        final String actualTextContent = element.getText();
+        if (textContent == null) {
+            assertEquals(0, actualTextContent.length());
+        } else {
+            assertEquals(textContent, actualTextContent);
+        }
+    }
+
+    public void helpCheckElement(final Object jdomNode, final String name, final String prefix, final String namespaceUri) {
+        assertTrue("Supplied JDOM node is not an Element", jdomNode instanceof Element); //$NON-NLS-1$
+        final Element element = (Element)jdomNode;
+        assertEquals(name, element.getName());
+        assertEquals(prefix, element.getNamespacePrefix());
+        assertEquals(namespaceUri, element.getNamespaceURI());
+    }
+
+    public void helpCheckAttribute(final Object jdomNode, final String name,
+                                 final String prefix, final String namespaceUri,
+                                 final String value ) {
+       assertTrue("Supplied JDOM node is not an Attribute",jdomNode instanceof Attribute); //$NON-NLS-1$
+       final Attribute attribute = (Attribute)jdomNode;
+       assertEquals(name,attribute.getName());
+       assertEquals(prefix,attribute.getNamespacePrefix());
+       assertEquals(namespaceUri,attribute.getNamespaceURI());
+       
+       final String actualTextContent = attribute.getValue();
+       assertEquals(value,actualTextContent);
+   }
+
+    @Test public void testElement() throws Exception {
         String doc = "<?xml version=\"1.0\" encoding=\"utf-8\" ?><a><b><c>test</c></b></a>"; //$NON-NLS-1$
         String xpath = "a/b/c"; //$NON-NLS-1$
-        String value = (String) XMLSystemFunctions.xpathValue(doc, xpath);
+        String value = XMLSystemFunctions.xpathValue(doc, xpath);
         assertEquals("test", value); //$NON-NLS-1$
     }
 
-    public void testAttribute() throws Exception {
+    @Test public void testAttribute() throws Exception {
         String doc = "<?xml version=\"1.0\" encoding=\"utf-8\" ?><a><b c=\"test\"></b></a>"; //$NON-NLS-1$
         String xpath = "a/b/@c"; //$NON-NLS-1$
-        String value = (String) XMLSystemFunctions.xpathValue(doc, xpath);
+        String value = XMLSystemFunctions.xpathValue(doc, xpath);
         assertEquals("test", value); //$NON-NLS-1$
     }
 
-    public void testText() throws Exception {
+    @Test public void testText() throws Exception {
         String doc = "<?xml version=\"1.0\" encoding=\"utf-8\" ?><a><b><c>test</c></b></a>"; //$NON-NLS-1$
         String xpath = "a/b/c/text()"; //$NON-NLS-1$
-        String value = (String) XMLSystemFunctions.xpathValue(doc, xpath);
+        String value = XMLSystemFunctions.xpathValue(doc, xpath);
         assertEquals("test", value); //$NON-NLS-1$
     }
 
-    public void testNoMatch() throws Exception {
+    @Test public void testNoMatch() throws Exception {
         String doc = "<?xml version=\"1.0\" encoding=\"utf-8\" ?><a><b><c>test</c></b></a>"; //$NON-NLS-1$
         String xpath = "x"; //$NON-NLS-1$
-        String value = (String) XMLSystemFunctions.xpathValue(doc, xpath);
+        String value = XMLSystemFunctions.xpathValue(doc, xpath);
         assertEquals(null, value);
     }
 
-    public void testNoXMLHeader() throws Exception {
+    @Test public void testNoXMLHeader() throws Exception {
         String doc = "<a><b><c>test</c></b></a>"; //$NON-NLS-1$
         String xpath = "a/b/c/text()"; //$NON-NLS-1$
-        String value = (String) XMLSystemFunctions.xpathValue(doc, xpath);
+        String value = XMLSystemFunctions.xpathValue(doc, xpath);
         assertEquals("test", value); //$NON-NLS-1$
     }
 
     // simulate what would happen if someone passed the output of an XML query to the xpathvalue function
-    public void testXMLInput() throws Exception {
+    @Test public void testXMLInput() throws Exception {
         XMLType doc = new XMLType(new SQLXMLImpl("<foo/>"));//$NON-NLS-1$
         String xpath = "a/b/c"; //$NON-NLS-1$
-        try {
-            XMLSystemFunctions.xpathValue(doc, xpath);
-        } catch(FunctionExecutionException e) {
-            // expected
-            //System.out.println(e.getMessage());
-        }            
+        String value = XMLSystemFunctions.xpathValue(doc, xpath);
+        assertNull(value);
     }
     
-    public void testBadTypeInput() throws Exception {
-        Integer doc = new Integer(1);
-        String xpath = "a/b/c"; //$NON-NLS-1$
-        try {
-            XMLSystemFunctions.xpathValue(doc, xpath);
-            fail("Expected exception passing xml stream to xpathvalue()"); //$NON-NLS-1$
-        } catch(FunctionExecutionException e) {
-            // expected
-            //System.out.println(e.getMessage());
-        }            
-    }    
-    
-    public void testBadXPath() throws Exception {
+    @Test(expected=XPathExpressionException.class) public void testBadXPath() throws Exception {
         String doc = "<?xml version=\"1.0\" encoding=\"utf-8\" ?><a><b><c>test</c></b></a>"; //$NON-NLS-1$
         String xpath = ":BOGUS:"; //$NON-NLS-1$
-        try {
-            XMLSystemFunctions.xpathValue(doc, xpath);
-            fail("Expected exception passing bad xpath"); //$NON-NLS-1$
-        } catch(FunctionExecutionException e) {
-            // expected
-        }                    
+        XMLSystemFunctions.xpathValue(doc, xpath);
     }
+    
+    @Test(expected=XPathExpressionException.class) public void testValidateXpath_Defect15088() throws Exception {
+        // Mismatched tick and quote
+        final String xpath = "//*[local-name()='bookName\"]"; //$NON-NLS-1$       
+    	XMLSystemFunctions.validateXpath(xpath);
+    }
 
+    @Test public void testValidateXpath_null() throws Exception {
+        XMLSystemFunctions.validateXpath(null);
+    }
+
+    @Test public void testValidateXpath_valid() throws Exception {
+    	XMLSystemFunctions.validateXpath("//shipTo/@country"); //$NON-NLS-1$
+    }
+
+    @Test public void testGetSingleMatch_01_001() throws Exception {
+        final String xmlFilePath = "testdoc.xml"; //$NON-NLS-1$
+        final String xpath = "//shipTo/@country"; //$NON-NLS-1$
+        final String expectedValue = "US"; //$NON-NLS-1$
+        helpTestXpathValue(xmlFilePath,xpath,null, expectedValue);
+    }
+
+    @Test public void testGetSingleMatch_01_002() throws Exception {
+        final String xmlFilePath = "testdoc.xml"; //$NON-NLS-1$
+        final String xpath = "//@partNum"; //$NON-NLS-1$
+        final String expectedValue = "872-AA"; //$NON-NLS-1$
+        helpTestXpathValue(xmlFilePath,xpath,null, expectedValue);
+    }
+
+    @Test public void testGetSingleMatch_01_003() throws Exception {
+        final String xmlFilePath = "testdoc.xml"; //$NON-NLS-1$
+        final String xpath = "//productName"; //$NON-NLS-1$
+        final String expectedValue = "Lawnmower"; //$NON-NLS-1$
+        helpTestXpathValue(xmlFilePath,xpath,null, expectedValue);
+    }
+
+    @Test public void testGetSingleMatch_01_004() throws Exception {
+        final String xmlFilePath = "testdoc.xml"; //$NON-NLS-1$
+        final String xpath = "/SOAP-ENV:Envelope/billTo/zip"; //$NON-NLS-1$
+        final String expectedValue = "95819"; //$NON-NLS-1$
+        helpTestXpathValue(xmlFilePath,xpath,"xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\"", expectedValue);
+    }
+
+    @Test public void testGetSingleMatch_03() throws Exception {
+        final String xmlFilePath = "testdoc.xml"; //$NON-NLS-1$
+        final String xpath = "//*[local-name()=\"ReadOnly\"]"; //$NON-NLS-1$
+        helpTestXpathValue(xmlFilePath,xpath,null, "false"); //$NON-NLS-1$
+    }
+    
+    /**
+     * * is no longer valid to match the namespace
+     */
+    @Test(expected=XPathExpressionException.class) public void testGetSingleMatch_04() throws Exception {
+        final String xmlFilePath = "testdoc.xml"; //$NON-NLS-1$
+        final String xpath = "//*:ReadOnly"; //$NON-NLS-1$
+        helpTestXpathValue(xmlFilePath,xpath,null, "false"); //$NON-NLS-1$
+    }
+
 }

Modified: trunk/engine/src/test/java/com/metamatrix/query/parser/TestParser.java
===================================================================
--- trunk/engine/src/test/java/com/metamatrix/query/parser/TestParser.java	2010-05-07 20:25:05 UTC (rev 2106)
+++ trunk/engine/src/test/java/com/metamatrix/query/parser/TestParser.java	2010-05-07 21:35:44 UTC (rev 2107)
@@ -6737,5 +6737,10 @@
     	SQLXMLFunction f = new SQLXMLFunction("xmlforest", Arrays.asList((SingleElementSymbol)new AliasSymbol("table", new ElementSymbol("a"))));
     	helpTestExpression("xmlforest(a as \"table\")", "xmlforest(a AS \"table\")", f);
     }
+    
+    @Test public void testXmlPi() throws Exception {
+    	Function f = new Function("xmlpi", new Expression[] {new Constant("a"), new ElementSymbol("val")});
+    	helpTestExpression("xmlpi(NAME a, val)", "xmlpi(NAME a, val)", f);
+    }
 
 }

Modified: trunk/engine/src/test/java/com/metamatrix/query/resolver/TestResolver.java
===================================================================
--- trunk/engine/src/test/java/com/metamatrix/query/resolver/TestResolver.java	2010-05-07 20:25:05 UTC (rev 2106)
+++ trunk/engine/src/test/java/com/metamatrix/query/resolver/TestResolver.java	2010-05-07 21:35:44 UTC (rev 2107)
@@ -2171,23 +2171,6 @@
         assertTrue("Params should be not equal", ! params[0].equals(params[1])); //$NON-NLS-1$
     }
     
-    @Test public void testXpathValueValid_defect15088() {
-        String userSql = "SELECT xpathValue('<?xml version=\"1.0\" encoding=\"utf-8\" ?><a><b><c>test</c></b></a>', 'a/b/c')"; //$NON-NLS-1$
-        helpResolve(userSql, FakeMetadataFactory.exampleBQTCached(), AnalysisRecord.createNonRecordingRecord());        
-    }
-
-    @Test public void testXpathValueInvalid_defect15088() throws Exception {
-        String userSql = "SELECT xpathValue('<?xml version=\"1.0\" encoding=\"utf-8\" ?><a><b><c>test</c></b></a>', '//*[local-name()=''bookName\"]')"; //$NON-NLS-1$
-        Command command = helpParse(userSql);
-        
-        try {
-            QueryResolver.resolveCommand(command, FakeMetadataFactory.exampleBQTCached(), AnalysisRecord.createNonRecordingRecord());
-            fail("Expected resolver exception on invalid xpath value"); //$NON-NLS-1$
-        } catch(QueryResolverException e) {
-            //System.out.println(e.getMessage());
-        }
-    }
-
     @Test public void testNullConstantInSelect() throws Exception {
         String userSql = "SELECT null as x"; //$NON-NLS-1$
         Query query = (Query)helpParse(userSql);

Modified: trunk/engine/src/test/java/com/metamatrix/query/validator/TestValidator.java
===================================================================
--- trunk/engine/src/test/java/com/metamatrix/query/validator/TestValidator.java	2010-05-07 20:25:05 UTC (rev 2106)
+++ trunk/engine/src/test/java/com/metamatrix/query/validator/TestValidator.java	2010-05-07 21:35:44 UTC (rev 2107)
@@ -65,6 +65,7 @@
 import com.metamatrix.query.unittest.FakeMetadataObject;
 import com.metamatrix.query.unittest.FakeMetadataStore;
 
+ at SuppressWarnings("nls")
 public class TestValidator {
 
     public static Map getStoredProcedureExternalMetadata(GroupSymbol virtualProc, QueryMetadataInterface metadata)
@@ -1961,5 +1962,21 @@
 	@Test public void testValidateNoExpressionName() {        
         helpValidate("SELECT xmlelement(name a, xmlattributes('1'))", new String[] {"'1'"}, exampleMetadata2()); //$NON-NLS-1$ //$NON-NLS-2$
 	}
+	
+    @Test public void testXpathValueValid_defect15088() {
+        String userSql = "SELECT xpathValue('<?xml version=\"1.0\" encoding=\"utf-8\" ?><a><b><c>test</c></b></a>', 'a/b/c')"; //$NON-NLS-1$
+        helpValidate(userSql, new String[] {}, FakeMetadataFactory.exampleBQTCached());        
+    }
 
+    @Test public void testXpathValueInvalid_defect15088() throws Exception {
+        String userSql = "SELECT xpathValue('<?xml version=\"1.0\" encoding=\"utf-8\" ?><a><b><c>test</c></b></a>', '//*[local-name()=''bookName\"]')"; //$NON-NLS-1$
+        helpValidate(userSql, new String[] {"xpathValue('<?xml version=\"1.0\" encoding=\"utf-8\" ?><a><b><c>test</c></b></a>', '//*[local-name()=''bookName\"]')"}, FakeMetadataFactory.exampleBQTCached());
+    }
+    
+    @Test public void testXpathValueInvalidNamespaces() throws Exception {
+        String userSql = "SELECT xpathValue('<?xml version=\"1.0\" encoding=\"utf-8\" ?><a><b><c>test</c></b></a>', '//*[local-name()=\"bookName\"]', 'xmlns==')"; //$NON-NLS-1$
+        helpValidate(userSql, new String[] {"xpathValue('<?xml version=\"1.0\" encoding=\"utf-8\" ?><a><b><c>test</c></b></a>', '//*[local-name()=\"bookName\"]', 'xmlns==')"}, FakeMetadataFactory.exampleBQTCached());
+    }
+
+
 }



More information about the teiid-commits mailing list