/*
 * 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());
         }
      }
   }
}

Reply via email to