#thundermods

Thundermods.net Projekte

WrathEd

Tiberium Wars Advanced

Granatball

@Thundermods @Thundermods

[Guide] Basics of XML editing

Golan

Note: This guide is meant to give a basic overview for the usage of XML in the TW/RA3 SDK, not a technical description of it. 
 
The XML file format used in the TW and RA3 SDK offers a lot of possibilities and useful features, but it's important to use it right, as there are certain restrictions to how it may be formated. The formating procedure of adding an additional indent for every sublevel is optional but highly recommended to keep code readable. 
It is advisable to use an Editor supporting the XML syntax to allow syntax highlighting, validation and other features. Notepad++ and its XML Plugin are often used for this. You can also use it to try creating some of the examples here yourself and have them validated. 
 

Basics

 
The most important thing when editing XML is the proper use of Elements. Elements have a name but come in two flavors: Single-Tag or Start-End-Tag. 
 
Example: Single-Tag 

	<TagName/>

 
 
Example: Start-End-Tag 

	<TagName>
	</TagName>

 
 
Every Element can have a number of Attributes, meaning pairs of names/values. Attributes must be defined after the Element has been opened; spaces, line breaks and tabs can be used to delimit Attributes. Each Attribute may be defined only once per Element. 
 
Example: Single-Tag  

	<TagName
		Attribute1="value1"
		Attribute2="value2"/>

 
 
Example: Single-Tag (compressed but functionally the same) 

	<TagName Attribute1="value1" Attribute2="value2"/>

 
 
Example: Start-End-Tag 

	<TagName
		Attribute1="value1"
		Attribute2="value2">
	</TagName>

 
 
Elements of the Start-End-Tag flavor may include content between the start and end tag. Content can mean simple text or other Elements (Child Elements). Child Elements can again include Child Elements of their own. Start-End-Tags without any content can be shortened to Single-Tags without loosing functionality. 
 
Example: Short text 

	<TagName>Text</TagName>

 
 
Example: Text 

	<TagName
		Attribute1="value1"
		Attribute2="value2">
		Text
	</TagName>

 
 
Example: Short Child Element 

	<TagName>
		<ChildTagName/>
	</TagName>

 
 
Example: Child Element 

	<TagName
		Attribute1="value1"
		Attribute2="value2">
		<Child1TagName
			PizzaCost="4$"
			PizzaTopping="Cheese">
			<Child2TagName>
			</Child2TagName>
		</Child1TagName>
	</TagName>

 
 
Example: Child Element (compressed but functionally the same) 

	<TagName Attribute1="value1" Attribute2="value2"><Child1TagName PizzaCost="4$" PizzaTopping="Cheese"><Child2TagName/></Child1TagName></TagName>

 
 
Technically, every XML-file consists of a single main Element (Root Element) to which all other Elements are Child Elements of varying degree. 
 
Comments can be made using special Elements denoted by the start sequence <!-- and end sequence -->. Comments can enclose regular Elements to deactivate them and be inserted like Child Elements; like regular Elements, they may not intersect other Elements. 
 
Example: Simple Comment 

	<!-- This is a comment -->
	<TagName
		Attribute1="value1"
		Attribute2="value2"/>

 
 
Example: Comment enclosing another Element 

	<!-- This comment deactivates the Element
	<TagName
		Attribute1="value1"
		Attribute2="value2"/>
	-->

 
 
Example: Comment intersecting another Element (invalid code) 

	<TagName
	<!-- 	Attribute1="value1"
		This comment breaks the Element-->
		Attribute2="value2"/>

 
 

SAGE XMLs

 
 
The first line in any XML must be the XML Declaration. The important part for us is the encoding Attribute, which defines the character set used in the file - UTF-8 is a reliable setting here. 
 
Example: XML Declaration 
<?xml version="1.0" encoding="UTF-8"?> 
 
The Root Element of SAGE XMLs used for regular assets (this means everything but XIncludes and Lua) must be the AssetDeclaration. It can be used to define the so called Namespaces which are used by the compiler to identify special commands. In most cases, it is best just to use an AssetDeclaration defining all possible Namespaces.  
 
Example: Complete AssetDeclaration 

	<AssetDeclaration xmlns="uri:ea.com:eala:asset" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xi="http://www.w3.org/2001/XInclude" xmlns:xai="uri:ea.com:eala:asset:instance">
	</AssetDeclaration>

 
 
All regular assets like objects, weapons, commandsets and so on (a complete list can be found in CnC3Types.xsd, line 586) are inserted as Child Elements to the AssetDeclaration. The sequence and number of these elements is irrelevant and can be decided by the user. 
The exception to this are the three Elements <Tags/>, <Includes/> and <Defines/> - they must come before any regular assets and appear in the order as listed, though they can be omitted when not needed. 
 
Example: XML with unspecified assets 

	<?xml version="1.0" encoding="UTF-8"?>
	<AssetDeclaration xmlns="uri:ea.com:eala:asset" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xi="http://www.w3.org/2001/XInclude" xmlns:xai="uri:ea.com:eala:asset:instance">
		<Tags/>
		<Includes/>
		<Defines/>
		<GameObject/>
		<ObjectCreationList/>
		<LogicCommand/>
		<LogicCommandSet/>
		<FXParticleSystemTemplate/>
		<ObjectCreationList/>
		<GameObject/>
		<FXParticleSystemTemplate/>
	</AssetDeclaration>

 
 
Of the three special Elements, the <Includes/> is the most important for now (<Defines/> will be covered later, <Tags/> is unneeded), as it allows adding new files to a mod. Though technically all assets could be added to a single file, it is important to structure a mod so that it can be edited easily. 
 
Next Guide: Includes - relative and absolute Paths 
 

Advanced -- XSDs

 
 
Much of the power of the XML language comes from the internal use of XSDs (XML Schema Document), which use the XML syntax as well. These files tell the SDK what is actually valid for the game - an <ObjectCreationList/> is recognized by the game while an <ObjectDeletionList/> is not. As modders, XSDs have two purposes for us: they serve as a library of what the game can handle and define default values that help keep code short. 
 
Reading XSDs 
All XSDs can be found in the [...]Mod SDKSchemasxsd folder and its subdirectories. When viewing them, it can be very useful to use regular XML syntax highlighting. 
While XSDs might seem confusing at first, they only represent the things you already know: valid Elements (names and properties), their structures (Attributes and Child Elements) and possible values (Data Types and Lists). 
 
Let's have a look at the important bits of the LogicCommand asset type as an example. You can find its XSD (AssetTypeLogicCommand.xsd) easily by making a text search for its name in the XSD folder. 
 
At the beginning, the type defined is simply given a name. This is actually the name of the type, not the XML Element - you will see the difference shortly.  

	<xs:complexType name="LogicCommand" xas:runtimeWrapper="::LogicCommand">

 
 
Next, the extension base is defined - this is another asset type (usually defined elsewhere) that this new type expands on. This means that our LogicCommand type includes the features already defined for the BaseInheritableAsset type. 

	<xs:extension base="BaseInheritableAsset">

 
 
Now, the valid Child Elements are defined. Being enclosed by a <xs:sequence/> Element means that they must occur in the sequence as listed here (like <Tags/>, <Includes/> and <Defines/>).The important attributes for each Element are: 
name: The name of the XML tag of the Child Element used in the actual coding file. 
type: The name of the XSD asset type definition, which again specifies how this Child Element is structured. 
min-/maxOccurs: How often the Child Element may be used at least/most. For example, some Child Elements are not required for the parent Element to work (minOccurs="0"), may occur only once (maxOccurs="1") or as often as needed (maxOccurs="unbounded"). 

	<xs:sequence>
		<xs:element name="SpecialPower" type="SpecialPowerTemplateRef" minOccurs="0" maxOccurs="1"/>
		<xs:element name="Upgrade" type="UpgradeTemplateRef" minOccurs="0" maxOccurs="1" />
		<xs:element name="Object"  type="GameObjectRef" minOccurs="0" maxOccurs="1" />
	</xs:sequence>

 
 
Then, the possible attributes are defined. This is similar to defining Elements; Attributes never require a special sequence though.  
name: The name of the Attribute as used in the XML tag 
type: The name of the XSD asset type definition. For Attributes, these are usually Data Types or Lists. 
use: Similar to min-/maxOccurs, this defines whether an Attribute must be defined. The inherited id Attribute is an example for this. 

	<xs:attribute name="Type" type="LogicCommandType" default="NONE"/>
	<xs:attribute name="Options" type="LogicCommandOptionsBitFlags" />

 
 
Default Values 
 
Most important Attributes are assigned default values in the XSD. These are used if an Attribute is not specified in the XML. This allows writing extremely short code if the default values match the ones needed. 
For example, the TurretAIData type used for the <TurretSettings/> Tag has defaults for all of its Attributes but ControlledWeaponSlots. Leaving out any Attributes will make the Compiler fill in the defaults, with the exception of ControlledWeaponSlots. 
 
Example: Shortened XML code for <TurretSettings/> 

	<TurretSettings
		TurretTurnRate="40"
		TurretPitchRate="20"
		AllowsPitch="true"
		MaxDeflectionClockwise="20d"
		/>

 
 
Example: Equivalent to aforementioned XML code for <TurretSettings/> 

	<TurretSettings
		TurretTurnRate="40"
		TurretPitchRate="20"
		AllowsPitch="true"
		MinimumPitch="0d"
		PitchHeight="50%"
		MinIdleScanTime="0.0s"
		MaxIdleScanTime="0.0s"
		MinIdleScanAngle="0.0"
		MaxIdleScanAngle="0.0"
		MaxDeflectionClockwise="20d"
		MaxDeflectionAntiClockwise="180d"
		NaturalTurretAngle="0d"
		RecenterWhenOutOfTurnRange="true"/>