1###############################################################################
2#
3# Relationships - A class for writing the Excel XLSX Worksheet file.
4#
5# SPDX-License-Identifier: BSD-2-Clause
6#
7# Copyright (c) 2013-2025, John McNamara, jmcnamara@cpan.org
8#
9
10# Package imports.
11from . import xmlwriter
12
13# Long namespace strings used in the class.
14SCHEMA_ROOT = "http://schemas.openxmlformats.org"
15PACKAGE_SCHEMA = SCHEMA_ROOT + "/package/2006/relationships"
16DOCUMENT_SCHEMA = SCHEMA_ROOT + "/officeDocument/2006/relationships"
17
18
19class Relationships(xmlwriter.XMLwriter):
20 """
21 A class for writing the Excel XLSX Relationships file.
22
23
24 """
25
26 ###########################################################################
27 #
28 # Public API.
29 #
30 ###########################################################################
31
32 def __init__(self):
33 """
34 Constructor.
35
36 """
37
38 super().__init__()
39
40 self.relationships = []
41 self.id = 1
42
43 ###########################################################################
44 #
45 # Private API.
46 #
47 ###########################################################################
48
49 def _assemble_xml_file(self):
50 # Assemble and write the XML file.
51
52 # Write the XML declaration.
53 self._xml_declaration()
54
55 self._write_relationships()
56
57 # Close the file.
58 self._xml_close()
59
60 def _add_document_relationship(self, rel_type, target, target_mode=None):
61 # Add container relationship to XLSX .rels xml files.
62 rel_type = DOCUMENT_SCHEMA + rel_type
63
64 self.relationships.append((rel_type, target, target_mode))
65
66 def _add_package_relationship(self, rel_type, target):
67 # Add container relationship to XLSX .rels xml files.
68 rel_type = PACKAGE_SCHEMA + rel_type
69
70 self.relationships.append((rel_type, target, None))
71
72 def _add_ms_package_relationship(self, rel_type, target):
73 # Add container relationship to XLSX .rels xml files. Uses MS schema.
74 schema = "http://schemas.microsoft.com/office/2006/relationships"
75 rel_type = schema + rel_type
76
77 self.relationships.append((rel_type, target, None))
78
79 def _add_rich_value_relationship(self):
80 # Add RichValue relationship to XLSX .rels xml files.
81 schema = "http://schemas.microsoft.com/office/2022/10/relationships/"
82 rel_type = schema + "richValueRel"
83 target = "richData/richValueRel.xml"
84 self.relationships.append((rel_type, target, None))
85
86 schema = "http://schemas.microsoft.com/office/2017/06/relationships/"
87 rel_type = schema + "rdRichValue"
88 target = "richData/rdrichvalue.xml"
89 self.relationships.append((rel_type, target, None))
90
91 rel_type = schema + "rdRichValueStructure"
92 target = "richData/rdrichvaluestructure.xml"
93 self.relationships.append((rel_type, target, None))
94
95 rel_type = schema + "rdRichValueTypes"
96 target = "richData/rdRichValueTypes.xml"
97 self.relationships.append((rel_type, target, None))
98
99 def _add_feature_bag_relationship(self):
100 # Add FeaturePropertyBag relationship to XLSX .rels xml files.
101 schema = "http://schemas.microsoft.com/office/2022/11/relationships/"
102 rel_type = schema + "FeaturePropertyBag"
103 target = "featurePropertyBag/featurePropertyBag.xml"
104 self.relationships.append((rel_type, target, None))
105
106 ###########################################################################
107 #
108 # XML methods.
109 #
110 ###########################################################################
111
112 def _write_relationships(self):
113 # Write the <Relationships> element.
114 attributes = [
115 (
116 "xmlns",
117 PACKAGE_SCHEMA,
118 )
119 ]
120
121 self._xml_start_tag("Relationships", attributes)
122
123 for relationship in self.relationships:
124 self._write_relationship(relationship)
125
126 self._xml_end_tag("Relationships")
127
128 def _write_relationship(self, relationship):
129 # Write the <Relationship> element.
130 rel_type, target, target_mode = relationship
131
132 attributes = [
133 ("Id", "rId" + str(self.id)),
134 ("Type", rel_type),
135 ("Target", target),
136 ]
137
138 self.id += 1
139
140 if target_mode:
141 attributes.append(("TargetMode", target_mode))
142
143 self._xml_empty_tag("Relationship", attributes)