Skip to content

ChatMapper XML

The Windows Desktop app reads and writes an XML serialisation of the same model as the JSON format. It is what Unity’s Dialogue System imports natively, and it is the safest way to hand a project to someone still on Desktop. ChatMapper Cloud exports it (Export → ChatMapper XML) and imports it, and the round trip JSON → XML → JSON is tested to be lossless for every documented field.

example-scenario.xml is the example project in this form.

<?xml version="1.0" encoding="utf-8"?>
<ChatMapperProject Language="en-US" Title="The Ferry at Dusk" Version="1.5.1.0" Author="…"
EmphasisColor1="#E7955B" EmphasisStyle1="b--" EmphasisColor1Label="" …>
<Description>…</Description>
<UserScript>Variable[&quot;has_token&quot;] = false</UserScript>
<Assets>
<Actors>
<Actor ID="1">
<Fields>
<Field Hint="" Type="Text"><Title>Name</Title><Value>Traveller</Value></Field>
<Field Hint="" Type="Boolean"><Title>IsPlayer</Title><Value>True</Value></Field>
…
</Fields>
</Actor>
</Actors>
<Items> <Item ID="1">…</Item> </Items>
<Locations> <Location ID="1">…</Location> </Locations>
<Conversations>
<Conversation ID="1" NodeColor="White" LockedMode="Unlocked">
<Fields>…</Fields>
<DialogEntries>
<DialogEntry ID="0" NodeColor="Green" DelaySimStatus="false" ConditionPriority="Normal"
FalseCondtionAction="Block" IsRoot="true" IsGroup="false">
<Fields>…</Fields>
<UserScript />
<ConditionsString />
<ReviewerStatus>None</ReviewerStatus>
<ReviewerNotes />
<OutgoingLinks>
<Link OriginConvoID="1" DestinationConvoID="1" OriginDialogID="0" DestinationDialogID="1" IsConnector="false" />
</OutgoingLinks>
</DialogEntry>
</DialogEntries>
</Conversation>
</Conversations>
<UserVariables>
<UserVariable>
<Fields>…</Fields>
</UserVariable>
</UserVariables>
</Assets>
</ChatMapperProject>
JSONXML
top-level Language, Title, Version, Authorattributes on <ChatMapperProject>
Description, UserScriptchild elements
_editor.emphasisEmphasisColorN, EmphasisStyleN, EmphasisColorNLabel attributes (N = 1–4)
Assets.Actors[] etc.<Actors><Actor ID>, <Items><Item ID>, <Locations><Location ID>
Assets.UserVariables[]<UserVariables><UserVariable> — no ID attribute
Fields: { "Name": "x" }<Field Hint="" Type="Text"><Title>Name</Title><Value>x</Value></Field>
Conversations[].DialogNodes[]<Conversation ID NodeColor LockedMode><DialogEntries><DialogEntry …>
node IsRoot, IsGroup, DelaySimStatusattributes, lowercase true/false
node ConditionPriority 1…5attribute High / AboveNormal / Normal / BelowNormal / Low
node FalseConditionAction 0/1attribute FalseCondtionAction = Block / Passthrough
node NodeColorattribute, colour name
node ConditionsString, UserScriptchild elements
_editor.reviewStatus[…], _editor.notes[…]<ReviewerStatus> and <ReviewerNotes> inline on the entry
OutgoingLinks[]<OutgoingLinks><Link … IsConnector="false" />
_editor.fieldMeta type / hint / exportType and Hint attributes on <Field>; a field marked not exported is omitted
  • The typo is canonical. The attribute is FalseCondtionAction (missing i). It is part of the format and will not change.
  • Enums are names in XML, often integers in JSON. Passthrough vs 1, Normal vs 3, Green vs 3. Both forms are accepted on read in JSON.
  • Variables have no IDs in XML. <UserVariable> carries only fields, so variable IDs do not survive a JSON → XML → JSON trip. Names do; key by name.
  • Empty collections are omitted. A project with no items has no <Items> element. Treat a missing collection as empty.
  • Field types are carried. Every <Field> has a Type (Text, Multiline, Number, Boolean, Files, Actor, Item, Location, Localization) and a Hint. Dialogue Text and Menu Text are Localization. JSON keeps this in _editor.fieldMeta and infers the built-ins.
  • Reviewer status vocabulary. JSON uses None / NeedsReview / Approved / Rejected; Desktop’s XML uses None / UnderReview / Approved / NeedsWork (plus WorkInProgress / Completed, which import as NeedsReview). The exporter translates.
  • Reviewer notes are inline in XML and in _editor in JSON, so they survive an XML round trip but are absent from the JSON export (which strips _editor).
  • Values are escaped, not CDATA. " in Lua becomes &quot;.

In the ChatMapper repository, ten structurally varied fixtures go JSON → XML → JSON and are asserted deep-equal, through both the web importer and the Python import_project.py, and the two importers are asserted to agree. What does not survive is exactly the list above: variable IDs and anything in _editor that has no XML home (canvas positions, templates, collapsed state, languages list). Node colours, custom fields with their types, Lua, links, notes and review status all do.

For a pipeline that still runs through the Windows app (1.5–1.9):

  • Exports: Project as XML, Project as JSON, Screenplay as RTF, Project Data to Excel (every field, editable and re-importable), Dialogue Graph as PDF/JPEG/PNG, CMPKG (project + media), and “as Chat Mapper 1.3/1.5 project”. XML export has options to include empty fields and to select which custom fields are written — enable both if the file is going to be re-imported anywhere.
  • Imports: CMPKG, “New Project from XML”, and Excel — which updates existing assets only and cannot create new ones.
  • Command line (commercial licence): "Chat Mapper.exe" -xml|-excel|-rtf|-csv <outputFolder> <file1.cmp,file2.cmp> batch-exports projects, and a custom exporter written with the Exporter Development Kit is invoked as -its-title-in-dashes.
  • Desktop runs Lua 5.1; ChatMapper Cloud’s simulator runs 5.4. Nothing in the documented host API differs between them.

The Desktop app’s native .cmp is a binary serialisation of the same model, encrypted with a fixed key compiled into the (freely distributed) app; a .cmpkg is a zip of a .cmp plus its media. ChatMapper Cloud decodes both server-side on import. Neither is a format to produce: write XML or JSON, which Desktop opens directly. See CMPKG for the package ChatMapper Cloud exports.