Christian ---
This works fine for me. I had to put the class in a package because
XalanJ assumes that anything registered without a package name is in its
own functions package.
My output is:
C:\Temp>java foo.FuncHere
Registered class foo.FuncHere for here() function in internal table
FuncHere.execute() has been called
#NODESET
xpath
Gary
Christian Geuer-Pollmann wrote:
>
> /*
> * Hi Xalan-Gurus,
> * dear Gary,
> *
> * My extension function crashes (and i programmed some things that I took
> * from the org.apache.xpath.functions package but did not understood
> completely).
> *
> * Could you please have a short (or longer) look at the code and give me
> some advise?
> *
> * Regards,
> * Christian
> *
> * @author <mailto:[EMAIL PROTECTED]>
> */
>
> import java.io.*;
> import java.util.*;
> import javax.xml.parsers.DocumentBuilder;
> import javax.xml.parsers.DocumentBuilderFactory;
> import org.apache.xalan.extensions.*;
> import org.apache.xalan.templates.*;
> import org.apache.xerces.dom.*;
> import org.apache.xml.utils.*;
> import org.apache.xml.dtm.*;
> import org.apache.xpath.*;
> import org.apache.xpath.objects.*;
> import org.apache.xpath.functions.Function;
> import org.apache.xpath.compiler.FunctionTable;
> import org.apache.xpath.res.XPATHErrorResources;
> import org.w3c.dom.*;
> import org.w3c.dom.traversal.NodeIterator;
>
> /**
> * The here function returns a node-set containing the attribute or
> * processing instruction node or the parent element of the text node
> * that directly bears the XPath expression. This expression results
> * in an error if the containing XPath expression does not appear in the
> * same XML document against which the XPath expression is being evaluated.
> *
> * Mainpart is stolen from FuncId.java
> *
> * @see
> http://www.w3.org/Signature/Drafts/xmldsig-core/Overview.html#function-here
> */
> public class FuncHere extends Function {
>
> public XObject execute(XPathContext xctxt)
> throws javax.xml.transform.TransformerException {
>
> System.out.println("FuncHere.execute() has been called");
>
> int currentNode = xctxt.getCurrentNode();
> DTM dtm = xctxt.getDTM(currentNode);
> int docContext = dtm.getDocument();
>
> if (DTM.NULL == docContext) {
> error(xctxt, XPATHErrorResources.ER_CONTEXT_HAS_NO_OWNERDOC, null);
> }
>
> XNodeSet nodes = new XNodeSet(xctxt.getDTMManager());
> NodeSetDTM nodeSet = nodes.mutableNodeset();
>
> // Do processing here
> {
> int contextNode = xctxt.getContextNode();
> int hereNode;
> if (dtm.getNodeType(contextNode) == Node.ATTRIBUTE_NODE) {
> hereNode = contextNode;
> } else if (dtm.getNodeType(contextNode) ==
> Node.PROCESSING_INSTRUCTION_NODE) {
> hereNode = contextNode;
> } else if (dtm.getNodeType(contextNode) == Node.TEXT_NODE) {
> hereNode = dtm.getParent(contextNode);
> } else {
> hereNode = DTM.NULL;
> }
>
> if (DTM.NULL != hereNode) {
> nodeSet.addNode(hereNode);
> }
> }
>
> // must I do this detach() ?
> nodeSet.detach();
> return nodes;
> }
>
> /**
> * No arguments to process, so this does nothing.
> * @param vars
> * @param globalsSize
> */
> public void fixupVariables(java.util.Vector vars, int globalsSize) {}
>
> /**
> * Method main
> *
> * @param unused
> * @throws Exception
> */
> public static void main(String unused[]) throws Exception {
>
> String thisClass = FuncHere.class.getName();
>
> /**
> * Try to register out here() implementation as internal function.
> * @todo Is this too much hardcore?
> */
> FunctionTable.installFunction("here", new FuncHere());
> System.out.println("Registered class " + thisClass
> + " for here() function in internal table");
>
> //J-
> String input =
> "<?xml version='1.0' encoding='UTF-8' ?>\n"
> + "<!DOCTYPE root [\n"
> + "<!ATTLIST XPath\n"
> + " Id ID #REQUIRED>\n"
> + "]>\n"
> + "<root>\n"
> + " <XPath Id='hereInText'>here()</XPath>\n"
> + " <XPath Id='hereInAttr' xpath='here()' />\n"
> + "</root>";
> //J+
> DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
>
> dbf.setNamespaceAware(true);
>
> DocumentBuilder db = dbf.newDocumentBuilder();
> Document doc = db.parse(new ByteArrayInputStream(input.getBytes()));
> Node a = XPathAPI.selectSingleNode(doc, "/root/XPath[2]");
> Node attr = ((Element) a).getAttributeNode("xpath");
> XObject o = XPathAPI.eval(attr, attr.getNodeValue());
>
> System.out.println(o.getTypeString());
>
> if (o.getType() == XObject.CLASS_NODESET) {
> NodeIterator ni = o.nodeset();
> Node currNode;
>
> while ((currNode = ni.nextNode()) != null) {
> System.out.println(currNode.getNodeName());
> }
> }
> }
> }