/**
   * Execute a variable declaration and push it onto the variable stack.
   *
   * @see <a href="http://www.w3.org/TR/xslt#variables">variables in XSLT Specification</a>
   * @param transformer non-null reference to the the current transform-time state.
   * @throws javax.xml.transform.TransformerException
   */
  public void execute(TransformerImpl transformer) throws TransformerException {

    if (transformer.getDebug()) transformer.getTraceManager().fireTraceEvent(this);

    int sourceNode = transformer.getXPathContext().getCurrentNode();

    XObject var = getValue(transformer, sourceNode);

    // transformer.getXPathContext().getVarStack().pushVariable(m_qname, var);
    transformer.getXPathContext().getVarStack().setLocalVariable(m_index, var);

    if (transformer.getDebug()) transformer.getTraceManager().fireTraceEndEvent(this);
  }
  /**
   * Get the XObject representation of the variable.
   *
   * @param transformer non-null reference to the the current transform-time state.
   * @param sourceNode non-null reference to the <a
   *     href="http://www.w3.org/TR/xslt#dt-current-node">current source node</a>.
   * @return the XObject representation of the variable.
   * @throws javax.xml.transform.TransformerException
   */
  public XObject getValue(TransformerImpl transformer, int sourceNode) throws TransformerException {

    XObject var;
    XPathContext xctxt = transformer.getXPathContext();

    xctxt.pushCurrentNode(sourceNode);

    try {
      if (null != m_selectPattern) {
        var = m_selectPattern.execute(xctxt, sourceNode, this);

        var.allowDetachToRelease(false);

        if (transformer.getDebug())
          transformer
              .getTraceManager()
              .fireSelectedEvent(sourceNode, this, "select", m_selectPattern, var);
      } else if (null == getFirstChildElem()) {
        var = XString.EMPTYSTRING;
      } else {

        // Use result tree fragment.
        // Global variables may be deferred (see XUnresolvedVariable) and hence
        // need to be assigned to a different set of DTMs than local variables
        // so they aren't popped off the stack on return from a template.
        int df;

        // Bugzilla 7118: A variable set via an RTF may create local
        // variables during that computation. To keep them from overwriting
        // variables at this level, push a new variable stack.
        ////// PROBLEM: This is provoking a variable-used-before-set
        ////// problem in parameters. Needs more study.
        try {
          ////////// xctxt.getVarStack().link(0);
          if (m_parentNode instanceof Stylesheet) // Global variable
          df = transformer.transformToGlobalRTF(this);
          else df = transformer.transformToRTF(this);
        } finally {
          ////////////// xctxt.getVarStack().unlink();
        }

        var = new XRTreeFrag(df, xctxt, this);
      }
    } finally {
      xctxt.popCurrentNode();
    }

    return var;
  }
Example #3
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();
    }
  }
Example #4
0
  /**
   * Copy a Literal Result Element into the Result tree, copy the non-excluded namespace attributes,
   * copy the attributes not of the XSLT namespace, and execute the children of the LRE.
   *
   * @see <a href="http://www.w3.org/TR/xslt#literal-result-element">literal-result-element in XSLT
   *     Specification</a>
   * @param transformer non-null reference to the the current transform-time state.
   * @throws TransformerException
   */
  public void execute(TransformerImpl transformer) throws TransformerException {
    SerializationHandler rhandler = transformer.getSerializationHandler();

    try {

      // JJK Bugzilla 3464, test namespace85 -- make sure LRE's
      // namespace is asserted even if default, since xsl:element
      // may have changed the context.
      rhandler.startPrefixMapping(getPrefix(), getNamespace());

      // Add namespace declarations.
      executeNSDecls(transformer);
      rhandler.startElement(getNamespace(), getLocalName(), getRawName());
    } catch (SAXException se) {
      throw new TransformerException(se);
    }

    /*
     * If we make it to here we have done a successful startElement()
     * we will do an endElement() call for balance, no matter what happens
     * in the middle.
     */

    // tException remembers if we had an exception "in the middle"
    TransformerException tException = null;
    try {

      // Process any possible attributes from xsl:use-attribute-sets first
      super.execute(transformer);

      // xsl:version, excludeResultPrefixes???
      // Process the list of avts next
      if (null != m_avts) {
        int nAttrs = m_avts.size();

        for (int i = (nAttrs - 1); i >= 0; i--) {
          AVT avt = (AVT) m_avts.get(i);
          XPathContext xctxt = transformer.getXPathContext();
          int sourceNode = xctxt.getCurrentNode();
          String stringedValue = avt.evaluate(xctxt, sourceNode, this);

          if (null != stringedValue) {

            // Important Note: I'm not going to check for excluded namespace
            // prefixes here.  It seems like it's too expensive, and I'm not
            // even sure this is right.  But I could be wrong, so this needs
            // to be tested against other implementations.

            rhandler.addAttribute(
                avt.getURI(), avt.getName(), avt.getRawName(), "CDATA", stringedValue, false);
          }
        } // end for
      }

      // Now process all the elements in this subtree
      // TODO: Process m_extensionElementPrefixes && m_attributeSetsNames
      transformer.executeChildTemplates(this, true);
    } catch (TransformerException te) {
      // thrown in finally to prevent original exception consumed by subsequent exceptions
      tException = te;
    } catch (SAXException se) {
      tException = new TransformerException(se);
    }

    try {
      /* we need to do this endElement() to balance the
       * successful startElement() call even if
       * there was an exception in the middle.
       * Otherwise an exception in the middle could cause a system to hang.
       */
      rhandler.endElement(getNamespace(), getLocalName(), getRawName());
    } catch (SAXException se) {
      /* we did call endElement(). If thee was an exception
       * in the middle throw that one, otherwise if there
       * was an exception from endElement() throw that one.
       */
      if (tException != null) throw tException;
      else throw new TransformerException(se);
    }

    /* If an exception was thrown in the middle but not with startElement() or
     * or endElement() then its time to let it percolate.
     */
    if (tException != null) throw tException;

    unexecuteNSDecls(transformer);

    // JJK Bugzilla 3464, test namespace85 -- balance explicit start.
    try {
      rhandler.endPrefixMapping(getPrefix());
    } catch (SAXException se) {
      throw new TransformerException(se);
    }
  }
  /**
   * <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();
    }
  }
Example #6
0
  /**
   * Invoke a named template.
   *
   * @see <a href="http://www.w3.org/TR/xslt#named-templates">named-templates in XSLT
   *     Specification</a>
   * @param transformer non-null reference to the the current transform-time state.
   * @throws TransformerException
   */
  public void execute(TransformerImpl transformer) throws TransformerException {

    if (null != m_template) {
      XPathContext xctxt = transformer.getXPathContext();
      VariableStack vars = xctxt.getVarStack();

      int thisframe = vars.getStackFrame();
      int nextFrame = vars.link(m_template.m_frameSize);

      // We have to clear the section of the stack frame that has params
      // so that the default param evaluation will work correctly.
      if (m_template.m_inArgsSize > 0) {
        vars.clearLocalSlots(0, m_template.m_inArgsSize);

        if (null != m_paramElems) {
          int currentNode = xctxt.getCurrentNode();
          vars.setStackFrame(thisframe);
          int size = m_paramElems.length;

          for (int i = 0; i < size; i++) {
            ElemWithParam ewp = m_paramElems[i];
            if (ewp.m_index >= 0) {
              XObject obj = ewp.getValue(transformer, currentNode);

              // Note here that the index for ElemWithParam must have been
              // statically made relative to the xsl:template being called,
              // NOT this xsl:template.
              vars.setLocalVariable(ewp.m_index, obj, nextFrame);
            }
          }
          vars.setStackFrame(nextFrame);
        }
      }

      SourceLocator savedLocator = xctxt.getSAXLocator();

      try {
        xctxt.setSAXLocator(m_template);

        // template.executeChildTemplates(transformer, sourceNode, mode, true);
        transformer.pushElemTemplateElement(m_template);
        m_template.execute(transformer);
      } finally {
        transformer.popElemTemplateElement();
        xctxt.setSAXLocator(savedLocator);
        // 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(thisframe);
      }
    } else {
      transformer
          .getMsgMgr()
          .error(
              this,
              XSLTErrorResources.ER_TEMPLATE_NOT_FOUND,
              new Object[] {
                m_templateName
              }); // "Could not find template named: '"+templateName+"'");
    }
  }