Document.xml describes every object in the document: its type, its name
and the values of its properties. It holds the geometric and parametric definition
only; FreeCAD in console mode reads nothing else. GuiDocument.xml is its
display counterpart, with one view provider for each object and the camera. There is
no schema file: the layout below is what FreeCAD’s source writes and reads (main
branch, read in November 2026), checked against the example on the FreeCAD wiki. The
child element inside each Property depends on the property’s type and is
described on the property types page.
Element tree
Document
├── StringHasher (when StringHasher="1")
│ └── StringHasher2 (when new="1")
├── Properties (the document’s own properties)
│ ├── _Property (TransientCount of them)
│ └── Property (Count of them)
│ └── (value element of the property type)
├── Objects
│ ├── ObjectDeps (when Dependencies="1", one per object)
│ │ └── Dep
│ └── Object (type, name and id of each object)
└── ObjectData
└── Object (one per object, same names)
├── Extensions (when Extensions="True")
│ └── Extension
└── Properties
├── _Property
└── Property
└── (value element)
Document
The file starts with <?xml version='1.0' encoding='utf-8'?> and a
comment, FreeCAD Document, see https://www.freecad.org for more
information..., then the root element.
| Attribute | Value written | Meaning |
|---|---|---|
SchemaVersion | 4 | Layout of the file. Readers handle 2 (Features layout, below) and 3 or higher (Objects layout); required |
ProgramVersion | major.minorRrevision | The FreeCAD build that saved the file. When it is missing, readers record the version as pre-0.14 |
FileVersion | 1 | Version of the data file layouts; read as 0 when missing |
StringHasher | 1 | A StringHasher element follows |
FreeCAD uses ProgramVersion when reading: colours in files older than
1.1 have their alpha inverted (see binary
list files). When objects are exported to another file rather than saved as a
document, the root carries SchemaVersion="4",
ProgramVersion and FileVersion="1" but no
StringHasher, the document Properties element is empty
(Count="0"), and object names get @ and the source
document’s name appended.
StringHasher
The document’s string hasher stores shared strings used by topological element names.
| Element | Attribute | Meaning |
|---|---|---|
StringHasher | saveall | Non-zero: save every string, not only the used ones |
threshold | Hasher threshold | |
count | Always 0 in the current layout; with an empty table the element is written with an end tag and nothing in it | |
new | 1: a StringHasher2 element follows | |
StringHasher2 | file | Entry holding the table, StringHasher.Table.txt in a saved document |
count | Number of strings, when the table is inline in a CDATA section instead |
An older layout, read when new is missing, lists the strings as
Item elements with id and hash,
data or text attributes.
Properties, Property and _Property
The same block holds the document’s own properties, each object’s properties (in
ObjectData) and each view provider’s properties (in
GuiDocument.xml). Properties are written in alphabetical order of
name. Transient properties, whose values are not saved, come first as
_Property elements that keep only their status; the rest follow as
Property elements holding one value element.
| Element | Attribute | Meaning |
|---|---|---|
Properties | Count | Number of Property elements |
TransientCount | Number of _Property elements before them; 0 when missing (older files) | |
_Property | name | Property name |
type | Property type, such as App::PropertyString | |
status | Status bits, decimal (below) | |
Property | name | Property name |
type | Property type; if it no longer matches the object’s property of that name, the object is asked to convert the value | |
status | Status bits, decimal; left out when zero | |
group | Dynamic properties only (added by scripts or the user): the group shown in the property editor | |
doc | Dynamic only: the tooltip text | |
attr | Dynamic only: the property type flags (below), decimal | |
ro | Dynamic only: read-only, 0 or 1 | |
hide | Dynamic only: hidden, 0 or 1 |
A property that is transient by its status but written as Property
(a dynamic one) has an empty element: its value is not saved.
Status bits
| Bit | Name | Meaning |
|---|---|---|
| 0 | Touched | Property is touched |
| 1 | Immutable | Cannot be modified |
| 2 | ReadOnly | Read-only in the property editor |
| 3 | Hidden | Hidden in the property editor |
| 4 | Transient | Value not saved in the document |
| 5 | MaterialEdit | Turns on material editing |
| 6 | NoMaterialListEdit | Turns off material list editing |
| 7 | Output | Output property |
| 8 | LockDynamic | Dynamic property cannot be removed |
| 9 | NoModify | Changes do not mark the GUI document modified |
| 10 | PartialTrigger | May change in a partially loaded document |
| 11 | NoRecompute | Changes do not touch the owner for recompute |
| 12 | Input | Input property |
| 13 | Ordered | For lists: the order of elements matters |
| 14 | EvalOnRestore | With an expression bound: evaluate it on restore and touch the object if the value changes |
| 15 | Busy | Internal, prevents recursive signals |
| 16 | CopyOnChange | Copy the linked object when the property changes |
| 17 | UserEdit | Property editor shows a button for user editing |
| 18 | DisableNotify | Changes are not passed to the container |
| 21 | PropDynamic | Property was added dynamically |
| 22 | PropNoPersist | Mirrors type flag NoPersist |
| 23 | PropNoRecompute | Mirrors type flag NoRecompute |
| 24 | PropReadOnly | Mirrors type flag ReadOnly |
| 25 | PropTransient | Mirrors type flag Transient |
| 26 | PropHidden | Mirrors type flag Hidden |
| 27 | PropOutput | Mirrors type flag Output |
| 28 | PropInput | Mirrors type flag Input |
| 29–31 | User1–User3 | For the owning class’s own use (the source also names User4 as bit 32, outside the 32 stored bits) |
When reading, a property whose saved status has bit 4 or bit 25 set is skipped rather than restored.
Property type flags (attr)
| Value | Name | Meaning |
|---|---|---|
| 0 | Prop_None | No special type |
| 1 | Prop_ReadOnly | Read-only in the editor |
| 2 | Prop_Transient | Content not saved, but name, type and status are |
| 4 | Prop_Hidden | Hidden in the editor |
| 8 | Prop_Output | Changing it does not touch the container |
| 16 | Prop_NoRecompute | Changing it does not touch the container for recompute |
| 32 | Prop_NoPersist | Not saved at all |
| 64 | Prop_Input | A true input property |
Document properties
The first Properties block belongs to the document itself.
| Name | Type | Meaning |
|---|---|---|
Comment | String | Free comment |
Company | String | Company name, from the preferences when created |
CreatedBy | String | Author, from the preferences when created |
CreationDate | String | Date of creation (read-only) |
FileName | String | Path of the saved file; transient, so written as _Property (older files hold its value) |
Id | String | Identifier of the document |
Label | String | Name of the document (read-only) |
LastModifiedBy | String | Last editor |
LastModifiedDate | String | Date of last change (read-only), Unknown by default |
License | String | Licence name, from the preferences |
LicenseURL | String | Address of the licence text |
Material | Map | Material properties |
Meta | Map | Additional meta information |
ShowHidden | Bool | Show hidden objects in the tree view |
Tip | Link | The tip object; transient, rebuilt from TipName after reading |
TipName | String | Name of the tip object (hidden, read-only) |
TransientDir | String | Folder where embedded files live while the document is open; transient |
Uid | UUID | UUID of the document (read-only) |
UnitSystem | Enumeration | Unit system for the project, an index into FreeCAD’s list of unit schemas |
UseHasher | Bool | Use the hasher for topological naming (hidden) |
Types are App::Property plus the name shown, so String is
App::PropertyString. After reading, FreeCAD puts back the
FileName and Label it opened the file with, since the
stored values may be out of date.
Objects
The Objects element lists every object before any property is read,
so that links between objects can be resolved. The objects appear in the document’s
internal order.
| Element | Attribute | Meaning |
|---|---|---|
Objects | Count | Number of objects |
Dependencies | 1: one ObjectDeps per object comes first (not written when exporting) | |
ObjectDeps | Name | The object |
Count | Number of Dep children; the element is empty when 0 | |
AllowPartial | Written when greater than 0. 1: when only part of the document is loaded, the dependencies may be created without being restored; other non-zero values: the object itself may stay partial | |
Dep | Name | An object this one depends on (hidden and external links are left out) |
Object | type | C++ type name, such as Part::Box, Sketcher::SketchObject, App::FeaturePython |
name | Internal name, unique in the document (with @document appended in exported files) | |
id | Numeric object identifier; FreeCAD keeps it on reload | |
ViewType | View provider type, only when it differs from the object type’s default | |
Touched | 1: object needs recomputing | |
Invalid | 1: object is in error | |
Error | Error message, with Invalid | |
Freeze | 1: object is frozen |
The dependency list lets FreeCAD open only some objects of a document together with everything they need; a document opened that way is marked partial.
ObjectData
| Element | Attribute | Meaning |
|---|---|---|
ObjectData | Count | Number of Object children |
Object | name | The object, as named in Objects |
Extensions | True: the first child is an Extensions element | |
Extensions | Count | Number of Extension children |
Extension | type | Extension type name; when FreeCAD has to create it while reading, it must be a Python-addable extension |
name | Extension name |
After the optional Extensions, each object holds one
Properties block as described above. An object whose type FreeCAD
cannot create is reported and its data skipped.
Schema version 2
Readers still accept the older layout with SchemaVersion="2", in which
the object list and object data use other element names:
| Schema 2 | Attributes | Schema 3 and later |
|---|---|---|
Features | Count | Objects |
Feature (in Features) | type, name | Object |
FeatureData | Count | ObjectData |
Feature (in FeatureData) | name | Object |
Attribute text
String values are escaped with FreeCAD’s own attribute encoder:
| Character | Written as |
|---|---|
< | < |
> | > |
& | & |
" | " |
' | ' |
| carriage return | |
| line feed | |
| tab | 	 |
When a document is saved, numbers are written in the C locale in fixed notation with 16 digits after the decimal point (the ZIP writer sets this on its stream). Elements are indented by four spaces per level.
GuiDocument.xml
Written only when FreeCAD runs with its GUI. It starts with the same XML
declaration and comment as Document.xml.
Document SchemaVersion="1" [HasExpansion="1"]
├── Expand (when HasExpansion="1")
│ └── Expand … (nested, one per expanded tree item)
├── ViewProviderData Count
│ └── ViewProvider name, expanded, treeRank [, Extensions]
│ ├── Extensions
│ │ └── Extension
│ └── Properties
│ └── Property …
└── Camera settings
| Element | Attribute | Meaning |
|---|---|---|
Document | SchemaVersion | 1, the only version FreeCAD reads view providers from |
HasExpansion | 1: an Expand element with the tree view’s expanded items follows | |
Expand | name | Object whose tree item is expanded (absent on the outer element) |
count | Number of expanded child items nested inside; an item with none is an empty element without count | |
ViewProviderData | Count | Number of view providers |
ViewProvider | name | Name of the object in Document.xml |
expanded | 1 or 0: tree item expanded (used only without HasExpansion) | |
treeRank | Position in the tree view | |
Extensions | True: view provider extensions come first | |
Camera | settings | The 3D view’s camera written as Open Inventor text (the camera node), with leading comment lines removed; may be empty |
Each ViewProvider holds an optional Extensions block and
a Properties block, exactly like objects in
Document.xml. Properties common to most view providers:
| Name | Type | Meaning |
|---|---|---|
DisplayMode | Enumeration | Display mode; the list of modes depends on the object |
Visibility | Bool | Shown in the 3D view |
ShowInTree | Bool | Shown in the tree view |
SelectionStyle | Enumeration | 0 Shape, 1 BoundBox |
OnTopWhenSelected | Enumeration | 0 Disabled, 1 Enabled, 2 Object (on top only when the whole object is selected), 3 Element (when a sub-element is selected) |
Transparency | Percent | Geometry objects: transparency 0–100 |
ShapeAppearance | MaterialList | Geometry objects: appearance materials, in a binary entry |
BoundingBox | Bool | Geometry objects: draw the bounding box |
Selectable | Bool | Geometry objects: can be selected |
When objects are exported, GuiDocument.xml has no comment, no
HasExpansion and an empty Camera settings="".
Worked example
The FreeCAD wiki’s example Document.xml, from a document holding a
mesh cube and a Part box. It uses schema version 4 but comes from an older FreeCAD
(its CreationDate is 2010): it has no ProgramVersion,
FileVersion or StringHasher, no
TransientCount, id or ObjectDeps, and it
still saves FileName.
<?xml version='1.0' encoding='utf-8'?>
<Document SchemaVersion="4">
<Properties Count="9">
<Property name="Comment" type="App::PropertyString">
<String value=""/>
</Property>
<Property name="Company" type="App::PropertyString">
<String value=""/>
</Property>
<Property name="CreatedBy" type="App::PropertyString">
<String value=""/>
</Property>
<Property name="CreationDate" type="App::PropertyString">
<String value="Fri Jan 29 15:14:38 2010 "/>
</Property>
<Property name="FileName" type="App::PropertyString">
<String value="/tmp/test.FCStd"/>
</Property>
<Property name="Id" type="App::PropertyString">
<String value="201b746f-a1ed-4297-bf3d-65d5ec11abe0"/>
</Property>
<Property name="Label" type="App::PropertyString">
<String value="names"/>
</Property>
<Property name="LastModifiedBy" type="App::PropertyString">
<String value=""/>
</Property>
<Property name="LastModifiedDate" type="App::PropertyString">
<String value="Fri Jan 29 15:15:21 2010 "/>
</Property>
</Properties>
<Objects Count="2">
<Object type="Mesh::Cube" name="Cube" />
<Object type="Part::Box" name="Box" />
</Objects>
<ObjectData Count="2">
<Object name="Cube">
<Properties Count="7">
<Property name="Height" type="App::PropertyFloatConstraint">
<Float value="10"/>
</Property>
<Property name="Label" type="App::PropertyString">
<String value="Cube"/>
</Property>
<Property name="Length" type="App::PropertyFloatConstraint">
<Float value="10"/>
</Property>
<Property name="Mesh" type="Mesh::PropertyMeshKernel">
<Mesh file="MeshKernel.bms"/>
</Property>
<Property name="Placement" type="App::PropertyPlacement">
<PropertyPlacement Px="0" Py="0" Pz="0" Q0="0" Q1="0" Q2="0" Q3="1"/>
</Property>
<Property name="Pos" type="App::PropertyPlacementLink">
<Link value=""/>
</Property>
<Property name="Width" type="App::PropertyFloatConstraint">
<Float value="10"/>
</Property>
</Properties>
</Object>
<Object name="Box">
<Properties Count="7">
<Property name="Height" type="App::PropertyLength">
<Float value="10"/>
</Property>
<Property name="Label" type="App::PropertyString">
<String value="Box2"/>
</Property>
<Property name="Length" type="App::PropertyLength">
<Float value="10"/>
</Property>
<Property name="Placement" type="App::PropertyPlacement">
<PropertyPlacement Px="0" Py="0" Pz="0" Q0="0" Q1="0" Q2="0" Q3="1"/>
</Property>
<Property name="Pos" type="App::PropertyPlacementLink">
<Link value=""/>
</Property>
<Property name="Shape" type="Part::PropertyPartShape">
<Part file="PartShape.brp2"/>
</Property>
<Property name="Width" type="App::PropertyLength">
<Float value="10"/>
</Property>
</Properties>
</Object>
</ObjectData>
</Document>
Reading it: Objects creates a Mesh::Cube named Cube and a
Part::Box named Box. In ObjectData, the box is 10 × 10 × 10
(Float values of its App::PropertyLength properties) at the
origin with no rotation: Q0 to Q2 are 0 and
Q3, the quaternion’s scalar part, is 1. Its user-visible name
(Label) is Box2. Its solid is in the ZIP entry named by the
Part element’s file attribute, and the cube’s mesh in
MeshKernel.bms.
A document saved by current FreeCAD differs as follows, taken from the code that writes it (values shown as … depend on the document):
<?xml version='1.0' encoding='utf-8'?>
<!--
FreeCAD Document, see https://www.freecad.org for more information...
-->
<Document SchemaVersion="4" ProgramVersion="…" FileVersion="1" StringHasher="1">
<StringHasher saveall="…" threshold="…" count="0"></StringHasher>
<Properties Count="…" TransientCount="…">
<_Property name="FileName" type="App::PropertyString" status="…"/>
…
<Property name="Label" type="App::PropertyString" status="…">
<String value="…"/>
</Property>
…
</Properties>
<Objects Count="1" Dependencies="1">
<ObjectDeps Name="Box" Count="0"/>
<Object type="Part::Box" name="Box" id="…" />
</Objects>
<ObjectData Count="1">
<Object name="Box">
<Properties Count="…" TransientCount="…">
…
<Property name="Shape" type="Part::PropertyPartShape" status="…">
<Part ElementMap="…" file="Box.Shape.brp"/>
…
</Property>
…
</Properties>
</Object>
</ObjectData>
</Document>
Not confirmed
- What changed between schema versions 3 and 4: readers treat every version from 3 up the same way, and the history of the change was not found in the sources read.
- The values of
UnitSystem: they come from FreeCAD’s list of unit schemas, which was not read. - The format of the camera text beyond its being an Open Inventor camera node.
- The format of the version string in
ProgramVersionbeyond the pattern built in the code (major, minor,R, revision).
Sources
- File Format FCStd – FreeCAD wiki, with the example Document.xml, read from the FreeCAD-documentation repository
- FreeCAD source code – main branch:
src/App/Document.cppandDocument.h(root, objects, dependencies, document properties, schema 2),src/App/PropertyContainer.cppand.h(properties blocks, type flags),src/App/Property.h(status bits),src/App/DynamicProperty.cpp,src/App/ExtensionContainer.cpp,src/App/StringHasher.cpp,src/Base/Persistence.cpp(attribute encoding),src/Base/Writer.cpp,src/Gui/Document.cpp(GuiDocument.xml),src/Gui/Tree.cpp(Expand),src/Gui/View3DInventor.cpp(camera),src/Gui/ViewProviderDocumentObject.cppandViewProviderGeometryObject.cpp