XML configuration syntax - ObjectVision/GeoDMS GitHub Wiki

The GeoDMS can read a configuration, or a part of one, written in XML instead of in the configuration file syntax. It is an alternative notation for the same tree of tree items, it is read by a reader of its own, and it is rarely used: almost every configuration is written in .dms syntax. It is described here because the reader ships with every version and a fragment can be included in any configuration.

including a fragment

An include statement whose file name ends in .xml is read by the XML reader instead of by the .dms parser. The fragment is added to the container the include statement appears in, exactly as a .dms include is:

container region_data
{
   #include <region.xml>
}

The folder rule is the same as for a .dms include: the included file lives in the subfolder named after the including configuration file, without its extension.

A whole configuration can also be written in XML and named on the command line:

GeoDmsRun.exe /Lrun.log region.xml /nr

The outermost element is then the configuration root, so its own name is not part of an item path, the same rule that holds for the top level container of a .dms configuration.

The GeoDMS GUI offers only .dms files in its open dialog, so an XML configuration is opened through the command line or through an include.

syntax

A fragment starts with a version header and holds one outermost element:

<?xml version="1.0"?>
<TreeItem name="region">
</TreeItem>

Since GeoDMS 20.20.0 the markup is read character by character, so this is ordinary XML: spaces around <, ?, /, > and = are optional, an attribute value may be quoted with " or with ', and a tag may close itself with />.

Before that release the reader split the markup on whitespace, so each of those characters had to stand on its own between spaces:

<? xml version = "1.0" ? >
< TreeItem name = "region" >
< / TreeItem >

The compact spelling ended the read with FormattedInpStream Error: expected '='. The spaced-out spelling is still accepted, so an existing fragment keeps working; a fragment written in the compact spelling does not load on an older GeoDMS.

The text between an opening and a closing tag is read as text, not as markup, so an expression inside an element needs no extra spaces.

Since GeoDMS 20.20.0 that text is kept as it stands, apart from the whitespace before its first and after its last non-blank character, which is dropped; line ends are read the way XML prescribes, so a CRLF and a lone CR each count as one line end. Before that release every run of whitespace was collapsed to a single space, which is invisible in a Descr but put a multi-line expression on one line and squeezed the alignment out of a value array.

comments

Since GeoDMS 20.20.0 a fragment may carry XML comments, wherever text or an element may stand:

<?xml version="1.0"?>
<TreeItem name="region">
   <!-- the study area, as delivered in 2026 -->
   <Descr>the study area</Descr>
</TreeItem>

They are skipped, not kept: a comment is gone from the tree, so writing the tree out again does not bring it back, exactly as in configuration file syntax. Before that release a comment was a parse error, because <!-- was read as the start of a tag named !--.

items

Three element names create a tree item. Any other element is read as a property of the item that its enclosing element created.

element creates attributes
TreeItem a container or any other tree item name
unit a unit name, ValueType
DATAITEM a data item name, DomainUnit, ValuesUnit, ValueComposition

name is required on all three, and ValueType on a unit and ValuesUnit on a DATAITEM. A DATAITEM without a DomainUnit is a parameter: its domain is the void unit, the same item that parameter<uint32> x configures in .dms syntax.

Since GeoDMS 20.20.0 a missing name or ValuesUnit is reported; a missing ValueType always was, as Unknown ValueType ''. And since that release a DATAITEM without a DomainUnit really is a parameter: before it, such an item was left with an unresolved domain instead of the void unit, and computing it took the process down with an access violation rather than producing a value. Every parameter of a written-out configuration was in that state, so a configuration that had been written as XML (see below) crashed on the first parameter it computed.

properties

Every property is written as a child element, never as an attribute. <TreeItem name="x" Descr="..."> is refused with XML Element property Descr seen as attribute for x: TreeItem, and the same holds for StorageName and StorageType:

<TreeItem name="region">
   <Descr>the study area</Descr>
   <StorageType>gdal.vect</StorageType>
   <StorageName>%projDir%/data/region.gpkg</StorageName>
</TreeItem>

The exception is the handful of properties that a tree item fixes when it is created: name, ValueType, DomainUnit, ValuesUnit and ValueComposition. Those are attributes of the opening tag, as the table above says, and never child elements.

Since GeoDMS 20.20.0 writing one of them as a child element is refused, with names a property that cannot be set here: it is set at construction, from an attribute of the open tag; the same holds for a read-only property such as TableType. Before that release such an element was dropped without a word, so <name>other</name> looked as if it renamed the item and in fact did nothing at all.

entities

The XML entities &amp; &lt; &gt; &apos; &quot; are decoded in element text.

Since GeoDMS 20.20.0 they are decoded in attribute values as well, and an attribute value is otherwise taken as it stands. Before that release an attribute value was read by the reader for quoted strings of a .dms configuration, which decoded neither: an entity stayed there literally, so ValueType = "uint32&amp;" was reported as Unknown ValueType 'uint32&amp;', and a backslash was taken for the start of a C escape, so a value containing a backslash lost it and kept only the character behind it.

Since GeoDMS 20.20.0 the character that follows an entity is kept. Before that release < Descr > a &amp; b < / Descr > gave a &b: the character right after the ; was swallowed, so a text lost one character per entity it contained, and two entities in a row turned the second one into literal text (x &amp;&amp; y gave x &amp; y). A configuration that compensated for this, by doubling the character after an entity, now has one character too many.

writing a configuration as XML

A loaded configuration can be written back out in this notation. @dumpconfig chooses the notation from the extension of the file name it is given, so

GeoDmsRun.exe /Lrun.log region.dms @dumpconfig C:/tmp/region.xml

writes the tree as XML, where C:/tmp/region.dms would have written it in configuration file syntax. The same happens through DMS_TreeItem_Dump. What is written is the compact spelling of the syntax section, with the construction attributes in the opening tag and every other property as a child element.

Since GeoDMS 20.20.0 that output can be read back. Before it, the reader rejected the writer's own spelling on the first line, so a configuration could be written as XML but not loaded again.

What survives the round trip is the tree: the same items, expressions, properties, units, templates, functions and configured value arrays. What does not survive is what the writer never writes: comments, and an #include, which is written inline rather than as a directive. Writing the same tree twice gives the same bytes, so one dump can be compared with a later one.

Since GeoDMS 20.20.0 a function declaration survives it. The notation has no declaration grammar for the function keyword, so a function item is written as a container with an extra FunctionSpec element that carries what makes it a function: the parameter count, the designated result, the type variables, the signature references and the variant flags. Before that release a function came back as a plain container with IsTemplate = "True", without its parameters or its result. A template always survived: IsTemplate is an ordinary property.

Since GeoDMS 20.20.0 a configured value array survives it as well, in a DataBlock element. Before that release it was written into the item element as text and dropped on reading, so a configuration written as XML came back with every value array gone, which shows as No calculation rule or storage manager was specified on the first item that had one.

The same element now carries an item that holds its values without having a rule for them, which is what the GeoDMS GUI writes when it saves a desktop. Such an item is written as a value array, so it reads back as one: that is the conversion the configuration file syntax has always made on a dump, and the two notations agree on it again. Before that release it went into a DATA element that nothing read.

errors

An error inside an included fragment is reported in the eventlog as an [E] line, but it does not fail the load by itself. The run fails later, at the point where something refers to an item the fragment did not create. So when a fragment does not do what you expect, read the eventlog rather than the exit code.

Since GeoDMS 20.20.0 an error in the markup names the file, the line and the column, and says what was expected:

[E] XML Error: .../region.xml(4, 14): the closing tag '</TreeItemm>' does not match the open tag '<TreeItem>'

Before that release six of these checks — the version header, a closing tag that does not match, a closing tag with an attribute, and the > after a / or a ? — were internal checks rather than checks on the input. In a release build they gave a message without a position; in a debug build they stopped the program on an assertion before any message could be reported, and the run ended with exit code 3 and a misleading memory-leak report of the half-built tree.

example

example.dms:

container region_data
{
   #include <region.xml>
   container checks
   {
      parameter<uint32> total := sum(region/nr), IntegrityCheck = "total == 33";
   }
}

example/region.xml, the subfolder named after the configuration file:

<?xml version="1.0"?>
<TreeItem name="region">
   <Descr>read from an xml fragment</Descr>
   <unit name="id" ValueType="uint32">
      <Expr>range(uint32, 0, 3)</Expr>
   </unit>
   <DATAITEM name="nr" DomainUnit="id" ValuesUnit="uint32">
      <Expr>id(id) + 10</Expr>
   </DATAITEM>
</TreeItem>

This configures the same tree as:

container region_data
{
   container region: Descr = "read from an xml fragment"
   {
      unit<uint32> id := range(uint32, 0, 3);
      attribute<uint32> nr (id) := id(id) + 10;
   }
}
⚠️ **GitHub.com Fallback** ⚠️