Hi Virgil,
Our group faced the same problem and came up with an approach that gives us a lot of flexibility at run time, but is a bit complicated to put together. We use Selenium so I'll speak in those terms, but even if you're not, this idea should work with other frameworks.
Because we didn't want to be in the business of managing xml files, we chose to configure each run dynamically at run time using either command line parameters, or through a single config file. Here's the basics...
We have a testConfig file--a simple properties file--where people can set values for how they want to execute the test run: browser, platform, browser version, languages, etc. These values act as a fallback if someone doesn't set something specifically. We then have a configuration class that checks for system properties (cmd parameters) and sets its values if it finds any we're concerned about, and if not, it reads values from the testConfig. We end up with a single object with all the configuration details for a particular run.
Next we have a "base" test class that instantiates the config object, and from the config object parameters it does two things. First it parses the config values and builds an array of all the combinations between browser/platform/browser version/language which is used to create a data provider. Second it creates Selenium drivers for the combinations. The final piece is that all our test classes extend the "base" test class and use a Factory to create an instances of the test class for every combination in the data provider.
Essentially this lets us parameterize test runs on the fly. We use this approach to manage a lot of things: environment to test against, what flags to use to get to features under development, languages to run the tests, browsers and versions to use, how many times to retry failures, whether to run in a local browser or use a grid, what groups to use, setting the implicit time out, and a handful of other things specific to our landscape. We use Jenkins a lot so this makes configuring jobs a piece of cake.
The key points are: Have simple way to dynamically set the key configuration points; Have a base class that handles as much of the test class set up as it possibly can and have it build a data provider with all your combinations; Test classes that extend the base class and are parameterized by the data provider.
Hope that helps, or at least gives you something to consider.
R