The body of an ODT document, inside office:text, is built from headings
and paragraphs, grouped into lists and sections, with spans, links, notes and marks
inside them. This page covers chapters 5 and 6 of OpenDocument 1.3 part 3. Every element
here is in the text namespace
(urn:oasis:names:tc:opendocument:xmlns:text:1.0) unless shown
otherwise.
Headings and paragraphs
| Element | Meaning | Attributes |
|---|---|---|
text:h | A heading. A chapter or section runs from a heading to the next heading at the same or a higher level. | text:outline-level, text:is-list-header, text:restart-numbering, text:start-value, and the paragraph attributes |
text:p | A paragraph, the basic unit of text. | text:style-name, text:class-names, text:cond-style-name, text:id, xml:id, and the RDFa attributes xhtml:about, xhtml:property, xhtml:content, xhtml:datatype |
| Attribute | Meaning |
|---|---|
text:outline-level | Heading level, from 1. Absent means 1. |
text:is-list-header | true: the heading is not numbered, even with a list style. Default false. |
text:restart-numbering | true: heading numbering restarts here. Default false. |
text:start-value | The number to restart heading numbering at. |
text:style-name | The paragraph style. When a conditional style was applied, this is the style it resolved to. |
text:cond-style-name | The conditional paragraph style itself. |
text:class-names | More paragraph styles, separated by spaces, applied in order after text:style-name. |
text:id, xml:id | Identifiers, for references and RDF metadata. |
The content of both is text mixed with the inline elements below, frames and shapes
anchored to the paragraph, fields, index marks, bookmarks, notes, annotations
(office:annotation, office:annotation-end) and change marks.
The paragraph’s own text is its character data in document order, leaving out note
bodies, ruby text, annotations and the content of shapes and frames.
Spaces, tabs and line breaks
Inside text:p and text:h, white space is collapsed. A reader
must get the result of these steps, or a variant (below) that matches files from
ODF 1.2 writers:
- Replace each
text:rubywith itstext:ruby-base. - Remove descendants that are not
text:s,text:tabortext:line-breakand that cannot themselves contain them. - Replace descendants that can contain them (spans, links and so on) with their content.
- Turn tab (U+0009), carriage return (U+000D) and line feed (U+000A) characters into spaces.
- Remove spaces at the start and end.
- Collapse each run of spaces into one.
- Read the remaining
text:s,text:tabandtext:line-breakas the characters they stand for.
The variant replaces step 2: first remove mark elements (change, bookmark, reference
and index marks), then replace each other removable element with an imagined
<text:s text:c="0"/>, so that spaces either side of it are not
joined.
| Element | Meaning | Attributes |
|---|---|---|
text:s | Spaces. Used for the second and later spaces of a run. | text:c: how many (absent means 1) |
text:tab | A tab character: the text after it aligns at the next tab stop. | text:tab-ref: a hint, the number of the tab stop it goes to (0 is the start margin) |
text:line-break | A line break within the paragraph. | – |
text:soft-page-break | Where the writer’s layout broke the page, inside or between paragraphs, or between table rows. | – |
A soft hyphen is the character U+00AD, a non-breaking hyphen U+2011, and a non-breaking space U+00A0; ODF has no elements for them.
<text:p text:style-name="P1">Two<text:s/> spaces,<text:tab/>a tab and<text:line-break/>a new line.</text:p>
Spans, links and inline metadata
| Element | Meaning | Attributes |
|---|---|---|
text:span | Applies a text (character) style to its content. Can nest. | text:style-name, text:class-names |
text:a | A hyperlink; its text is the anchor. | xlink:href, xlink:type, xlink:show, xlink:actuate, office:name, office:title, office:target-frame-name, text:style-name (unvisited), text:visited-style-name; may contain office:event-listeners |
text:meta | A run of text with RDFa metadata attached. | xml:id, xhtml:about, xhtml:property, xhtml:content, xhtml:datatype |
text:ruby | Ruby: small text above or below a base text, for pronunciation or notes. | text:style-name (a ruby style) |
text:ruby-base | The text being annotated; any paragraph content. | – |
text:ruby-text | The annotation, plain text only. | text:style-name (a text style) |
Lists
A list is text:list, with an optional text:list-header and
then text:list-item elements, each holding paragraphs, headings or another
list. The level of a list is how deeply it is nested: 1 at the top, and back to 1 inside
a table cell or text box. A top-level list is one counting domain for its items and
sub-lists. Whether numbers or bullets show depends on the list style.
| Element | Meaning | Attributes |
|---|---|---|
text:list | A list. | text:style-name (a list style), text:continue-list, text:continue-numbering, xml:id |
text:list-header | Paragraphs before the items, formatted like items but without a number or bullet. | xml:id |
text:list-item | An item. | text:start-value (restart numbering here, numbered lists only), text:style-override (another list style for this item), xml:id |
text:number | The formatted number as text, for readers that do not number lists themselves; others ignore it. | – |
text:numbered-paragraph | Deprecated: one paragraph numbered as if it were in a list at text:level (default 1). | text:level, text:list-id (paragraphs with the same ID form one list), text:start-value, text:style-name, text:continue-numbering, xml:id |
text:continue-listgives thexml:idof a list whose numbering this one continues. It overridestext:continue-numbering, which, whentrue, continues from the list just before if it has the same style.- A list with no style takes its parent list’s style; failing that, a list style set by the paragraph styles inside it; failing that, an implementation’s default.
- If the list style has no style for an item’s level, the parent list’s style for that level is used, then the default list style.
- An item that only starts another list and has no text shows no number.
<text:list xml:id="list1" text:style-name="L1">
<text:list-item><text:p>First</text:p></text:list-item>
<text:list-item><text:p>Second</text:p>
<text:list><text:list-item><text:p>Second, part a</text:p></text:list-item></text:list>
</text:list-item>
</text:list>
Sections and page sequences
| Element | Meaning | Attributes |
|---|---|---|
text:section | A named part of the document with its own formatting (such as columns), possibly hidden, protected or linked to outside content. Holds any body content, including other sections. | text:name, text:style-name (a section style), text:display, text:condition, text:protected, text:protection-key, text:protection-key-digest-algorithm, xml:id |
text:section-source | First child of a linked section: the linked file. | xlink:href, xlink:type, xlink:show, text:section-name (a section in that file), text:filter-name (the import filter) |
office:dde-source | First child of a section linked by DDE instead. | See DDE connections |
text:page-sequence | A sequence of pages, for documents laid out page by page; the first page’s master page is the document’s default. | – |
text:page | One page of a page sequence. | text:master-page-name |
text:display:trueshown (default),nonehidden,conditionhidden whentext:conditionholds. A condition is a namespace prefix, a colon and a formula, such asooow:Page > 1.text:protected:truestops the user editing the section (in the user interface only).text:protection-key: if present, a hash of the password (UTF-8) needed to remove the protection, made with the algorithm intext:protection-key-digest-algorithm: by defaulthttp://www.w3.org/2000/09/xmldsig#sha1; writers should use…#sha256.- A linked section should still contain a full copy of the linked content.
Tracked changes
Changes are recorded in a text:tracked-changes element at the start of
the scope they cover (usually office:text), and marked in the text by
change marks that point at them with text:change-id. The specification
warns that change tracking was under-specified in ODF 1.2 and that programs differ.
| Element | Meaning | Attributes |
|---|---|---|
text:tracked-changes | All changes in its scope. Without it, change marks are ignored. | text:track-changes: whether changes are being recorded (default true) |
text:changed-region | One change, holding exactly one of the next three. | xml:id or text:id, which the marks refer to |
text:insertion | Text was inserted. Holds office:change-info. | – |
text:deletion | Text was deleted. Holds office:change-info and the deleted content, in paragraphs. | – |
text:format-change | Formatting was changed (the old formatting is not stored). Holds office:change-info. | – |
office:change-info | Who and when: dc:creator, dc:date, and optional comment paragraphs. | – |
text:change-start | Start of an inserted or reformatted range. | text:change-id |
text:change-end | End of that range. | text:change-id |
text:change | The point where text was deleted. | text:change-id |
To restore deleted text at a text:change inside a paragraph, insert the
deleted content without the opening tags up to its first text:p and the
closing tags from its last </text:p> or </text:h>,
so the first and last deleted paragraphs merge with the paragraph around the mark (if
the last was a heading, the paragraph becomes one). Inside a heading, the same with
text:h. Elsewhere, insert the deleted content as it is.
<text:tracked-changes>
<text:changed-region xml:id="ct1" text:id="ct1">
<text:deletion>
<office:change-info><dc:creator>Ann</dc:creator><dc:date>2026-11-12T10:00:00</dc:date></office:change-info>
<text:p>old </text:p>
</text:deletion>
</text:changed-region>
</text:tracked-changes>
<text:p>The <text:change text:change-id="ct1"/>text.</text:p>
Bookmarks and reference marks
Both come as a single point or as a start and end pair, matched by
text:name, which must be unique. Ranges may overlap. Bookmarks are what
hyperlinks and cross-reference fields point at; reference marks are what reference
fields point at.
| Element | Meaning | Attributes |
|---|---|---|
text:bookmark | A bookmarked position. | text:name, xml:id |
text:bookmark-start | Start of a bookmarked range. | text:name, xml:id, RDFa attributes |
text:bookmark-end | End of the range. | text:name |
text:reference-mark | A reference position. | text:name |
text:reference-mark-start | Start of a reference range. | text:name |
text:reference-mark-end | End of the range. | text:name |
Footnotes and endnotes
A note sits in the text where it is anchored. How notes are numbered and where they
are printed is set by text:notes-configuration in
office:styles.
| Element | Meaning | Attributes |
|---|---|---|
text:note | A note: text:note-citation then text:note-body. | text:note-class: footnote (foot of the page) or endnote (end of the chapter or document); text:id |
text:note-citation | The mark shown in the text, as a number or string. | text:label: a user’s own mark; absent means the content is used |
text:note-body | The note’s paragraphs, lists and tables. Notes inside notes need not be supported. | – |
<text:p>A claim.<text:note text:id="ftn1" text:note-class="footnote">
<text:note-citation>1</text:note-citation>
<text:note-body><text:p text:style-name="Footnote">The source.</text:p></text:note-body>
</text:note></text:p>
Declarations
These come before the main content of office:text and define things the
text uses: text:variable-decl (variable fields),
text:user-field-decl (user fields), text:sequence-decl
(sequence fields such as figure numbers), text:dde-connection (DDE fields
and sections) and text:alphabetical-index-auto-mark-file (a file of words
to index). Fields themselves are on the fields
and indexes page.