Index: c/src/xalanc/XalanEXSLT/XalanEXSLTStringImpl.hpp
===================================================================
--- c/src/xalanc/XalanEXSLT/XalanEXSLTStringImpl.hpp	(.../vendor/xml-xalan/1.10)	(revision 13764)
+++ c/src/xalanc/XalanEXSLT/XalanEXSLTStringImpl.hpp	(.../trunk/3rdparty/xml-xalan)	(revision 13764)
@@ -394,6 +394,193 @@
     operator==(const XalanEXSLTFunctionDecodeURI&) const;
 };
 
+
+
+class XALAN_EXSLT_EXPORT XalanEXSLTFunctionReplace : public Function
+{
+public:
+
+    typedef Function    ParentType;
+
+    XalanEXSLTFunctionReplace() :
+        Function()
+    {
+    }
+
+    virtual
+    ~XalanEXSLTFunctionReplace()
+    {
+    }
+
+    // These methods are inherited from Function ...
+
+    virtual XObjectPtr
+    execute(
+            XPathExecutionContext&          executionContext,
+            XalanNode*                      context,
+            const XObjectArgVectorType&     args,
+            const LocatorType*              locator) const;
+
+#if !defined(XALAN_NO_USING_DECLARATION)
+    using ParentType::execute;
+#endif
+
+#if defined(XALAN_NO_COVARIANT_RETURN_TYPE)
+    virtual Function*
+#else
+    virtual XalanEXSLTFunctionReplace*
+#endif
+    clone(MemoryManagerType&    theManager) const
+    {
+        return XalanCopyConstruct(theManager, *this);
+    }
+
+protected:
+
+    const XalanDOMString&
+    getError(XalanDOMString&    theBuffer) const
+    {
+        return XalanMessageLoader::getMessage(
+                    theBuffer,
+                    XalanMessages::EXSLTFunctionAcceptsThreeArguments_1Param,
+                    "replace()");
+
+    }
+
+private:
+    // Not implemented...
+    XalanEXSLTFunctionReplace&
+    operator=(const XalanEXSLTFunctionReplace&);
+
+    bool
+    operator==(const XalanEXSLTFunctionReplace&) const;
+};
+
+
+
+class XALAN_EXSLT_EXPORT XalanEXSLTFunctionSplit : public Function
+{
+public:
+
+    typedef Function    ParentType;
+
+    XalanEXSLTFunctionSplit() :
+        Function()
+    {
+    }
+
+    virtual
+    ~XalanEXSLTFunctionSplit()
+    {
+    }
+
+    // These methods are inherited from Function ...
+
+    virtual XObjectPtr
+    execute(
+            XPathExecutionContext&          executionContext,
+            XalanNode*                      context,
+            const XObjectArgVectorType&     args,
+            const LocatorType*              locator) const;
+
+#if !defined(XALAN_NO_USING_DECLARATION)
+    using ParentType::execute;
+#endif
+
+#if defined(XALAN_NO_COVARIANT_RETURN_TYPE)
+    virtual Function*
+#else
+    virtual XalanEXSLTFunctionSplit*
+#endif
+    clone(MemoryManagerType&    theManager) const
+    {
+        return XalanCopyConstruct(theManager, *this);
+    }
+
+protected:
+
+    const XalanDOMString&
+    getError(XalanDOMString&    theBuffer) const
+    {
+        return XalanMessageLoader::getMessage(
+                    theBuffer,
+                    XalanMessages::EXSLTFunctionAccepts1Or2Argument_1Param,
+                    "split()");
+
+    }
+
+private:
+    // Not implemented...
+    XalanEXSLTFunctionSplit&
+    operator=(const XalanEXSLTFunctionSplit&);
+
+    bool
+    operator==(const XalanEXSLTFunctionSplit&) const;
+};
+
+
+
+class XALAN_EXSLT_EXPORT XalanEXSLTFunctionTokenize : public Function
+{
+public:
+
+    typedef Function    ParentType;
+
+    XalanEXSLTFunctionTokenize() :
+        Function()
+    {
+    }
+
+    virtual
+    ~XalanEXSLTFunctionTokenize()
+    {
+    }
+
+    // These methods are inherited from Function ...
+
+    virtual XObjectPtr
+    execute(
+            XPathExecutionContext&          executionContext,
+            XalanNode*                      context,
+            const XObjectArgVectorType&     args,
+            const LocatorType*              locator) const;
+
+#if !defined(XALAN_NO_USING_DECLARATION)
+    using ParentType::execute;
+#endif
+
+#if defined(XALAN_NO_COVARIANT_RETURN_TYPE)
+    virtual Function*
+#else
+    virtual XalanEXSLTFunctionTokenize*
+#endif
+    clone(MemoryManagerType&    theManager) const
+    {
+        return XalanCopyConstruct(theManager, *this);
+    }
+
+protected:
+
+    const XalanDOMString&
+    getError(XalanDOMString&    theBuffer) const
+    {
+        return XalanMessageLoader::getMessage(
+                    theBuffer,
+                    XalanMessages::EXSLTFunctionAccepts1Or2Argument_1Param,
+                    "tokenize()");
+
+    }
+
+private:
+    // Not implemented...
+    XalanEXSLTFunctionTokenize&
+    operator=(const XalanEXSLTFunctionTokenize&);
+
+    bool
+    operator==(const XalanEXSLTFunctionTokenize&) const;
+};
+
+
 XALAN_CPP_NAMESPACE_END
 
 
Index: c/src/xalanc/XalanEXSLT/XalanEXSLTString.cpp
===================================================================
--- c/src/xalanc/XalanEXSLT/XalanEXSLTString.cpp	(.../vendor/xml-xalan/1.10)	(revision 13764)
+++ c/src/xalanc/XalanEXSLT/XalanEXSLTString.cpp	(.../trunk/3rdparty/xml-xalan)	(revision 13764)
@@ -21,9 +21,17 @@
 #include <xalanc/PlatformSupport/DoubleSupport.hpp>
 #include <xalanc/PlatformSupport/XalanUnicode.hpp>
 #include <xalanc/PlatformSupport/XalanTranscodingServices.hpp>
+#include <xalanc/PlatformSupport/AttributesImpl.hpp>
 
 
 
+#include <xalanc/include/XalanVector.hpp>
+
+
+
+#include <xalanc/XalanDOM/XalanNode.hpp>
+
+
 #include <xalanc/DOMSupport/DOMServices.hpp>
 
 
@@ -33,10 +41,18 @@
 
 
 
+#include <xalanc/XalanTransformer/XalanDocumentBuilder.hpp>
+
+
+
+#include <xercesc/sax2/ContentHandler.hpp>
+
+
+
 XALAN_CPP_NAMESPACE_BEGIN
 
+XALAN_USING_XERCES(ContentHandler)
 
-
 const XalanDOMChar  XalanEXSLTFunctionAlign::s_centerString[] =
 {
     XalanUnicode::charLetter_c,
@@ -652,7 +668,469 @@
     return byte;
 }
 
+class ReplacePair
+{
+public:
+	ReplacePair(const XalanDOMString &search,
+				const XalanDOMString &replace) :
+		m_search(search),
+		m_replace(replace)
+	{
+	}
 
+	const XalanDOMString &getSearch() const
+	{
+		return m_search;
+	}
+
+	const XalanDOMString &getReplace() const
+	{
+		return m_replace;
+	}
+
+private:
+	XalanDOMString	m_search;
+	XalanDOMString	m_replace;
+};
+
+inline bool operator<(const ReplacePair &lhs, const ReplacePair &rhs)
+{
+	return lhs.getSearch().length() > rhs.getSearch().length();
+}
+
+static void doReplace(
+	XalanDOMString&						theResult,
+	XalanDOMString&						theTempString,
+	const XalanDOMString&				theString, 
+	XalanDOMString::size_type			start, 
+	XalanDOMString::size_type			end, 
+	const XalanVector<ReplacePair>&		replData,
+	XalanVector<ReplacePair>::size_type	replIndex)
+{
+	for (; replIndex < replData.size() && start < end; ++replIndex)
+	{
+		const XalanDOMString &match = replData[replIndex].getSearch();
+
+		for (XalanDOMString::size_type pos = start; pos < end; )
+		{
+			// Look for match
+			XalanDOMString::size_type i = 0;
+			for (;
+				 pos + i < end && i < match.length() &&
+				 theString[pos + i] == match[i]; ++i)
+				 ;
+			if (i != match.length())
+			{
+				// Definitely not the most efficient string 
+				// matching algorithm in the world...
+				pos++;
+				continue;
+			}
+
+			// Handle the odd case of zero length search string
+			if (i == 0) 
+			{
+				theString.substr(theTempString, start, 1);
+				theResult += theTempString;
+				theResult += replData[replIndex].getReplace();
+				pos = ++start;
+				continue;
+			}
+
+			if (pos > start)
+			{
+				// Recurse to handle subsequent replacements in the non-matching
+				// portion of the string
+				if (replIndex + 1 < replData.size())
+				{
+					doReplace(theResult, theTempString, theString, start, pos, replData, replIndex + 1);
+				}
+				// Or just take it as there are no replacements left
+				else
+				{
+					theString.substr(theTempString, start, pos - start);
+					theResult += theTempString;
+				}
+			}
+
+			// Add the replacement string in
+			theResult += replData[replIndex].getReplace();
+
+			// Carry on with the rest of the string
+			pos += i;
+			start = pos;
+		}
+	}
+	// Append anything left over
+	if (start != end)
+	{
+		theString.substr(theTempString, start, end - start);
+		theResult += theTempString;
+	}
+}
+
+
+static const AttributesImpl s_emptyAttributes(XalanMemMgrs::getDummyMemMgr());
+
+static const XalanDOMChar	s_rootNodeName[] =
+{
+    XalanUnicode::charLetter_r,
+    XalanUnicode::charLetter_o,
+    XalanUnicode::charLetter_o,
+    XalanUnicode::charLetter_t,
+    0
+};
+
+static const XalanDOMChar	s_emptyCharArray[] =
+{
+	0
+};
+
+XObjectPtr
+XalanEXSLTFunctionReplace::execute(
+			XPathExecutionContext&          executionContext,
+			XalanNode*                      context,
+			const XObjectArgVectorType&     args,
+			const LocatorType*              locator) const
+{
+    if (args.size() != 3)
+    {
+        XPathExecutionContext::GetAndReleaseCachedString    theGuard(executionContext);
+
+        XalanDOMString&     theBuffer = theGuard.get();
+
+        executionContext.error(getError(theBuffer), context, locator);
+    }
+
+	// Get the string to replace
+	const XalanDOMString& theString = args[0]->str();
+	
+	// Get the search/replaces pairs into a vector, dealing with the variety
+	// of things that the user is allowed to throw at us
+	XalanVector<ReplacePair> replData(executionContext.getMemoryManager());
+	switch (args[1]->getType())
+	{
+	case XObject::eTypeNodeSet:
+	{
+		// Deal with a nodeset of strings to replace as input
+		const NodeRefListBase &searches = args[1]->nodeset();
+
+		// See if the replacement is a single string
+		if (args[2]->getType() != XObject::eTypeNodeSet)
+		{
+			XPathExecutionContext::GetAndReleaseCachedString theData(executionContext);
+			XalanDOMString &theSearch = theData.get();
+
+			for (NodeRefListBase::size_type i = 0; i < searches.getLength(); ++i)
+			{
+				theSearch.clear();
+				if (searches.item(i))
+					DOMServices::getNodeData(*(searches.item(i)), theSearch);
+
+				if (i == 0)
+				{
+					replData.push_back(ReplacePair(theSearch, args[2]->str()));
+				}
+				else
+				{
+					replData.push_back(ReplacePair(theSearch, s_emptyString));
+				}
+			}
+		}
+		// Otherwise map the two nodesets together
+		else
+		{
+			const NodeRefListBase &replacements = args[2]->nodeset();
+
+			XPathExecutionContext::GetAndReleaseCachedString theSearchData(executionContext);
+			XalanDOMString &theSearch = theSearchData.get();
+
+			XPathExecutionContext::GetAndReleaseCachedString theReplacementData(executionContext);
+			XalanDOMString &theReplacement = theReplacementData.get();
+
+			for (NodeRefListBase::size_type i = 0; i < searches.getLength(); ++i)
+			{
+				theSearch.clear();
+				if (searches.item(i))
+					DOMServices::getNodeData(*(searches.item(i)), theSearch);
+
+				theReplacement.clear();
+				if (i < replacements.getLength())
+				{
+					if (replacements.item(i))
+						DOMServices::getNodeData(*(replacements.item(i)), theReplacement);
+				}
+				replData.push_back(ReplacePair(theSearch, theReplacement));
+			}
+		}
+		break;
+	}
+
+	default:
+	{
+		// Deal with a single search string
+		const XalanDOMString &theSearch = args[1]->str();
+
+		// Deal with a nodeset as a replacement
+		if (args[2]->getType() == XObject::eTypeNodeSet)
+		{
+			XPathExecutionContext::GetAndReleaseCachedString theData(executionContext);
+			XalanDOMString &theReplacement = theData.get();
+
+			const NodeRefListBase &nl = args[2]->nodeset();
+			if (nl.getLength() > 0 && nl.item(0))
+			{
+				DOMServices::getNodeData(*(nl.item(0)), theReplacement);
+			}
+
+			replData.push_back(ReplacePair(theSearch, theReplacement));
+		} 
+		// Deal with a single string as a replacement
+		else
+		{
+			replData.push_back(ReplacePair(theSearch, args[2]->str()));
+		}
+		break;
+	}
+	}
+
+	// Sort the vector by replacement length (longest search strings are replaced first)
+	XALAN_USING_STD(stable_sort)
+	stable_sort(replData.begin(), replData.end());
+
+	// Munch through the string doing replacements.
+	XPathExecutionContext::GetAndReleaseCachedString theResultData(executionContext);
+	XalanDOMString &theResult = theResultData.get();
+
+	XPathExecutionContext::GetAndReleaseCachedString theTempStringData(executionContext);
+	XalanDOMString &theTempString = theTempStringData.get();
+
+	doReplace(theResult, theTempString, theString, 0, theString.length(), replData, 0);
+
+	// Make a nodeset with the string in it (why a nodeset?)
+	XalanDocumentBuilder *theBuilder = executionContext.createDocumentBuilder();
+	ContentHandler *theContentHandler = theBuilder->getContentHandler();
+	theContentHandler->startDocument();
+	theContentHandler->startElement(s_emptyCharArray, s_emptyCharArray, s_rootNodeName, s_emptyAttributes);
+	theContentHandler->characters(theResult.data(), theResult.length());
+	theContentHandler->endElement(s_emptyCharArray, s_emptyCharArray, s_rootNodeName);
+	theContentHandler->endDocument();
+
+	XPathExecutionContext::BorrowReturnMutableNodeRefList mnl(executionContext);
+	XalanDocument *theDocument = theBuilder->getDocument();
+	XalanNode *theRootNode = theDocument->getFirstChild();
+	XalanNode *theTextNode = theRootNode->getFirstChild();
+	if (theTextNode)
+		mnl->addNodeInDocOrder(theTextNode, executionContext);
+	assert(mnl->checkForDuplicates(executionContext.getMemoryManager()) == false);
+	mnl->setDocumentOrder();
+	return executionContext.getXObjectFactory().createNodeSet(mnl);
+}
+
+static const XalanDOMChar   s_tokenName[] =
+{
+    XalanUnicode::charLetter_t,
+    XalanUnicode::charLetter_o,
+    XalanUnicode::charLetter_k,
+    XalanUnicode::charLetter_e,
+    XalanUnicode::charLetter_n,
+    0
+};
+
+XObjectPtr
+XalanEXSLTFunctionSplit::execute(
+			XPathExecutionContext&          executionContext,
+			XalanNode*                      context,
+			const XObjectArgVectorType&     args,
+			const LocatorType*              locator) const
+{
+	const XObjectArgVectorType::size_type   theSize = args.size();
+
+    if (theSize != 1 && theSize != 2)
+    {
+        XPathExecutionContext::GetAndReleaseCachedString    theGuard(executionContext);
+
+        XalanDOMString&     theBuffer = theGuard.get();
+
+        executionContext.error(getError(theBuffer), context, locator);
+    }
+
+	const XalanDOMString &theString = args[0]->str();
+
+	// Get the pattern, defaulting to a space
+	XPathExecutionContext::GetAndReleaseCachedString thePatternData(executionContext);
+	XalanDOMString &thePattern = thePatternData.get();
+
+	if (theSize == 2)
+		thePattern = args[1]->str();
+	else
+		thePattern = " ";
+
+	// Create a document for the result data
+	XalanDocumentBuilder *theBuilder = executionContext.createDocumentBuilder();
+	ContentHandler *theContentHandler = theBuilder->getContentHandler();
+	theContentHandler->startDocument();
+	theContentHandler->startElement(s_emptyCharArray, s_emptyCharArray, s_rootNodeName, s_emptyAttributes);
+
+	// Split the string on the pattern & add token nodes
+	XalanDOMString::size_type tokenStart = 0;
+	for (XalanDOMString::size_type i = 0; i < theString.length(); )
+	{
+		XalanDOMString::size_type j = 0;
+		for (;
+			 i + j < theString.length() && 
+			 j < thePattern.length() &&
+			 theString[i + j] == thePattern[j];
+			 ++j)
+			;
+
+		if (j != thePattern.length())
+		{
+			// Match again
+			++i;
+			continue;
+		}
+
+		theContentHandler->startElement(s_emptyCharArray, s_emptyCharArray, s_tokenName, s_emptyAttributes);
+		
+		// Handle a zero length pattern by outputting just the next character
+		if (thePattern.length() == 0)
+		{
+			theContentHandler->characters(&theString[i], 1);
+			++i;
+		}
+		// Otherwise output the bit before the token
+		else
+		{
+			theContentHandler->characters(&theString[tokenStart], i - tokenStart);
+			tokenStart = (i += j);
+		}
+
+		theContentHandler->endElement(s_emptyCharArray, s_emptyCharArray, s_tokenName);
+	}
+	
+	// Add last token if non-empty
+	if (thePattern.length() > 0 && tokenStart != theString.length())
+	{
+		theContentHandler->startElement(s_emptyCharArray, s_emptyCharArray, s_tokenName, s_emptyAttributes);
+		theContentHandler->characters(&theString[tokenStart], theString.length() - tokenStart);
+		theContentHandler->endElement(s_emptyCharArray, s_emptyCharArray, s_tokenName);
+	}
+
+	// Make a nodeset with the token nodes in it
+	theContentHandler->endElement(s_emptyCharArray, s_emptyCharArray, s_rootNodeName);
+	theContentHandler->endDocument();
+	XPathExecutionContext::BorrowReturnMutableNodeRefList mnl(executionContext);
+	XalanDocument *theDocument = theBuilder->getDocument();
+	for (XalanNode *tokenNode = theDocument->getFirstChild()->getFirstChild();
+		 tokenNode;
+		 tokenNode = tokenNode->getNextSibling())
+	{
+		mnl->addNodeInDocOrder(tokenNode, executionContext);
+	}
+	assert(mnl->checkForDuplicates(executionContext.getMemoryManager()) == false);
+	mnl->setDocumentOrder();
+	return executionContext.getXObjectFactory().createNodeSet(mnl);
+}
+
+XObjectPtr
+XalanEXSLTFunctionTokenize::execute(
+			XPathExecutionContext&          executionContext,
+			XalanNode*                      context,
+			const XObjectArgVectorType&     args,
+			const LocatorType*              locator) const
+{
+	const XObjectArgVectorType::size_type   theSize = args.size();
+
+    if (theSize != 1 && theSize != 2)
+    {
+        XPathExecutionContext::GetAndReleaseCachedString    theGuard(executionContext);
+
+        XalanDOMString&     theBuffer = theGuard.get();
+
+        executionContext.error(getError(theBuffer), context, locator);
+    }
+
+	const XalanDOMString &theString = args[0]->str();
+
+	// Get the pattern, defaulting to a space
+	XPathExecutionContext::GetAndReleaseCachedString thePatternData(executionContext);
+	XalanDOMString &thePattern = thePatternData.get();
+
+	if (theSize == 2)
+		thePattern = args[1]->str();
+	else
+		thePattern = " ";
+
+	// Create a document for the result data
+	XalanDocumentBuilder *theBuilder = executionContext.createDocumentBuilder();
+	ContentHandler *theContentHandler = theBuilder->getContentHandler();
+	theContentHandler->startDocument();
+	theContentHandler->startElement(s_emptyCharArray, s_emptyCharArray, s_rootNodeName, s_emptyAttributes);
+
+	// Split the string on the pattern & add token nodes
+	XalanDOMString::size_type tokenStart = 0;
+	for (XalanDOMString::size_type i = 0; i < theString.length(); )
+	{
+		if (thePattern.length() > 0)
+		{
+			XalanDOMString::size_type j = 0;
+			for (j = 0; j < thePattern.length(); ++j)
+			{
+				if (theString[i] == thePattern[j])
+					break;
+			}
+
+			if (j >= thePattern.length())
+			{
+				// Match again
+				++i;
+				continue;
+			}
+		}
+
+		theContentHandler->startElement(s_emptyCharArray, s_emptyCharArray, s_tokenName, s_emptyAttributes);
+		
+		// Handle a zero length pattern by outputting just the next character
+		if (thePattern.length() == 0)
+		{
+			theContentHandler->characters(&theString[i], 1);
+			++i;
+		}
+		// Otherwise output the bit before the token
+		else
+		{
+			theContentHandler->characters(&theString[tokenStart], i - tokenStart);
+			tokenStart = ++i;
+		}
+
+		theContentHandler->endElement(s_emptyCharArray, s_emptyCharArray, s_tokenName);
+	}
+	
+	// Add last token if non-empty
+	if (thePattern.length() > 0 && tokenStart != theString.length())
+	{
+		theContentHandler->startElement(s_emptyCharArray, s_emptyCharArray, s_tokenName, s_emptyAttributes);
+		theContentHandler->characters(&theString[tokenStart], theString.length() - tokenStart);
+		theContentHandler->endElement(s_emptyCharArray, s_emptyCharArray, s_tokenName);
+	}
+
+	// Make a nodeset with the token nodes in it
+	theContentHandler->endElement(s_emptyCharArray, s_emptyCharArray, s_rootNodeName);
+	theContentHandler->endDocument();
+	XPathExecutionContext::BorrowReturnMutableNodeRefList mnl(executionContext);
+	XalanDocument *theDocument = theBuilder->getDocument();
+	for (XalanNode *tokenNode = theDocument->getFirstChild()->getFirstChild();
+		 tokenNode;
+		 tokenNode = tokenNode->getNextSibling())
+	{
+		mnl->addNodeInDocOrder(tokenNode, executionContext);
+	}
+	assert(mnl->checkForDuplicates(executionContext.getMemoryManager()) == false);
+	mnl->setDocumentOrder();
+	return executionContext.getXObjectFactory().createNodeSet(mnl);
+}
+
 static const XalanDOMChar   s_stringNamespace[] =
 {
     XalanUnicode::charLetter_h,
@@ -751,19 +1229,56 @@
     0
 };
 
+static const XalanDOMChar   s_replaceFunctionName[] =
+{
+    XalanUnicode::charLetter_r,
+    XalanUnicode::charLetter_e,
+    XalanUnicode::charLetter_p,
+    XalanUnicode::charLetter_l,
+    XalanUnicode::charLetter_a,
+    XalanUnicode::charLetter_c,
+	XalanUnicode::charLetter_e,
+    0
+};
+
+static const XalanDOMChar   s_splitFunctionName[] =
+{
+    XalanUnicode::charLetter_s,
+    XalanUnicode::charLetter_p,
+    XalanUnicode::charLetter_l,
+    XalanUnicode::charLetter_i,
+    XalanUnicode::charLetter_t,
+    0
+};
+
+static const XalanDOMChar   s_tokenizeFunctionName[] =
+{
+    XalanUnicode::charLetter_t,
+    XalanUnicode::charLetter_o,
+    XalanUnicode::charLetter_k,
+    XalanUnicode::charLetter_e,
+    XalanUnicode::charLetter_n,
+    XalanUnicode::charLetter_i,
+	XalanUnicode::charLetter_z,
+    XalanUnicode::charLetter_e,
+    0
+};
+
 static const XalanEXSLTFunctionAlign    s_alignFunction;
 static const XalanEXSLTFunctionConcat   s_concatFunction;
+static const XalanEXSLTFunctionReplace	s_replaceFunction;
+static const XalanEXSLTFunctionSplit	s_splitFunction;
+static const XalanEXSLTFunctionTokenize	s_tokenizeFunction;
+
 // Note this is a special constructor of XalanEXSLTFunctionPadding which
 // allocates no memory.  It is only used here, so we can have table-based
 // initialization, but not have any memory allocation.
-
 static const XalanEXSLTFunctionPadding  s_paddingFunction(XalanMemMgrs::getDummyMemMgr(), 1);
 
 static const XalanEXSLTFunctionEncodeURI s_encodeUriFunction;
 static const XalanEXSLTFunctionDecodeURI s_decodeUriFunction;
 
 
-
 static const XalanEXSLTStringFunctionsInstaller::FunctionTableEntry     theFunctionTable[] =
 {
     { s_alignFunctionName, &s_alignFunction },
@@ -771,6 +1286,9 @@
     { s_paddingFunctionName, &s_paddingFunction },
     { s_encodeUriFunctionName, &s_encodeUriFunction },
     { s_decodeUriFunctionName, &s_decodeUriFunction },
+	{ s_replaceFunctionName, &s_replaceFunction },
+	{ s_splitFunctionName, &s_splitFunction },
+	{ s_tokenizeFunctionName, &s_tokenizeFunction },
     { 0, 0 }
 };
 
Index: c/src/xalanc/NLS/en_US/XalanMsg_en_US.xlf
===================================================================
--- c/src/xalanc/NLS/en_US/XalanMsg_en_US.xlf	(.../vendor/xml-xalan/1.10)	(revision 13764)
+++ c/src/xalanc/NLS/en_US/XalanMsg_en_US.xlf	(.../trunk/3rdparty/xml-xalan)	(revision 13764)
@@ -777,6 +777,11 @@
 		<target>The EXSLT function '{0}' accepts one or two arguments.</target>
 </trans-unit>
 
+<trans-unit id="EXSLTFunctionAcceptsThreeArguments_1Param">
+		<source>The EXSLT function '{0}' accepts three arguments.</source>
+		<target>The EXSLT function '{0}' accepts three arguments.</target>
+</trans-unit>
+
 <trans-unit id="XalanDOMExceptionCaught_1Param">
 		<source>XalanDOMException caught. The code is '{0}'.</source>
 		<target>XalanDOMException caught. The code is '{0}'.</target>
