Exemple #1
0
 /**
  * Get the value of a node as a string.
  *
  * @param n Node to be converted to a string. May be null.
  * @return value of n as a string, or an empty string if n is null.
  */
 public String toString(org.w3c.dom.Node n) {
   // %REVIEW% You can't get much uglier than this...
   int nodeHandle = getDTMHandleFromNode(n);
   DTM dtm = getDTM(nodeHandle);
   XMLString strVal = dtm.getStringValue(nodeHandle);
   return strVal.toString();
 }
  /**
   * Try and find a node that was previously counted. If found, return a positive integer that
   * corresponds to the count.
   *
   * @param support The XPath context to use
   * @param node The node to be counted.
   * @return The count of the node, or -1 if not found.
   */
  int getPreviouslyCounted(XPathContext support, int node) {

    int n = m_countNodes.size();

    m_countResult = 0;

    for (int i = n - 1; i >= 0; i--) {
      int countedNode = m_countNodes.elementAt(i);

      if (node == countedNode) {

        // Since the list is in backwards order, the count is
        // how many are in the rest of the list.
        m_countResult = i + 1 + m_countNodesStartCount;

        break;
      }

      DTM dtm = support.getDTM(countedNode);

      // Try to see if the given node falls after the counted node...
      // if it does, don't keep searching backwards.
      if (dtm.isNodeAfter(countedNode, node)) break;
    }

    return m_countResult;
  }
Exemple #3
0
 /**
  * Get the value of a node as a number.
  *
  * @param n Node to be converted to a number. May be null.
  * @return value of n as a number.
  */
 public double toNumber(org.w3c.dom.Node n) {
   // %REVIEW% You can't get much uglier than this...
   int nodeHandle = getDTMHandleFromNode(n);
   DTM dtm = getDTM(nodeHandle);
   XString xobj = (XString) dtm.getStringValue(nodeHandle);
   return xobj.num();
 }
Exemple #4
0
  /**
   * Add the node into a vector of nodes where it should occur in document order.
   *
   * @param node The node to be added.
   * @param test true if we should test for doc order
   * @param support The XPath runtime context.
   * @return insertIndex.
   * @throws RuntimeException thrown if this NodeSetDTM is not of a mutable type.
   */
  public int addNodeInDocOrder(int node, boolean test, XPathContext support) {

    if (!m_mutable)
      throw new RuntimeException(
          XSLMessages.createXPATHMessage(
              XPATHErrorResources.ER_NODESETDTM_NOT_MUTABLE,
              null)); // "This NodeSetDTM is not mutable!");

    int insertIndex = -1;

    if (test) {

      // This needs to do a binary search, but a binary search
      // is somewhat tough because the sequence test involves
      // two nodes.
      int size = size(), i;

      for (i = size - 1; i >= 0; i--) {
        int child = elementAt(i);

        if (child == node) {
          i = -2; // Duplicate, suppress insert

          break;
        }

        DTM dtm = support.getDTM(node);
        if (!dtm.isNodeAfter(node, child)) {
          break;
        }
      }

      if (i != -2) {
        insertIndex = i + 1;

        insertElementAt(node, insertIndex);
      }
    } else {
      insertIndex = this.size();

      boolean foundit = false;

      for (int i = 0; i < insertIndex; i++) {
        if (i == node) {
          foundit = true;

          break;
        }
      }

      if (!foundit) addElement(node);
    }

    // checkDups();
    return insertIndex;
  } // end addNodeInDocOrder(Vector v, Object obj)
Exemple #5
0
  /**
   * Tell what the test score is for the given node.
   *
   * @param xctxt XPath runtime context.
   * @param context The node being tested.
   * @return {@link org.apache.xpath.patterns.NodeTest#SCORE_NODETEST}, {@link
   *     org.apache.xpath.patterns.NodeTest#SCORE_NONE}, {@link
   *     org.apache.xpath.patterns.NodeTest#SCORE_NSWILD}, {@link
   *     org.apache.xpath.patterns.NodeTest#SCORE_QNAME}, or {@link
   *     org.apache.xpath.patterns.NodeTest#SCORE_OTHER}.
   * @throws javax.xml.transform.TransformerException
   */
  public XObject execute(XPathContext xctxt, int context, DTM dtm, int expType)
      throws javax.xml.transform.TransformerException {

    if (m_whatToShow == DTMFilter.SHOW_ALL) return m_score;

    int nodeBit = (m_whatToShow & (0x00000001 << ((dtm.getNodeType(context)) - 1)));

    switch (nodeBit) {
      case DTMFilter.SHOW_DOCUMENT_FRAGMENT:
      case DTMFilter.SHOW_DOCUMENT:
        return SCORE_OTHER;
      case DTMFilter.SHOW_COMMENT:
        return m_score;
      case DTMFilter.SHOW_CDATA_SECTION:
      case DTMFilter.SHOW_TEXT:

        // was:
        // return (!xctxt.getDOMHelper().shouldStripSourceNode(context))
        //       ? m_score : SCORE_NONE;
        return m_score;
      case DTMFilter.SHOW_PROCESSING_INSTRUCTION:
        return subPartMatch(dtm.getNodeName(context), m_name) ? m_score : SCORE_NONE;

        // From the draft: "Two expanded names are equal if they
        // have the same local part, and either both have no URI or
        // both have the same URI."
        // "A node test * is true for any node of the principal node type.
        // For example, child::* will select all element children of the
        // context node, and attribute::* will select all attributes of
        // the context node."
        // "A node test can have the form NCName:*. In this case, the prefix
        // is expanded in the same way as with a QName using the context
        // namespace declarations. The node test will be true for any node
        // of the principal type whose expanded name has the URI to which
        // the prefix expands, regardless of the local part of the name."
      case DTMFilter.SHOW_NAMESPACE:
        {
          String ns = dtm.getNodeValue(context);

          return (subPartMatch(ns, m_name)) ? m_score : SCORE_NONE;
        }
      case DTMFilter.SHOW_ATTRIBUTE:
      case DTMFilter.SHOW_ELEMENT:
        {
          return (m_isTotallyWild
                  || (subPartMatchNS(dtm.getNamespaceURI(context), m_namespace)
                      && subPartMatch(dtm.getLocalName(context), m_name)))
              ? m_score
              : SCORE_NONE;
        }
      default:
        return SCORE_NONE;
    } // end switch(testType)
  }
Exemple #6
0
  /**
   * Execute the first argument expression that is expected to return a string. If the argument is
   * null, then get the string value from the current context node.
   *
   * @param xctxt Runtime XPath context.
   * @return The string value of the first argument, or the string value of the current context node
   *     if the first argument is null.
   * @throws javax.xml.transform.TransformerException if an error occurs while executing the
   *     argument expression.
   */
  protected XMLString getArg0AsString(XPathContext xctxt)
      throws javax.xml.transform.TransformerException {
    if (null == m_arg0) {
      int currentNode = xctxt.getCurrentNode();
      if (DTM.NULL == currentNode) return XString.EMPTYSTRING;
      else {
        DTM dtm = xctxt.getDTM(currentNode);
        return dtm.getStringValue(currentNode);
      }

    } else return m_arg0.execute(xctxt).xstr();
  }
Exemple #7
0
  /**
   * Execute the first argument expression that is expected to return a number. If the argument is
   * null, then get the number value from the current context node.
   *
   * @param xctxt Runtime XPath context.
   * @return The number value of the first argument, or the number value of the current context node
   *     if the first argument is null.
   * @throws javax.xml.transform.TransformerException if an error occurs while executing the
   *     argument expression.
   */
  protected double getArg0AsNumber(XPathContext xctxt)
      throws javax.xml.transform.TransformerException {

    if (null == m_arg0) {
      int currentNode = xctxt.getCurrentNode();
      if (DTM.NULL == currentNode) return 0;
      else {
        DTM dtm = xctxt.getDTM(currentNode);
        XMLString str = dtm.getStringValue(currentNode);
        return str.toDouble();
      }

    } else return m_arg0.execute(xctxt).num();
  }
Exemple #8
0
  /**
   * Perform a query if needed, and call transformNode for each child.
   *
   * @param transformer non-null reference to the the current transform-time state.
   * @throws TransformerException Thrown in a variety of circumstances.
   * @xsl.usage advanced
   */
  public void transformSelectedNodes(TransformerImpl transformer) throws TransformerException {

    final XPathContext xctxt = transformer.getXPathContext();
    final int sourceNode = xctxt.getCurrentNode();
    DTMIterator sourceNodes = m_selectExpression.asIterator(xctxt, sourceNode);

    try {

      final Vector keys =
          (m_sortElems == null) ? null : transformer.processSortKeys(this, sourceNode);

      // Sort if we need to.
      if (null != keys) sourceNodes = sortNodes(xctxt, keys, sourceNodes);

      if (transformer.getDebug()) {

        // The original code, which is broken for bug#16889,
        // which fails to get the original select expression in the select event.
        /*  transformer.getTraceManager().fireSelectedEvent(
         *    sourceNode,
         *            this,
         *            "select",
         *            new XPath(m_selectExpression),
         *            new org.apache.xpath.objects.XNodeSet(sourceNodes));
         */

        // The following code fixes bug#16889
        // Solution: Store away XPath in setSelect(Xath), and use it here.
        // Pass m_xath, which the current node is associated with, onto the TraceManager.

        Expression expr = m_xpath.getExpression();
        org.apache.xpath.objects.XObject xObject = expr.execute(xctxt);
        int current = xctxt.getCurrentNode();
        transformer.getTraceManager().fireSelectedEvent(current, this, "select", m_xpath, xObject);
      }

      xctxt.pushCurrentNode(DTM.NULL);

      IntStack currentNodes = xctxt.getCurrentNodeStack();

      xctxt.pushCurrentExpressionNode(DTM.NULL);

      IntStack currentExpressionNodes = xctxt.getCurrentExpressionNodeStack();

      xctxt.pushSAXLocatorNull();
      xctxt.pushContextNodeList(sourceNodes);
      transformer.pushElemTemplateElement(null);

      // pushParams(transformer, xctxt);
      // Should be able to get this from the iterator but there must be a bug.
      DTM dtm = xctxt.getDTM(sourceNode);
      int docID = sourceNode & DTMManager.IDENT_DTM_DEFAULT;
      int child;

      while (DTM.NULL != (child = sourceNodes.nextNode())) {
        currentNodes.setTop(child);
        currentExpressionNodes.setTop(child);

        if ((child & DTMManager.IDENT_DTM_DEFAULT) != docID) {
          dtm = xctxt.getDTM(child);
          docID = child & DTMManager.IDENT_DTM_DEFAULT;
        }

        // final int exNodeType = dtm.getExpandedTypeID(child);
        final int nodeType = dtm.getNodeType(child);

        // Fire a trace event for the template.
        if (transformer.getDebug()) {
          transformer.getTraceManager().fireTraceEvent(this);
        }

        // And execute the child templates.
        // Loop through the children of the template, calling execute on
        // each of them.
        for (ElemTemplateElement t = this.m_firstChild; t != null; t = t.m_nextSibling) {
          xctxt.setSAXLocator(t);
          transformer.setCurrentElement(t);
          t.execute(transformer);
        }

        if (transformer.getDebug()) {
          // We need to make sure an old current element is not
          // on the stack.  See TransformerImpl#getElementCallstack.
          transformer.setCurrentElement(null);
          transformer.getTraceManager().fireTraceEndEvent(this);
        }

        // KLUGE: Implement <?xalan:doc_cache_off?>
        // ASSUMPTION: This will be set only when the XPath was indeed
        // a call to the Document() function. Calling it in other
        // situations is likely to fry Xalan.
        //
        // %REVIEW% We need a MUCH cleaner solution -- one that will
        // handle cleaning up after document() and getDTM() in other
        // contexts. The whole SourceTreeManager mechanism should probably
        // be moved into DTMManager rather than being explicitly invoked in
        // FuncDocument and here.
        if (m_doc_cache_off) {
          if (DEBUG)
            System.out.println(
                "JJK***** CACHE RELEASE *****\n" + "\tdtm=" + dtm.getDocumentBaseURI());
          // NOTE: This will work because this is _NOT_ a shared DTM, and thus has
          // only a single Document node. If it could ever be an RTF or other
          // shared DTM, this would require substantial rework.
          xctxt.getSourceTreeManager().removeDocumentFromCache(dtm.getDocument());
          xctxt.release(dtm, false);
        }
      }
    } finally {
      if (transformer.getDebug())
        transformer
            .getTraceManager()
            .fireSelectedEndEvent(
                sourceNode,
                this,
                "select",
                new XPath(m_selectExpression),
                new org.apache.xpath.objects.XNodeSet(sourceNodes));

      xctxt.popSAXLocator();
      xctxt.popContextNodeList();
      transformer.popElemTemplateElement();
      xctxt.popCurrentExpressionNode();
      xctxt.popCurrentNode();
      sourceNodes.detach();
    }
  }
  /**
   * Execute the function. The function must return a valid object.
   *
   * @param xctxt The current execution context.
   * @return A valid XObject.
   * @throws javax.xml.transform.TransformerException
   */
  public XObject execute(XPathContext xctxt) throws javax.xml.transform.TransformerException {

    // TransformerImpl transformer = (TransformerImpl)xctxt;
    TransformerImpl transformer = (TransformerImpl) xctxt.getOwnerObject();
    XNodeSet nodes = null;
    int context = xctxt.getCurrentNode();
    DTM dtm = xctxt.getDTM(context);
    int docContext = dtm.getDocumentRoot(context);

    if (DTM.NULL == docContext) {

      // path.error(context, XPATHErrorResources.ER_CONTEXT_HAS_NO_OWNERDOC); //"context does not
      // have an owner document!");
    }

    String xkeyname = getArg0().execute(xctxt).str();
    QName keyname = new QName(xkeyname, xctxt.getNamespaceContext());
    XObject arg = getArg1().execute(xctxt);
    boolean argIsNodeSetDTM = (XObject.CLASS_NODESET == arg.getType());
    KeyManager kmgr = transformer.getKeyManager();

    // Don't bother with nodeset logic if the thing is only one node.
    if (argIsNodeSetDTM) {
      XNodeSet ns = (XNodeSet) arg;
      ns.setShouldCacheNodes(true);
      int len = ns.getLength();
      if (len <= 1) argIsNodeSetDTM = false;
    }

    if (argIsNodeSetDTM) {
      Hashtable usedrefs = null;
      DTMIterator ni = arg.iter();
      int pos;
      UnionPathIterator upi = new UnionPathIterator();
      upi.exprSetParent(this);

      while (DTM.NULL != (pos = ni.nextNode())) {
        dtm = xctxt.getDTM(pos);
        XMLString ref = dtm.getStringValue(pos);

        if (null == ref) continue;

        if (null == usedrefs) usedrefs = new Hashtable();

        if (usedrefs.get(ref) != null) {
          continue; // We already have 'em.
        } else {

          // ISTRUE being used as a dummy value.
          usedrefs.put(ref, ISTRUE);
        }

        XNodeSet nl =
            kmgr.getNodeSetDTMByKey(xctxt, docContext, keyname, ref, xctxt.getNamespaceContext());

        nl.setRoot(xctxt.getCurrentNode(), xctxt);

        //        try
        //        {
        upi.addIterator(nl);
        //        }
        //        catch(CloneNotSupportedException cnse)
        //        {
        //          // will never happen.
        //        }
        // mnodeset.addNodesInDocOrder(nl, xctxt); needed??
      }

      int current = xctxt.getCurrentNode();
      upi.setRoot(current, xctxt);

      nodes = new XNodeSet(upi);
    } else {
      XMLString ref = arg.xstr();
      nodes = kmgr.getNodeSetDTMByKey(xctxt, docContext, keyname, ref, xctxt.getNamespaceContext());
      nodes.setRoot(xctxt.getCurrentNode(), xctxt);
    }

    return nodes;
  }
  /**
   * <meta name="usage" content="advanced"/> Perform a query if needed, and call transformNode for
   * each child.
   *
   * @param transformer non-null reference to the the current transform-time state.
   * @param template The owning template context.
   * @throws TransformerException Thrown in a variety of circumstances.
   */
  public void transformSelectedNodes(TransformerImpl transformer) throws TransformerException {

    final XPathContext xctxt = transformer.getXPathContext();
    final int sourceNode = xctxt.getCurrentNode();
    DTMIterator sourceNodes = m_selectExpression.asIterator(xctxt, sourceNode);
    VariableStack vars = xctxt.getVarStack();
    int nParams = getParamElemCount();
    int thisframe = vars.getStackFrame();
    StackGuard guard = transformer.getStackGuard();
    boolean check = (guard.getRecursionLimit() > -1) ? true : false;

    try {

      final Vector keys =
          (m_sortElems == null) ? null : transformer.processSortKeys(this, sourceNode);

      // Sort if we need to.
      if (null != keys) sourceNodes = sortNodes(xctxt, keys, sourceNodes);

      if (TransformerImpl.S_DEBUG) {
        transformer
            .getTraceManager()
            .fireSelectedEvent(
                sourceNode,
                this,
                "select",
                new XPath(m_selectExpression),
                new org.apache.xpath.objects.XNodeSet(sourceNodes));
      }

      final ResultTreeHandler rth = transformer.getResultTreeHandler();
      ContentHandler chandler = rth.getContentHandler();
      final StylesheetRoot sroot = transformer.getStylesheet();
      final TemplateList tl = sroot.getTemplateListComposed();
      final boolean quiet = transformer.getQuietConflictWarnings();

      // Should be able to get this from the iterator but there must be a bug.
      DTM dtm = xctxt.getDTM(sourceNode);

      int argsFrame = -1;
      if (nParams > 0) {
        // This code will create a section on the stack that is all the
        // evaluated arguments.  These will be copied into the real params
        // section of each called template.
        argsFrame = vars.link(nParams);
        vars.setStackFrame(thisframe);

        for (int i = 0; i < nParams; i++) {
          ElemWithParam ewp = m_paramElems[i];
          XObject obj = ewp.getValue(transformer, sourceNode);

          vars.setLocalVariable(i, obj, argsFrame);
        }
        vars.setStackFrame(argsFrame);
      }

      xctxt.pushCurrentNode(DTM.NULL);
      IntStack currentNodes = xctxt.getCurrentNodeStack();

      xctxt.pushCurrentExpressionNode(DTM.NULL);
      IntStack currentExpressionNodes = xctxt.getCurrentExpressionNodeStack();

      xctxt.pushSAXLocatorNull();
      xctxt.pushContextNodeList(sourceNodes);
      transformer.pushElemTemplateElement(null);
      // pushParams(transformer, xctxt);

      int child;
      while (DTM.NULL != (child = sourceNodes.nextNode())) {
        currentNodes.setTop(child);
        currentExpressionNodes.setTop(child);

        if (xctxt.getDTM(child) != dtm) {
          dtm = xctxt.getDTM(child);
        }

        final int exNodeType = dtm.getExpandedTypeID(child);
        final int nodeType = dtm.getNodeType(child);

        final QName mode = transformer.getMode();

        ElemTemplate template = tl.getTemplateFast(xctxt, child, exNodeType, mode, -1, quiet, dtm);

        // If that didn't locate a node, fall back to a default template rule.
        // See http://www.w3.org/TR/xslt#built-in-rule.
        if (null == template) {
          switch (nodeType) {
            case DTM.DOCUMENT_FRAGMENT_NODE:
            case DTM.ELEMENT_NODE:
              template = sroot.getDefaultRule();
              // %OPT% direct faster?
              break;
            case DTM.ATTRIBUTE_NODE:
            case DTM.CDATA_SECTION_NODE:
            case DTM.TEXT_NODE:
              // if(rth.m_elemIsPending || rth.m_docPending)
              //  rth.flushPending(true);
              transformer.pushPairCurrentMatched(sroot.getDefaultTextRule(), child);
              transformer.setCurrentElement(sroot.getDefaultTextRule());
              // dtm.dispatchCharactersEvents(child, chandler, false);
              dtm.dispatchCharactersEvents(child, rth, false);
              transformer.popCurrentMatched();
              continue;
            case DTM.DOCUMENT_NODE:
              template = sroot.getDefaultRootRule();
              break;
            default:

              // No default rules for processing instructions and the like.
              continue;
          }
        } else {
          transformer.setCurrentElement(template);
        }

        transformer.pushPairCurrentMatched(template, child);
        if (check) guard.checkForInfinateLoop();

        int currentFrameBottom; // See comment with unlink, below
        if (template.m_frameSize > 0) {
          xctxt.pushRTFContext();
          currentFrameBottom = vars.getStackFrame(); // See comment with unlink, below
          vars.link(template.m_frameSize);
          // You can't do the check for nParams here, otherwise the
          // xsl:params might not be nulled.
          if (
          /* nParams > 0 && */ template.m_inArgsSize > 0) {
            int paramIndex = 0;
            for (ElemTemplateElement elem = template.getFirstChildElem();
                null != elem;
                elem = elem.getNextSiblingElem()) {
              if (Constants.ELEMNAME_PARAMVARIABLE == elem.getXSLToken()) {
                ElemParam ep = (ElemParam) elem;

                int i;
                for (i = 0; i < nParams; i++) {
                  ElemWithParam ewp = m_paramElems[i];
                  if (ewp.m_qnameID == ep.m_qnameID) {
                    XObject obj = vars.getLocalVariable(i, argsFrame);
                    vars.setLocalVariable(paramIndex, obj);
                    break;
                  }
                }
                if (i == nParams) vars.setLocalVariable(paramIndex, null);
              } else break;
              paramIndex++;
            }
          }
        } else currentFrameBottom = 0;

        // Fire a trace event for the template.
        if (TransformerImpl.S_DEBUG) transformer.getTraceManager().fireTraceEvent(template);

        // And execute the child templates.
        // Loop through the children of the template, calling execute on
        // each of them.
        for (ElemTemplateElement t = template.m_firstChild; t != null; t = t.m_nextSibling) {
          xctxt.setSAXLocator(t);
          try {
            transformer.pushElemTemplateElement(t);
            t.execute(transformer);
          } finally {
            transformer.popElemTemplateElement();
          }
        }

        if (TransformerImpl.S_DEBUG) transformer.getTraceManager().fireTraceEndEvent(template);

        if (template.m_frameSize > 0) {
          // See Frank Weiss bug around 03/19/2002 (no Bugzilla report yet).
          // While unlink will restore to the proper place, the real position
          // may have been changed for xsl:with-param, so that variables
          // can be accessed.
          // of right now.
          // More:
          // When we entered this function, the current
          // frame buffer (cfb) index in the variable stack may
          // have been manually set.  If we just call
          // unlink(), however, it will restore the cfb to the
          // previous link index from the link stack, rather than
          // the manually set cfb.  So,
          // the only safe solution is to restore it back
          // to the same position it was on entry, since we're
          // really not working in a stack context here. (Bug4218)
          vars.unlink(currentFrameBottom);
          xctxt.popRTFContext();
        }

        transformer.popCurrentMatched();
      } // end while (DTM.NULL != (child = sourceNodes.nextNode()))
    } catch (SAXException se) {
      transformer.getErrorListener().fatalError(new TransformerException(se));
    } finally {
      if (TransformerImpl.S_DEBUG)
        transformer
            .getTraceManager()
            .fireSelectedEndEvent(
                sourceNode,
                this,
                "select",
                new XPath(m_selectExpression),
                new org.apache.xpath.objects.XNodeSet(sourceNodes));

      // Unlink to the original stack frame
      if (nParams > 0) vars.unlink(thisframe);
      xctxt.popSAXLocator();
      xctxt.popContextNodeList();
      transformer.popElemTemplateElement();
      xctxt.popCurrentExpressionNode();
      xctxt.popCurrentNode();
      sourceNodes.detach();
    }
  }