Using the PORTB interrupt on change feature with XC8
One thing that would help (and is definitely best practise) would be to check what is causing the interrupt.  You should also be writing to the latch (LATx register) on an 18F and you need to disable analogue functions.

Sample code for this might look like:

#define LED_OUTPUT LATC3

void main(void) {
    // .. other setup here .. 

    // Disable analogue functions
    ADCON1 |= 0b0011;

    // .. interrupt setup ..
}

void interrupt isr(void) {

    // Was it the port B interrupt on change?
    if (INTCONbits.RBIF) {
        // Dummy read of the port, as per datasheet
        if (PORTB) {
            asm("nop");
        }

        // Use XOR to toggle the pin, saving a variable
        LED_OUTPUT ^= 1;

        // Reset the interrupt flag
        INTCONbits.RBIF = 0;
    }
}


To use the interrupt-on-change feature with a specific input pin is a bit harder, but you could check in the ISR whether the current input value is 0 or 1 (whichever is most relevant).  Don't forget to debounce your switch also, either in hardware or in software.

PORTB mismatch condition

Note this cryptic portion of the datasheet in section 9.1 "INTCON Registers" regarding the RBIF bit:


  Note 1: A mismatch condition will continue to set this bit. Reading
  PORTB will end the mismatch condition and allow the bit to be cleared.


In order to stop your code getting stuck in the ISR (repeatedly setting RBIF) you should read the port in your ISR even if you do nothing with the value.  The code sample above shows this.

(note I found this answer which is about the same thing)

Errata

The errata for your device is another excellent place to go.  Here's the errata for the 18F2520, however in this case there don't seem to be any relating to interrupts or the data ports.

Special functions

You might also need to disable other special functions on PORTB.  Specifically the analogue functions, which always need to be disabled if you are using the pin as a digital input.

// Make just AN12 (on pin B0) a digital input
ADCON1 |= 0b0011;

// Make all external pins digital inputs
ADCON1 |= 0b1111;


Alternative interrupt mechanisms

Note that on the 18F2520 you have three dedicated external interrupts available as INT0 to INT2.  These map to pins B0 to B2.  See section 9.6 "INTx Pin Interrupts" where we find the following:


  External interrupts on the RB0/INT0, RB1/INT1 and RB2/INT2 pins are
  edge-triggered. If the corresponding INTEDGx bit in the INTCON2
  register is set (= 1), the interrupt is triggered by a rising edge; if
  the bit is clear, the trigger is on the falling edge.


You could use the INT0 interrupt instead, which means you are not depending on the values  from all of PORTB.  Because they are edge triggered you will get less spurious interrupts, but you will still need to debounce the switch.