    /*
     * call-seq:
     *  [index] -> Node or nil
     *  [start, length] -> NodeSet or nil
     *  [range] -> NodeSet or nil
     *  slice(index) -> Node or nil
     *  slice(start, length) -> NodeSet or nil
     *  slice(range) -> NodeSet or nil
     *
     * Element reference - returns the node at +index+, or returns a NodeSet
     * containing nodes starting at +start+ and continuing for +length+ elements, or
     * returns a NodeSet containing nodes specified by +range+. Negative +indices+
     * count backward from the end of the +node_set+ (-1 is the last node). Returns
     * nil if the +index+ (or +start+) are out of range.
     */
    static VALUE slice(int argc, VALUE *argv, VALUE self)
    {
      VALUE arg ;
      long beg, len ;
      xmlNodeSetPtr node_set;
      Data_Get_Struct(self, xmlNodeSet, node_set);

      if (argc == 2) {
        beg = NUM2LONG(argv[0]);
        len = NUM2LONG(argv[1]);
        if (beg < 0) {
          beg += node_set->nodeNr ;
        }
        return subseq(self, beg, len);
      }

      if (argc != 1) {
        rb_scan_args(argc, argv, "11", NULL, NULL);
      }
      arg = argv[0];

      if (FIXNUM_P(arg)) {
        return index_at(self, FIX2LONG(arg));
      }

      /* if arg is Range */
      switch (rb_range_beg_len(arg, &beg, &len, (long)node_set->nodeNr, 0)) {
      case Qfalse:
        break;
      case Qnil:
        return Qnil;
      default:
        return subseq(self, beg, len);
      }

      return index_at(self, NUM2LONG(arg));
    }