/**
   * 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 {

    String prefix;
    String namespace;
    String methName;

    String fullName = m_arg0.execute(xctxt).str();
    int indexOfNSSep = fullName.indexOf(':');

    if (indexOfNSSep < 0) {
      prefix = "";
      namespace = Constants.S_XSLNAMESPACEURL;
      methName = fullName;
    } else {
      prefix = fullName.substring(0, indexOfNSSep);
      namespace = xctxt.getNamespaceContext().getNamespaceForPrefix(prefix);
      if (null == namespace) return XBoolean.S_FALSE;
      methName = fullName.substring(indexOfNSSep + 1);
    }

    if (namespace.equals(Constants.S_XSLNAMESPACEURL)) {
      try {
        return Keywords.functionAvailable(methName) ? XBoolean.S_TRUE : XBoolean.S_FALSE;
      } catch (Exception e) {
        return XBoolean.S_FALSE;
      }
    } else {
      // dml
      ExtensionsProvider extProvider = (ExtensionsProvider) xctxt.getOwnerObject();
      return extProvider.functionAvailable(namespace, methName)
          ? XBoolean.S_TRUE
          : XBoolean.S_FALSE;
    }
  }
  /**
   * For support of literal objects in xpaths.
   *
   * @param xctxt The XPath execution context.
   * @return This object.
   * @throws javax.xml.transform.TransformerException
   */
  public XObject execute(XPathContext xctxt) throws javax.xml.transform.TransformerException {
    if (!m_doneEval) {
      this.m_transformer
          .getMsgMgr()
          .error(
              xctxt.getSAXLocator(),
              XSLTErrorResources.ER_REFERENCING_ITSELF,
              new Object[] {((ElemVariable) this.object()).getName().getLocalName()});
    }
    VariableStack vars = xctxt.getVarStack();

    // These three statements need to be combined into one operation.
    int currentFrame = vars.getStackFrame();
    //// vars.setStackFrame(m_varStackPos);

    ElemVariable velem = (ElemVariable) m_obj;
    try {
      m_doneEval = false;
      if (-1 != velem.m_frameSize) vars.link(velem.m_frameSize);
      XObject var = velem.getValue(m_transformer, m_context);
      m_doneEval = true;
      return var;
    } finally {
      // These two statements need to be combined into one operation.
      // vars.setStackFrame(currentFrame);

      if (-1 != velem.m_frameSize) vars.unlink(currentFrame);
    }
  }
示例#3
0
  /**
   * Create a NodeSetDTM, and copy the members of the given DTMIterator into it.
   *
   * @param iterator Iterator which yields Nodes to be made members of the new set.
   */
  public NodeSetDTM(NodeIterator iterator, XPathContext xctxt) {

    super();

    Node node;
    m_manager = xctxt.getDTMManager();

    while (null != (node = iterator.nextNode())) {
      int handle = xctxt.getDTMHandleFromNode(node);
      addNodeInDocOrder(handle, xctxt);
    }
  }
示例#4
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();
  }
示例#5
0
  /** Create a NodeSetDTM, and copy the members of the given DTMIterator into it. */
  public NodeSetDTM(NodeList nodeList, XPathContext xctxt) {

    super();

    m_manager = xctxt.getDTMManager();

    int n = nodeList.getLength();
    for (int i = 0; i < n; i++) {
      Node node = nodeList.item(i);
      int handle = xctxt.getDTMHandleFromNode(node);
      // Do not reorder or strip duplicate nodes from the given DOM nodelist
      addNode(handle); // addNodeInDocOrder(handle, xctxt);
    }
  }
示例#6
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();
  }
  /**
   * 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;
  }
示例#8
0
  /**
   * Return the XPathContext to be used for evaluating expressions.
   *
   * <p>If the child is nested withing a forEach tag its iteration context is used. Otherwise, a new
   * context is created based on an empty Document.
   *
   * @param child the tag whose context should be returned
   * @param pageContext the current page context
   * @return the XPath evaluation context
   */
  public static XPathContext getContext(Tag child, PageContext pageContext) {
    // if within a forEach tag, use its context
    ForEachTag forEachTag = (ForEachTag) TagSupport.findAncestorWithClass(child, ForEachTag.class);
    if (forEachTag != null) {
      return forEachTag.getContext();
    }

    // otherwise, create a new context referring to an empty document
    XPathContext context = new XPathContext(false);
    VariableStack variableStack = new JSTLVariableStack(pageContext);
    context.setVarStack(variableStack);
    int dtm = context.getDTMHandleFromNode(newEmptyDocument());
    context.pushCurrentNodeAndExpression(dtm, dtm);
    return context;
  }
示例#9
0
  /**
   * 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;
  }
示例#10
0
  /**
   * Sort given nodes
   *
   * @param xctxt The XPath runtime state for the sort.
   * @param keys Vector of sort keyx
   * @param sourceNodes Iterator of nodes to sort
   * @return iterator of sorted nodes
   * @throws TransformerException
   */
  public DTMIterator sortNodes(XPathContext xctxt, Vector keys, DTMIterator sourceNodes)
      throws TransformerException {

    NodeSorter sorter = new NodeSorter(xctxt);
    sourceNodes.setShouldCacheNodes(true);
    sourceNodes.runTo(-1);
    xctxt.pushContextNodeList(sourceNodes);

    try {
      sorter.sort(sourceNodes, keys, xctxt);
      sourceNodes.setCurrentPos(0);
    } finally {
      xctxt.popContextNodeList();
    }

    return sourceNodes;
  }
示例#11
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)
      throws javax.xml.transform.TransformerException {

    DTM dtm = xctxt.getDTM(context);
    short nodeType = dtm.getNodeType(context);

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

    int nodeBit = (m_whatToShow & (0x00000001 << (nodeType - 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)
  }
示例#12
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)
  /**
   * 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 {

    SubContextList subContextList = xctxt.getCurrentNodeList();
    int currentNode = DTM.NULL;

    if (null != subContextList) {
      if (subContextList instanceof PredicatedNodeTest) {
        LocPathIterator iter = ((PredicatedNodeTest) subContextList).getLocPathIterator();
        currentNode = iter.getCurrentContextNode();
      } else if (subContextList instanceof StepPattern) {
        throw new RuntimeException(
            XSLMessages.createMessage(XSLTErrorResources.ER_PROCESSOR_ERROR, null));
      }
    } else {
      // not predicate => ContextNode == CurrentNode
      currentNode = xctxt.getContextNode();
    }
    return new XNodeSet(currentNode, xctxt.getDTMManager());
  }
  public XNodeSetForDOM(NodeIterator nodeIter, XPathContext xctxt) {
    m_dtmMgr = xctxt.getDTMManager();
    m_origObj = nodeIter;

    // JKESS 20020514: Longer-term solution is to force
    // folks to request length through an accessor, so we can defer this
    // retrieval... but that requires an API change.
    // m_obj = new org.apache.xpath.NodeSetDTM(nodeIter, xctxt);
    org.apache.xpath.NodeSetDTM nsdtm = new org.apache.xpath.NodeSetDTM(nodeIter, xctxt);
    m_last = nsdtm.getLength();
    m_obj = nsdtm;
  }
示例#15
0
  /**
   * Evaluate XPath string to an XObject. XPath namespace prefixes are resolved from the
   * namespaceNode. The implementation of this is a little slow, since it creates a number of
   * objects each time it is called. This could be optimized to keep the same objects around, but
   * then thread-safety issues would arise.
   *
   * @param contextNode The node to start searching from.
   * @param xpathnode
   * @param str
   * @param namespaceNode The node from which prefixes in the XPath will be resolved to namespaces.
   * @return An XObject, which can be used to obtain a string, number, nodelist, etc, should never
   *     be null.
   * @see org.apache.xpath.objects.XObject
   * @see org.apache.xpath.objects.XNull
   * @see org.apache.xpath.objects.XBoolean
   * @see org.apache.xpath.objects.XNumber
   * @see org.apache.xpath.objects.XString
   * @see org.apache.xpath.objects.XRTreeFrag
   * @throws TransformerException
   */
  public XObject eval(Node contextNode, Node xpathnode, String str, Node namespaceNode)
      throws TransformerException {
    //  Create the XPath object.
    // String str = CachedXPathFuncHereAPI.getStrFromNode(xpathnode);

    // Since we don't have a XML Parser involved here, install some default support
    // for things like namespaces, etc.
    // (Changed from: XPathContext xpathSupport = new XPathContext();
    //    because XPathContext is weak in a number of areas... perhaps
    //    XPathContext should be done away with.)
    if (this._funcHereContext == null) {
      this._funcHereContext = new FuncHereContext(xpathnode, this._dtmManager);
    }

    // Create an object to resolve namespace prefixes.
    // XPath namespaces are resolved from the input context node's document element
    // if it is a root node, or else the current context node (for lack of a better
    // resolution space, given the simplicity of this sample code).
    PrefixResolverDefault prefixResolver =
        new PrefixResolverDefault(
            (namespaceNode.getNodeType() == Node.DOCUMENT_NODE)
                ? ((Document) namespaceNode).getDocumentElement()
                : namespaceNode);

    // only check if string points to different object (for performance)
    if (str != xpathStr) {
      if (str.indexOf("here()") > 0) {
        _context.reset();
        _dtmManager = _context.getDTMManager();
      }
      xpath = createXPath(str, prefixResolver);
      xpathStr = str;
    }

    // Execute the XPath, and have it return the result
    // return xpath.execute(xpathSupport, contextNode, prefixResolver);
    int ctxtNode = this._funcHereContext.getDTMHandleFromNode(contextNode);

    return xpath.execute(this._funcHereContext, ctxtNode, prefixResolver);
  }
示例#16
0
  /**
   * Evaluate XPath string to an XObject. XPath namespace prefixes are resolved from the
   * namespaceNode. The implementation of this is a little slow, since it creates a number of
   * objects each time it is called. This could be optimized to keep the same objects around, but
   * then thread-safety issues would arise.
   *
   * @param contextNode The node to start searching from.
   * @param xpathnode
   * @param str
   * @param prefixResolver Will be called if the parser encounters namespace prefixes, to resolve
   *     the prefixes to URLs.
   * @return An XObject, which can be used to obtain a string, number, nodelist, etc, should never
   *     be null.
   * @see org.apache.xpath.objects.XObject
   * @see org.apache.xpath.objects.XNull
   * @see org.apache.xpath.objects.XBoolean
   * @see org.apache.xpath.objects.XNumber
   * @see org.apache.xpath.objects.XString
   * @see org.apache.xpath.objects.XRTreeFrag
   * @throws TransformerException
   */
  public XObject eval(Node contextNode, Node xpathnode, String str, PrefixResolver prefixResolver)
      throws TransformerException {

    // Since we don't have a XML Parser involved here, install some default support
    // for things like namespaces, etc.
    // (Changed from: XPathContext xpathSupport = new XPathContext();
    //    because XPathContext is weak in a number of areas... perhaps
    //    XPathContext should be done away with.)
    // Create the XPath object.
    // String str = CachedXPathFuncHereAPI.getStrFromNode(xpathnode);
    // only check if string points to different object (for performance)
    if (str != xpathStr) {
      if (str.indexOf("here()") > 0) {
        _context.reset();
        _dtmManager = _context.getDTMManager();
      }
      try {
        xpath = createXPath(str, prefixResolver);
      } catch (TransformerException ex) {
        // Try to see if it is a problem with the classloader.
        Throwable th = ex.getCause();
        if (th instanceof ClassNotFoundException) {
          if (th.getMessage().indexOf("FuncHere") > 0) {
            throw new RuntimeException(I18n.translate("endorsed.jdk1.4.0") /*,*/ + ex);
          }
        }
        throw ex;
      }
      xpathStr = str;
    }

    // Execute the XPath, and have it return the result
    if (this._funcHereContext == null) {
      this._funcHereContext = new FuncHereContext(xpathnode, this._dtmManager);
    }

    int ctxtNode = this._funcHereContext.getDTMHandleFromNode(contextNode);

    return xpath.execute(this._funcHereContext, ctxtNode, prefixResolver);
  }
示例#17
0
  /**
   * Get a local variable or parameter in the current stack frame.
   *
   * @param xctxt The XPath context, which must be passed in order to lazy evaluate variables.
   * @param index Local variable index relative to the current stack frame bottom.
   * @return The value of the variable.
   * @throws TransformerException
   */
  public XObject getLocalVariable(XPathContext xctxt, int index) throws TransformerException {

    index += _currentFrameBottom;

    XObject val = _stackFrames[index];

    if (null == val)
      throw new TransformerException(
          XSLMessages.createXPATHMessage(
              XPATHErrorResources.ER_VARIABLE_ACCESSED_BEFORE_BIND, null),
          xctxt.getSAXLocator());
    // "Variable accessed before it is bound!", xctxt.getSAXLocator());

    // Lazy execution of variables.
    if (val.getType() == XObject.CLASS_UNRESOLVEDVARIABLE)
      return (_stackFrames[index] = val.execute(xctxt));

    return val;
  }
示例#18
0
  /**
   * Get a variable based on it's qualified name. This is for external use only.
   *
   * @param xctxt The XPath context, which must be passed in order to lazy evaluate variables.
   * @param qname The qualified name of the variable.
   * @return The evaluated value of the variable.
   * @throws javax.xml.transform.TransformerException
   */
  public XObject getVariableOrParam(XPathContext xctxt, org.apache.xml.utils.QName qname)
      throws javax.xml.transform.TransformerException {

    org.apache.xml.utils.PrefixResolver prefixResolver = xctxt.getNamespaceContext();

    // Get the current ElemTemplateElement, which must be pushed in as the
    // prefix resolver, and then walk backwards in document order, searching
    // for an xsl:param element or xsl:variable element that matches our
    // qname.  If we reach the top level, use the StylesheetRoot's composed
    // list of top level variables and parameters.

    if (prefixResolver instanceof org.apache.xalan.templates.ElemTemplateElement) {

      org.apache.xalan.templates.ElemVariable vvar;

      org.apache.xalan.templates.ElemTemplateElement prev =
          (org.apache.xalan.templates.ElemTemplateElement) prefixResolver;

      if (!(prev instanceof org.apache.xalan.templates.Stylesheet)) {
        while (!(prev.getParentNode() instanceof org.apache.xalan.templates.Stylesheet)) {
          org.apache.xalan.templates.ElemTemplateElement savedprev = prev;

          while (null != (prev = prev.getPreviousSiblingElem())) {
            if (prev instanceof org.apache.xalan.templates.ElemVariable) {
              vvar = (org.apache.xalan.templates.ElemVariable) prev;

              if (vvar.getName().equals(qname)) return getLocalVariable(xctxt, vvar.getIndex());
            }
          }
          prev = savedprev.getParentElem();
        }
      }

      vvar = prev.getStylesheetRoot().getVariableOrParamComposed(qname);
      if (null != vvar) return getGlobalVariable(xctxt, vvar.getIndex());
    }

    throw new javax.xml.transform.TransformerException(
        XSLMessages.createXPATHMessage(
            XPATHErrorResources.ER_VAR_NOT_RESOLVABLE,
            new Object[] {qname.toString()})); // "Variable not resolvable: " + qname);
  }
示例#19
0
  /**
   * Execute the first argument expression that is expected to return a nodeset. If the argument is
   * null, then return the current context node.
   *
   * @param xctxt Runtime XPath context.
   * @return The first node of the executed nodeset, or 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 int getArg0AsNode(XPathContext xctxt) throws javax.xml.transform.TransformerException {

    return (null == m_arg0) ? xctxt.getCurrentNode() : m_arg0.asNode(xctxt);
  }
示例#20
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+"'");
    }
  }
示例#21
0
  /**
   * 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 {

    String fullName = m_arg0.execute(xctxt).str();
    int indexOfNSSep = fullName.indexOf(':');
    String result = null;
    String propName = "";

    // List of properties where the name of the
    // property argument is to be looked for.
    Properties xsltInfo = new Properties();

    loadPropertyFile(XSLT_PROPERTIES, xsltInfo);

    if (indexOfNSSep > 0) {
      String prefix = (indexOfNSSep >= 0) ? fullName.substring(0, indexOfNSSep) : "";
      String namespace;

      namespace = xctxt.getNamespaceContext().getNamespaceForPrefix(prefix);
      propName = (indexOfNSSep < 0) ? fullName : fullName.substring(indexOfNSSep + 1);

      if (namespace.startsWith("http://www.w3.org/XSL/Transform")
          || namespace.equals("http://www.w3.org/1999/XSL/Transform")) {
        result = xsltInfo.getProperty(propName);

        if (null == result) {
          warn(
              xctxt,
              XPATHErrorResources.WG_PROPERTY_NOT_SUPPORTED,
              new Object[] {fullName}); // "XSL Property not supported: "+fullName);

          return XString.EMPTYSTRING;
        }
      } else {
        warn(
            xctxt,
            XPATHErrorResources.WG_DONT_DO_ANYTHING_WITH_NS,
            new Object[] {
              namespace, fullName
            }); // "Don't currently do anything with namespace "+namespace+" in property:
        // "+fullName);

        try {
          // if secure procession is enabled only handle required properties do not not map any
          // valid system property
          if (!xctxt.isSecureProcessing()) {
            result = System.getProperty(propName);
          } else {
            warn(
                xctxt,
                XPATHErrorResources.WG_SECURITY_EXCEPTION,
                new Object[] {
                  fullName
                }); // "SecurityException when trying to access XSL system property: "+fullName);
          }
          if (null == result) {
            return XString.EMPTYSTRING;
          }
        } catch (SecurityException se) {
          warn(
              xctxt,
              XPATHErrorResources.WG_SECURITY_EXCEPTION,
              new Object[] {
                fullName
              }); // "SecurityException when trying to access XSL system property: "+fullName);

          return XString.EMPTYSTRING;
        }
      }
    } else {
      try {
        // if secure procession is enabled only handle required properties do not not map any valid
        // system property
        if (!xctxt.isSecureProcessing()) {
          result = System.getProperty(fullName);
        } else {
          warn(
              xctxt,
              XPATHErrorResources.WG_SECURITY_EXCEPTION,
              new Object[] {
                fullName
              }); // "SecurityException when trying to access XSL system property: "+fullName);
        }
        if (null == result) {
          return XString.EMPTYSTRING;
        }
      } catch (SecurityException se) {
        warn(
            xctxt,
            XPATHErrorResources.WG_SECURITY_EXCEPTION,
            new Object[] {
              fullName
            }); // "SecurityException when trying to access XSL system property: "+fullName);

        return XString.EMPTYSTRING;
      }
    }

    if (propName.equals("version") && result.length() > 0) {
      try {
        // Needs to return the version number of the spec we conform to.
        return new XString("1.0");
      } catch (Exception ex) {
        return new XString(result);
      }
    } else return new XString(result);
  }
  /**
   * <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();
    }
  }
示例#23
0
 /**
  * Return the first node out of the nodeset, if this expression is a nodeset expression. This is
  * the default implementation for nodesets. Derived classes should try and override this and
  * return a value without having to do a clone operation.
  *
  * @param xctxt The XPath runtime context.
  * @return the first node out of the nodeset, or DTM.NULL.
  */
 public int asNode(XPathContext xctxt) throws javax.xml.transform.TransformerException {
   return xctxt.getCurrentNode();
 }
示例#24
0
 /**
  * Test the current node to see if it matches the given node test.
  *
  * @param xctxt XPath runtime context.
  * @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) throws javax.xml.transform.TransformerException {
   return execute(xctxt, xctxt.getCurrentNode());
 }
示例#25
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();
    }
  }
示例#26
0
  /**
   * Extension element for piping an XML document through a series of 1 or more transformations.
   *
   * <pre>Common usage pattern: A stylesheet transforms a listing of documents to be
   * transformed into a TOC. For each document in the listing calls the pipeDocument
   * extension element to pipe that document through a series of 1 or more stylesheets
   * to the desired output document.
   *
   * Syntax:
   * &lt;xsl:stylesheet version="1.0"
   *                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
   *                xmlns:pipe="http://xml.apache.org/xalan/PipeDocument"
   *                extension-element-prefixes="pipe"&gt;
   * ...
   * &lt;pipe:pipeDocument   source="source.xml" target="target.xml"&gt;
   *   &lt;stylesheet href="ss1.xsl"&gt;
   *     &lt;param name="param1" value="value1"/&gt;
   *   &lt;/stylesheet&gt;
   *   &lt;stylesheet href="ss2.xsl"&gt;
   *     &lt;param name="param1" value="value1"/&gt;
   *     &lt;param name="param2" value="value2"/&gt;
   *   &lt;/stylesheet&gt;
   *   &lt;stylesheet href="ss1.xsl"/&gt;
   * &lt;/pipe:pipeDocument&gt;
   *
   * Notes:</pre>
   *
   * <ul>
   *   <li>The base URI for the source attribute is the XML "listing" document.
   *   <li/>
   *   <li>The target attribute is taken as is (base is the current user directory).
   *   <li/>
   *   <li>The stylsheet containg the extension element is the base URI for the stylesheet hrefs.
   *   <li/>
   * </ul>
   */
  public void pipeDocument(XSLProcessorContext context, ElemExtensionCall elem)
      throws TransformerException, TransformerConfigurationException, SAXException, IOException,
          FileNotFoundException {

    SAXTransformerFactory saxTFactory = (SAXTransformerFactory) TransformerFactory.newInstance();

    // XML doc to transform.
    String source = elem.getAttribute("source", context.getContextNode(), context.getTransformer());
    TransformerImpl transImpl = context.getTransformer();

    // Base URI for input doc, so base for relative URI to XML doc to transform.
    String baseURLOfSource = transImpl.getBaseURLOfSource();
    // Absolute URI for XML doc to transform.
    String absSourceURL = SystemIDResolver.getAbsoluteURI(source, baseURLOfSource);

    // Transformation target
    String target = elem.getAttribute("target", context.getContextNode(), context.getTransformer());

    XPathContext xctxt = context.getTransformer().getXPathContext();
    int xt = xctxt.getDTMHandleFromNode(context.getContextNode());

    // Get System Id for stylesheet; to be used to resolve URIs to other stylesheets.
    String sysId = elem.getSystemId();

    NodeList ssNodes = null;
    NodeList paramNodes = null;
    Node ssNode = null;
    Node paramNode = null;
    if (elem.hasChildNodes()) {
      ssNodes = elem.getChildNodes();
      // Vector to contain TransformerHandler for each stylesheet.
      Vector vTHandler = new Vector(ssNodes.getLength());

      // The child nodes of an extension element node are instances of
      // ElemLiteralResult, which requires does not fully support the standard
      // Node interface. Accordingly, some special handling is required (see below)
      // to get attribute values.
      for (int i = 0; i < ssNodes.getLength(); i++) {
        ssNode = ssNodes.item(i);
        if (ssNode.getNodeType() == Node.ELEMENT_NODE
            && ((Element) ssNode).getTagName().equals("stylesheet")
            && ssNode instanceof ElemLiteralResult) {
          AVT avt = ((ElemLiteralResult) ssNode).getLiteralResultAttribute("href");
          String href = avt.evaluate(xctxt, xt, elem);
          String absURI = SystemIDResolver.getAbsoluteURI(href, sysId);
          Templates tmpl = saxTFactory.newTemplates(new StreamSource(absURI));
          TransformerHandler tHandler = saxTFactory.newTransformerHandler(tmpl);
          Transformer trans = tHandler.getTransformer();

          // AddTransformerHandler to vector
          vTHandler.addElement(tHandler);

          paramNodes = ssNode.getChildNodes();
          for (int j = 0; j < paramNodes.getLength(); j++) {
            paramNode = paramNodes.item(j);
            if (paramNode.getNodeType() == Node.ELEMENT_NODE
                && ((Element) paramNode).getTagName().equals("param")
                && paramNode instanceof ElemLiteralResult) {
              avt = ((ElemLiteralResult) paramNode).getLiteralResultAttribute("name");
              String pName = avt.evaluate(xctxt, xt, elem);
              avt = ((ElemLiteralResult) paramNode).getLiteralResultAttribute("value");
              String pValue = avt.evaluate(xctxt, xt, elem);
              trans.setParameter(pName, pValue);
            }
          }
        }
      }
      usePipe(vTHandler, absSourceURL, target);
    }
  }
示例#27
0
 /**
  * Constructor CachedXPathFuncHereAPI
  *
  * @param existingXPathContext
  */
 public CachedXPathFuncHereAPI(XPathContext existingXPathContext) {
   this._dtmManager = existingXPathContext.getDTMManager();
   this._context = existingXPathContext;
 }
示例#28
0
  /**
   * 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;
  }
示例#29
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);
    }
  }