Schema definition for ESOUI XML

Creating GUI in Elder Scrolls Online is time consuming and frustrating. For a long time I have played with the thought of making it somehow easier and finally decided to look into that.

After thinking about it very hard for a few evenings and researching different ways to improve the experience, I arrived at the conclusion that it would be best to create a schema for the XML files used to define the GUI elements. This way I would learn more about the available possibilities and end up with something that will allow me to craft them faster and with less errors.

The first step was to learn how to define a schema for XML files. After a bit of searching around, it turned out that there are two ways how it can be done: Document Type Definition (DTD) and XML Schema Definition (XSD). Looking up the differences, it quickly became clear that DTD is basically obsolete and XSD was the way to go.

Now it was time to find some resources on how to write actual XSD files. This turned out a bit harder than expected. For some reason all the results I found where copied parts of the same tutorial, which seems to have originated from w3schools. They cover the basics, but don’t really explain much in depth. With their guides and googling some StackOverflow answers, I managed to write my first schema that would validate the first few elements in an ESOUI XML file!

<?xml version="1.0" encoding="UTF-8" ?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xs:complexType name="ControlType">
        <xs:sequence>
            <xs:element name="Controls" type="ControlsType" minOccurs="0" />
        </xs:sequence>
        <xs:attribute name="name" type="xs:string" />
        <xs:attribute name="hidden" type="xs:boolean" />
    </xs:complexType>

    <xs:complexType name="ControlsType">
        <xs:sequence>
            <xs:element name="Control" type="ControlType" />
        </xs:sequence>
    </xs:complexType>

    <xs:complexType name="GuiXmlType">
        <xs:sequence>
            <xs:element name="Controls" type="ControlsType"/>
        </xs:sequence>
    </xs:complexType>

    <xs:element name="GuiXml" type="GuiXmlType"/>
</xs:schema>

But this was only just the beginning. The next hurdle was to figure out how to model the actual content of the ESOUI XML. For that I had to take a deep look at the “UI XML Layout” section in the ESOUIDocumentation and figure out how all the things there are related to each other. After a few evenings of thinking and doing, I managed to write an XSD that could properly validate a couple of files from the ESOUI source.

It became quite clear how everything is structured and that I only needed to repeat a few templates in order to create a complete version. But that would be boring to do by hand, wouldn’t it? Especially since the XML could change at any major update and new attributes and elements could become available or old ones could get deleted. That’s why I decided to generate the XSD automatically from the documentation file.

I already had set up a JavaScript to parse parts of the documentation in order to generate an Execution Environment for Eclipse LDT in the past, but left out the section about the UI, since it was not necessary back then. After some tinkering I managed to parse the remainder of it and generate the first full version of the schema. My Windows had Visual Studio set as default program for .xsd files, so I decided to take a look.

Turned out VS can visualize the relations between the controls in a neat way.

The next step was to validate all files in the ESOUI source to make sure everything worked, but opening the xsd file in Eclipse for the first time turned out differently than expected and I was greeted by a lot of errors in the part where I defined the different Control Types.

cos-nonambig: Anchor and Anchor (or elements from their substitution group) violate “Unique Particle Attribution”. During validation against this schema, ambiguity would be created for those two particles.

After some searching around and sleeping over it, it turned out that the way I did the inheritance of Control and AnimationBase elements was not going to work, since it would add the same group of elements to both the parent and the child type. So I had to introduce a virtual base type for each of them and handle the actual Control and AnimationBase as regular child elements.

    <xs:complexType name="Control">
        <xs:choice minOccurs="0" maxOccurs="unbounded">
            <xs:group ref="ControlElements"/>
        </xs:choice>
    </xs:complexType>

    <xs:complexType name="Label">
        <xs:complexContent>
            <xs:extension base="Control">
                <xs:choice minOccurs="0" maxOccurs="unbounded">
                    <xs:group ref="ControlElements"/>
                </xs:choice>
            </xs:extension>
        </xs:complexContent>
    </xs:complexType>

Since the first version of the script was just hacked together and didn’t really allow for an easy fix, I decided to use this occasion to learn something new and rewrote everything in TypeScript.

Now Eclipse also accepted the schema, but even after an extensive search I could not find a way to globally set it to be used for all xml files in a specific directory. So instead I decided to just replace the opening tag in all xml files to include a noNamespaceSchemaLocation.

The result was a surprisingly short list. It reported 36 errors, most of which are typos or misplaced attributes.

The final part was to create a second schema for the bindings xml files, but since they are not part of the documentation and didn’t look very complicated, I just created a schema based on the available code in the ESOUI source.

This first version of the schema already works quite well and the autocomplete is awesome, but I have some plans to make it even better in the future. One thing I will add for sure are more specific rules for types. Right now most attributes are just strings, but the name attributes for example support variable expansion for things like $(parent), so I would like to make sure that these are completed and validated correctly too.

The schema files for the game version on live are available via the following two URLs:

In order to use them in Eclipse you just need to specify them in the root element of the xml like this:

<GuiXml xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://sir.insidi.at/or/schema/esoui.xsd">
<Bindings xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://sir.insidi.at/or/schema/esobindings.xsd">

This will make Eclipse download the xsd file automatically. If you don’t want to rely on an external resource, you can also set a local override file in the settings. Just go to XML > XML Catalog and create a new entry with type URI, where the key is the exact link from above. This can also be used to specify a different version of the schema, e.g. for PTS.

You can also find the tool I wrote to convert the ESOUIDocumentation.txt on github.

Leave a Reply

Your email address will not be published. Required fields are marked *