Hot-swapping dependencies is not the only goal of using a DI Container.
Dependency Injection (DI) is a principle that helps us develop loosely coupled code. Loose coupling only means that we can vary consumer and service independently of each other. How we achieve this is not addressed at this level.
DI Containers are frameworks that help use wire dependencies together. They are more or less just utility libraries that help us apply DI patterns. Once again, how we configure a container is perpendicular to how we consume those dependencies.
XML configurations allows us to change the container configuration without recompilation. Code as configuration doesn’t.
However, swapping dependencies without recompilation is typically only relevant for a small subset of all your loosely coupled code. For the rest, a convention-based approach is much more effective, because it tends to be less brittle. See here for more information.