Skip to content

Note

Note class for “text:note” tag.

Classes:

Name Description
Note

A note (footnote or endnote), “text:note”.

NoteBody

Container for the content of a note, “text:note-body”.

NoteMixin

Mixin class for classes containing Notes.

Note

Bases: MDNote, LinkMixin, Element

A note (footnote or endnote), “text:note”.

Either a footnote or a endnote element with the given text, optionally referencing it using the given note_id.

Methods:

Name Description
__init__

Initialize a Note element (footnote or endnote).

__str__
check_validity

Check the validity of the note’s properties.

Attributes:

Name Type Description
NOTE_CLASS ClassVar
citation str

Get the text content of the note citation.

label str

Get the text:label attribute of the note citation.

note_body str

Get the text content of the note body.

note_class
note_id
Source code in odfdo/note.py
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
class Note(MDNote, LinkMixin, Element):
    """A note (footnote or endnote), "text:note".

    Either a footnote or a endnote element with the given text, optionally
    referencing it using the given note_id.
    """

    _tag = "text:note"
    _properties: tuple[PropDef | PropDefBool, ...] = (
        PropDef("note_class", "text:note-class"),
        PropDef("note_id", "text:id"),
    )
    NOTE_CLASS: ClassVar = {"footnote", "endnote"}

    def __init__(
        self,
        note_class: str = "footnote",
        note_id: str | None = None,
        citation: str | None = None,
        label: str | None = None,
        body: str | None = None,
        **kwargs: Any,
    ) -> None:
        """Initialize a Note element (footnote or endnote).

        A note can be either auto-numbered or have a fixed label:

        - **Auto-numbered**: the consumer (e.g. LibreOffice) generates the
          citation number from <text:notes-configuration>. Create this by
          providing only "citation" (pre-filled display text) or nothing at
          all. No "text:label" attribute is written.

        - **Labeled**: the note carries a fixed label. Create this by providing
          "label" (sets the "text:label" attribute). If "citation" is not
          given, the display text defaults to the label value.

        Args:
            note_class: The class of the note ("footnote" or "endnote").
                Defaults to "footnote".
            note_id: A unique ID for the note. If None, one is generated.
            citation: The display text of the note citation. If provided alone,
                the note is auto-numbered (no text:label attribute).
            label: The fixed label value (text:label attribute). When provided
                without citation, the display text defaults to this value.
            body: The content of the note body. Can be a string or an `Element`.
            **kwargs: Additional keyword arguments for the parent `Element` class.
        """
        super().__init__(**kwargs)
        if self._do_init:
            self.insert(Element.from_tag("text:note-body"), position=0)
            self.insert(Element.from_tag("text:note-citation"), position=0)
            self.note_class = note_class
            if note_id is not None:
                self.note_id = note_id
            if label is not None and citation is None:
                self.label = label
                self.citation = label
            elif label is not None and citation is not None:
                self.label = label
                self.citation = citation
            elif citation is not None:
                self.citation = citation
            if body is not None:
                self.note_body = body

    @property
    def citation(self) -> str:
        """Get the text content of the note citation.

        Returns:
            str: The citation text, or an empty string if not found.
        """
        note_citation = self.get_element("text:note-citation")
        if note_citation:
            return note_citation.text
        return ""

    @citation.setter
    def citation(self, text: str | None) -> None:
        """Set the text content of the note citation.

        Args:
            text: The new citation text.
        """
        note_citation = self.get_element("text:note-citation")
        if note_citation:
            note_citation.text = text

    @property
    def label(self) -> str:
        """Get the text:label attribute of the note citation.

        Returns:
            str: The label value, or an empty string if not found.
        """
        note_citation = self.get_element("text:note-citation")
        if note_citation:
            value = note_citation.get_attribute("text:label")
            return str(value or "")
        return ""

    @label.setter
    def label(self, text: str | None) -> None:
        """Set the text:label attribute of the note citation.

        Args:
            text: The new label value, or None to remove the attribute.
        """
        note_citation = self.get_element("text:note-citation")
        if note_citation:
            note_citation.set_attribute("text:label", text)

    @property
    def note_body(self) -> str:
        """Get the text content of the note body.

        Returns:
            str: The content of the note body, or an empty string if not
                 found.
        """
        note_body = self.get_element("text:note-body")
        if note_body:
            return note_body.text_content
        return ""

    @note_body.setter
    def note_body(
        self, text_or_element: Iterable[Element] | Element | str | None
    ) -> None:
        """Set the content of the note body.

        Args:
            text_or_element: The new content for the note body.
                Can be a string, an `Element`, an Iterable of `Element` or
                None to clear the content.
        """
        note_body = self.get_element("text:note-body")
        if not note_body:
            return None
        if text_or_element is None:
            note_body.text_content = ""
        elif isinstance(text_or_element, str):
            note_body.text_content = text_or_element
        elif isinstance(text_or_element, Element):
            note_body.clear()
            note_body.append(text_or_element)
        elif isinstance(text_or_element, Iterable):
            note_body.clear()
            for element in text_or_element:
                if isinstance(element, Element):
                    note_body.append(element)
        else:
            raise TypeError(f'Unexpected type for body: "{type(text_or_element)}"')

    def check_validity(self) -> None:
        """Check the validity of the note's properties.

        Ensures that `note_class` is valid, and that `note_id` and `citation`
        are not empty.

        Raises:
            ValueError: If `note_class` is invalid, or if `note_id` or
                `citation` are empty.
        """
        if not self.note_class or self.note_class not in self.NOTE_CLASS:
            raise ValueError('Note class must be "footnote" or "endnote"')
        if not self.note_id:
            raise ValueError("Note must have an id")
        if not self.citation:
            raise ValueError("Note must have a citation")
        if not self.note_body:
            pass

    def __str__(self) -> str:
        if self.citation:
            return f"{self.citation}. {self.note_body}"
        return self.note_body

NOTE_CLASS class-attribute instance-attribute

NOTE_CLASS: ClassVar = {'footnote', 'endnote'}

_properties class-attribute instance-attribute

_properties: tuple[PropDef | PropDefBool, ...] = (
    PropDef("note_class", "text:note-class"),
    PropDef("note_id", "text:id"),
)

_tag class-attribute instance-attribute

_tag = 'text:note'

citation property writable

citation: str

Get the text content of the note citation.

Returns:

Name Type Description
str str

The citation text, or an empty string if not found.

label property writable

label: str

Get the text:label attribute of the note citation.

Returns:

Name Type Description
str str

The label value, or an empty string if not found.

note_body property writable

note_body: str

Get the text content of the note body.

Returns:

Name Type Description
str str

The content of the note body, or an empty string if not found.

note_class instance-attribute

note_class = note_class

note_id instance-attribute

note_id = note_id

__init__

__init__(
    note_class: str = "footnote",
    note_id: str | None = None,
    citation: str | None = None,
    label: str | None = None,
    body: str | None = None,
    **kwargs: Any,
) -> None

Initialize a Note element (footnote or endnote).

A note can be either auto-numbered or have a fixed label:

  • Auto-numbered: the consumer (e.g. LibreOffice) generates the citation number from . Create this by providing only “citation” (pre-filled display text) or nothing at all. No “text:label” attribute is written.

  • Labeled: the note carries a fixed label. Create this by providing “label” (sets the “text:label” attribute). If “citation” is not given, the display text defaults to the label value.

Parameters:

Name Type Description Default
note_class str

The class of the note (“footnote” or “endnote”). Defaults to “footnote”.

'footnote'
note_id str | None

A unique ID for the note. If None, one is generated.

None
citation str | None

The display text of the note citation. If provided alone, the note is auto-numbered (no text:label attribute).

None
label str | None

The fixed label value (text:label attribute). When provided without citation, the display text defaults to this value.

None
body str | None

The content of the note body. Can be a string or an Element.

None
**kwargs Any

Additional keyword arguments for the parent Element class.

{}
Source code in odfdo/note.py
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
def __init__(
    self,
    note_class: str = "footnote",
    note_id: str | None = None,
    citation: str | None = None,
    label: str | None = None,
    body: str | None = None,
    **kwargs: Any,
) -> None:
    """Initialize a Note element (footnote or endnote).

    A note can be either auto-numbered or have a fixed label:

    - **Auto-numbered**: the consumer (e.g. LibreOffice) generates the
      citation number from <text:notes-configuration>. Create this by
      providing only "citation" (pre-filled display text) or nothing at
      all. No "text:label" attribute is written.

    - **Labeled**: the note carries a fixed label. Create this by providing
      "label" (sets the "text:label" attribute). If "citation" is not
      given, the display text defaults to the label value.

    Args:
        note_class: The class of the note ("footnote" or "endnote").
            Defaults to "footnote".
        note_id: A unique ID for the note. If None, one is generated.
        citation: The display text of the note citation. If provided alone,
            the note is auto-numbered (no text:label attribute).
        label: The fixed label value (text:label attribute). When provided
            without citation, the display text defaults to this value.
        body: The content of the note body. Can be a string or an `Element`.
        **kwargs: Additional keyword arguments for the parent `Element` class.
    """
    super().__init__(**kwargs)
    if self._do_init:
        self.insert(Element.from_tag("text:note-body"), position=0)
        self.insert(Element.from_tag("text:note-citation"), position=0)
        self.note_class = note_class
        if note_id is not None:
            self.note_id = note_id
        if label is not None and citation is None:
            self.label = label
            self.citation = label
        elif label is not None and citation is not None:
            self.label = label
            self.citation = citation
        elif citation is not None:
            self.citation = citation
        if body is not None:
            self.note_body = body

__str__

__str__() -> str
Source code in odfdo/note.py
281
282
283
284
def __str__(self) -> str:
    if self.citation:
        return f"{self.citation}. {self.note_body}"
    return self.note_body

check_validity

check_validity() -> None

Check the validity of the note’s properties.

Ensures that note_class is valid, and that note_id and citation are not empty.

Raises:

Type Description
ValueError

If note_class is invalid, or if note_id or citation are empty.

Source code in odfdo/note.py
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
def check_validity(self) -> None:
    """Check the validity of the note's properties.

    Ensures that `note_class` is valid, and that `note_id` and `citation`
    are not empty.

    Raises:
        ValueError: If `note_class` is invalid, or if `note_id` or
            `citation` are empty.
    """
    if not self.note_class or self.note_class not in self.NOTE_CLASS:
        raise ValueError('Note class must be "footnote" or "endnote"')
    if not self.note_id:
        raise ValueError("Note must have an id")
    if not self.citation:
        raise ValueError("Note must have a citation")
    if not self.note_body:
        pass

NoteBody

Bases: ListMixin, TocMixin, LinkMixin, SectionMixin

Container for the content of a note, “text:note-body”.

Source code in odfdo/note.py
101
102
103
104
105
class NoteBody(ListMixin, TocMixin, LinkMixin, SectionMixin):
    """Container for the content of a note, "text:note-body"."""

    _tag: str = "text:note-body"
    _properties: tuple[PropDef | PropDefBool, ...] = ()

_properties class-attribute instance-attribute

_properties: tuple[PropDef | PropDefBool, ...] = ()

_tag class-attribute instance-attribute

_tag: str = 'text:note-body'

NoteMixin

Bases: Element

Mixin class for classes containing Notes.

Used by the following classes: “text:a”, “text:h”, “text:meta”, “text:meta-field”, “text:p”, “text:ruby-base”, “text:span”. And with “office:text” for compatibility with previous versions.

Methods:

Name Description
get_note

Retrieve a specific note (text:note) that matches the specified

get_notes

Retrieve all notes (text:note) that match the specified criteria.

Source code in odfdo/note.py
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
class NoteMixin(Element):
    """Mixin class for classes containing Notes.

    Used by the following classes: "text:a", "text:h", "text:meta", "text:meta-field",
    "text:p", "text:ruby-base", "text:span". And with "office:text" for compatibility
    with previous versions.
    """

    def get_notes(
        self,
        note_class: str | None = None,
        content: str | None = None,
    ) -> list[Note]:
        """Retrieve all notes (`text:note`) that match the specified criteria.

        Args:
            note_class: Filter by note class ("footnote" or "endnote").
            content: A regular expression to match against the note's content.

        Returns:
            list[Note]: A list of `Note` instances matching the criteria.
        """
        return cast(
            list[Note],
            self._filtered_elements(
                "descendant::text:note", note_class=note_class, content=content
            ),
        )

    def get_note(
        self,
        position: int = 0,
        note_id: str | None = None,
        note_class: str | None = None,
        content: str | None = None,
    ) -> Note | None:
        """Retrieve a specific note (`text:note`) that matches the specified
           criteria.

        Args:
            position: The 0-based index of the matching note to retrieve if
                multiple match the other criteria. Defaults to 0.
            note_id: The unique ID of the note.
            note_class: Filter by note class ("footnote" or "endnote").
            content: A regular expression to match against the note's content.

        Returns:
            Note | None: A `Note` instance matching the criteria, or `None`
                if not found.
        """
        return cast(
            None | Note,
            self._filtered_element(
                "descendant::text:note",
                position,
                text_id=note_id,
                note_class=note_class,
                content=content,
            ),
        )

get_note

get_note(
    position: int = 0,
    note_id: str | None = None,
    note_class: str | None = None,
    content: str | None = None,
) -> Note | None

Retrieve a specific note (text:note) that matches the specified criteria.

Parameters:

Name Type Description Default
position int

The 0-based index of the matching note to retrieve if multiple match the other criteria. Defaults to 0.

0
note_id str | None

The unique ID of the note.

None
note_class str | None

Filter by note class (“footnote” or “endnote”).

None
content str | None

A regular expression to match against the note’s content.

None

Returns:

Type Description
Note | None

Note | None: A Note instance matching the criteria, or None if not found.

Source code in odfdo/note.py
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
def get_note(
    self,
    position: int = 0,
    note_id: str | None = None,
    note_class: str | None = None,
    content: str | None = None,
) -> Note | None:
    """Retrieve a specific note (`text:note`) that matches the specified
       criteria.

    Args:
        position: The 0-based index of the matching note to retrieve if
            multiple match the other criteria. Defaults to 0.
        note_id: The unique ID of the note.
        note_class: Filter by note class ("footnote" or "endnote").
        content: A regular expression to match against the note's content.

    Returns:
        Note | None: A `Note` instance matching the criteria, or `None`
            if not found.
    """
    return cast(
        None | Note,
        self._filtered_element(
            "descendant::text:note",
            position,
            text_id=note_id,
            note_class=note_class,
            content=content,
        ),
    )

get_notes

get_notes(
    note_class: str | None = None,
    content: str | None = None,
) -> list[Note]

Retrieve all notes (text:note) that match the specified criteria.

Parameters:

Name Type Description Default
note_class str | None

Filter by note class (“footnote” or “endnote”).

None
content str | None

A regular expression to match against the note’s content.

None

Returns:

Type Description
list[Note]

list[Note]: A list of Note instances matching the criteria.

Source code in odfdo/note.py
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
def get_notes(
    self,
    note_class: str | None = None,
    content: str | None = None,
) -> list[Note]:
    """Retrieve all notes (`text:note`) that match the specified criteria.

    Args:
        note_class: Filter by note class ("footnote" or "endnote").
        content: A regular expression to match against the note's content.

    Returns:
        list[Note]: A list of `Note` instances matching the criteria.
    """
    return cast(
        list[Note],
        self._filtered_elements(
            "descendant::text:note", note_class=note_class, content=content
        ),
    )