/**
   * Get a DTM to be used as a container for a dynamic Result Tree Fragment. This will always be an
   * instance of (derived from? equivalent to?) SAX2DTM, since each RTF is constructed by
   * temporarily redirecting our SAX output to it. It may be a single DTM containing for multiple
   * fragments, if the implementation supports that.
   *
   * @return a non-null DTM reference.
   */
  public DTM getRTFDTM() {
    SAX2RTFDTM rtfdtm;

    // We probably should _NOT_ be applying whitespace filtering at this stage!
    //
    // Some magic has been applied in DTMManagerDefault to recognize this set of options
    // and generate an instance of DTM which can contain multiple documents
    // (SAX2RTFDTM). Perhaps not the optimal way of achieving that result, but
    // I didn't want to change the manager API at this time, or expose
    // too many dependencies on its internals. (Ideally, I'd like to move
    // isTreeIncomplete all the way up to DTM, so we wouldn't need to explicitly
    // specify the subclass here.)

    if (m_rtfdtm_stack == null) {
      m_rtfdtm_stack = new Vector();
      rtfdtm = (SAX2RTFDTM) m_dtmManager.getDTM(null, true, null, false, false);
      m_rtfdtm_stack.addElement(rtfdtm);
      ++m_which_rtfdtm;
    } else if (m_which_rtfdtm < 0) {
      rtfdtm = (SAX2RTFDTM) m_rtfdtm_stack.elementAt(++m_which_rtfdtm);
    } else {
      rtfdtm = (SAX2RTFDTM) m_rtfdtm_stack.elementAt(m_which_rtfdtm);

      // It might already be under construction -- the classic example would be
      // an xsl:variable which uses xsl:call-template as part of its value. To
      // handle this recursion, we have to start a new RTF DTM, pushing the old
      // one onto a stack so we can return to it. This is not as uncommon a case
      // as we might wish, unfortunately, as some folks insist on coding XSLT
      // as if it were a procedural language...
      if (rtfdtm.isTreeIncomplete()) {
        if (++m_which_rtfdtm < m_rtfdtm_stack.size())
          rtfdtm = (SAX2RTFDTM) m_rtfdtm_stack.elementAt(m_which_rtfdtm);
        else {
          rtfdtm = (SAX2RTFDTM) m_dtmManager.getDTM(null, true, null, false, false);
          m_rtfdtm_stack.addElement(rtfdtm);
        }
      }
    }

    return rtfdtm;
  }
  /**
   * Get a DTM to be used as a container for a global Result Tree Fragment. This will always be an
   * instance of (derived from? equivalent to?) SAX2DTM, since each RTF is constructed by
   * temporarily redirecting our SAX output to it. It may be a single DTM containing for multiple
   * fragments, if the implementation supports that.
   *
   * <p>Note: The distinction between this method and getRTFDTM() is that the latter allocates space
   * from the dynamic variable stack (m_rtfdtm_stack), which may be pruned away again as the
   * templates which defined those variables are exited. Global variables may be bound late (see
   * XUnresolvedVariable), and never want to be discarded, hence we need to allocate them separately
   * and don't actually need a stack to track them.
   *
   * @return a non-null DTM reference.
   */
  public DTM getGlobalRTFDTM() {
    // We probably should _NOT_ be applying whitespace filtering at this stage!
    //
    // Some magic has been applied in DTMManagerDefault to recognize this set of options
    // and generate an instance of DTM which can contain multiple documents
    // (SAX2RTFDTM). Perhaps not the optimal way of achieving that result, but
    // I didn't want to change the manager API at this time, or expose
    // too many dependencies on its internals. (Ideally, I'd like to move
    // isTreeIncomplete all the way up to DTM, so we wouldn't need to explicitly
    // specify the subclass here.)

    // If it doesn't exist, or if the one already existing is in the middle of
    // being constructed, we need to obtain a new DTM to write into. I'm not sure
    // the latter will ever arise, but I'd rather be just a bit paranoid..
    if (m_global_rtfdtm == null || m_global_rtfdtm.isTreeIncomplete()) {
      m_global_rtfdtm = (SAX2RTFDTM) m_dtmManager.getDTM(null, true, null, false, false);
    }
    return m_global_rtfdtm;
  }