What you are doing is returning a string that will be added as a text node. The markup in the string has to be escaped so that it will not be mistaken for markup (which is actually what you want).

What you need to do is create DOM nodes. Try:

<?xml version="1.0"?>

<xsl:stylesheet xmlns:xsl="http://www.w3.org/XSL/Transform/1.0"
xmlns:myns="http://edgar.com"
xmlns="http://www.w3.org/TR/REC-html40" result-ns=""
indent-result="yes">

<xsl:functions ns="myns" type="text/javascript"><![CDATA[

function menu(resultNode)
{
doc = resultNode.getOwnerDocument();
frag = doc.createDocumentFragment();
elem = doc.createElement("OPTION");
elem.appendChild(doc.createTextNode("choice1"));
frag.appendChild(elem);
return frag;
}

]]></xsl:functions>

<xsl:variable name="resultNode">.</xsl:variable>

<xsl:template match="/">
<SELECT name="menu">
<xsl:copy-of select="myns:menu($resultNode)"/>
</SELECT>
</xsl:template>

</xsl:stylesheet>

Which will give you:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<SELECT name="menu">
<OPTION>choice1</OPTION>
</SELECT>

Sorry if this looks a bit complex. What this is doing is:

1) create a result tree fragment via xsl:variable. This is simply an easy way to get a Node that is based on the result tree, so you can get a Document object, which you need to create new nodes.

2) Pass that variable to the function.

3) Create a result tree fragment object, which will hold whatever result tree fragment you want to create.

4) Create an element.

5) Create a text node and add it to the element.

6) Add the element to the fragment's child list.

7) return the fragment to the XSL processor.

8) xsl:copy-of copies the fragment to the result tree. (Note: xsl:value-of will not work here).

Sorry this is so complex. I'm not sure of an easy way to just return a string and have it interpreted as markup.

-scott