I am not an expert in OVAL, but here is my thoughts.
Generator is just a metadata. I have a product_name, schema_version and timestamp blocks in it.
Definitions is something like a book cover. In definition (i use one definition per file) you want to specify class of checking (like "vulnerability", for example) title of this vulnerability, description, reference for it (i use URL to cve.mitre.org), affected software family (like "windows") and affected products (like "Visual Studio Code").
Inside definition block there is a "Criteria" block. Here you write a condition which returns "true" (criterion - it is a reference to some test in your file which checks for this vulnerability).
Then you write Tests block. Test must contain object and state. When you run your XML through Ovaldi, this test will check if object is in specified state. For example - you get object "version" from Windows Registry and check its state ("is it equal to 8.1?") If there is an object and it is in specified state - test will return true.
Objects and states are described in blocks objects and states AFTER block tests. You always have to write those blocks in right order: Generator, Definitions, Tests, Objects, States, Variables (here you can find the diagrams for it).
Yes, there is a Variables block. I don't really know much about it but it seems like community uses them mostly for lists of versions: github repository, example with regular expressions.