I think I finally figured out precisely how we should end up with civics and how to enter the different types
We have 4 XML files, one for each of civics, inventions, traits and FFs. More can easily be added if needed.
Each file has it's own schema. This allows for unique setup. For instance inventions have to enter a location in the tech tree while the others can't give that value. After the file specific setup, all the files have the same elements. Each of the shared elements have a fitting name and contain multiple settings. For instance CivicGroupAllow contains all the AllowsImprovements, AllowsUnitClasses and so on. Future additions should be added to the appropriate group and that way be accessible to all files.
On load, all files are loaded as civics and they enter the same vector. All settings are loaded for all, including the file specific ones. The options not present will then be given default values to make them inactive. The default location in the tech tree is outside the window, meaning it will not be drawn. This give the XML modder the impression that the tech tree location is only present for inventions while inside the DLL it's present for all.
CvGlobals will keep track of where in the civic vector each type is, which allows looping from GC.getFirstInvention() to GC.getLastInvention() and skip looking at non-inventions if that is what we want. Naturally we can loop the entire vector if needed, which is what the cache generating code will do. It will not care if a unit is unlocked by a trait or an invention, which is the whole point of this merge.
That's it. It looks so simple when it's written like this, but it sure took some code reading and some thinking to end up with this.