1
1
import json
2
2
import yaml
3
3
import bson
4
+ import xml .etree .ElementTree as ET
5
+ import xml .dom .minidom
4
6
import sys
5
7
6
8
import numpy as np
@@ -113,6 +115,25 @@ def to_bson(self) -> str:
113
115
"""
114
116
return bson .encode (self .to_dict ())
115
117
118
+ def to_xml (self ) -> str :
119
+ """
120
+ Convert the data dictionary to an XML string representation using the ElementTree library.
121
+ """
122
+ from modelspec .utils import build_xml_element
123
+ root = ET .Element ("root" )
124
+ build_xml_element (root , self .to_dict ())
125
+
126
+ xml_string = ET .tostring (
127
+ root ,
128
+ encoding = 'utf-8' ,
129
+ xml_declaration = False ,
130
+ method = 'xml'
131
+ ).decode ('utf-8' )
132
+
133
+ parsed_xml = xml .dom .minidom .parseString (xml_string )
134
+ pretty_xml = parsed_xml .toprettyxml (indent = " " * 4 )
135
+ return pretty_xml
136
+
116
137
@classmethod
117
138
def from_dict (cls , d : Dict [str , Any ]) -> "Base" :
118
139
"""Instantiate an Base object from a dictionary"""
@@ -144,6 +165,15 @@ def from_bson(cls, bson_str: str) -> "Base":
144
165
"""Instantiate an modelspec object from a BSON string"""
145
166
return cls .from_dict (bson .decode (bson_str ))
146
167
168
+ @classmethod
169
+ def from_xml (cls , xml_str : str ) -> "Base" :
170
+ """Instantiate a Base object from an XML string"""
171
+ from modelspec .utils import _parse_xml_element
172
+
173
+ root = ET .fromstring (xml_str )
174
+ data_dict = _parse_xml_element (root )
175
+ return cls .from_dict (data_dict )
176
+
147
177
def to_json_file (
148
178
self , filename : Optional [str ] = None , include_metadata : bool = True
149
179
) -> str :
@@ -189,7 +219,7 @@ def to_bson_file(self, filename: str, include_metadata: bool = True) -> str:
189
219
)
190
220
outfile .write (bson_data )
191
221
192
- return filename
222
+ return filename
193
223
194
224
def to_yaml (self , include_metadata : bool = True ) -> str :
195
225
"""
@@ -232,6 +262,61 @@ def to_yaml_file(
232
262
)
233
263
234
264
return filename
265
+
266
+
267
+
268
+ def to_xml_file (self , filename : Optional [str ] = None , include_metadata : bool = True ) -> str :
269
+ from modelspec .utils import build_xml_element
270
+
271
+ if filename is None :
272
+ filename = f"{ self .id } .xml"
273
+
274
+ root = ET .Element ("root" ) # Create the root element
275
+
276
+ build_xml_element (root , self .to_dict ())
277
+
278
+ # Create an ElementTree object with the root element
279
+ tree = ET .ElementTree (root )
280
+
281
+ # Generate the XML string
282
+ xml_str = ET .tostring (root , encoding = "utf-8" ).decode ("utf-8" )
283
+
284
+ # Pretty format the XML string using minidom
285
+ #dom = xml.dom.minidom.parseString(xml_str)
286
+ #pretty_xml_str = dom.toprettyxml(indent=" ")
287
+
288
+ # Write the formatted XML data to the file
289
+ with open (filename , "w" , encoding = "utf-8" ) as file :
290
+ file .write (xml_str )
291
+
292
+ return filename
293
+
294
+
295
+
296
+ # def to_xml_file(self, filename: Optional[str] = None, include_metadata: bool = True) -> str:
297
+ # from modelspec.utils import build_xml_element
298
+ # if filename is None:
299
+ # filename = f"{self.id}.xml"
300
+
301
+ # root = ET.Element("root") # Create the root element
302
+
303
+ # # Convert self to dictionary representation (assuming self.to_dict() returns a dictionary)
304
+ # model_dict = self.to_dict()
305
+
306
+ # # Create XML elements based on the dictionary
307
+ # build_xml_element(root, model_dict)
308
+
309
+ # xml_data = ET.tostring(root, encoding="utf-8", xml_declaration=True)
310
+
311
+ # # Create a pretty-formatted XML string using minidom
312
+ # xml_dom = xml.dom.minidom.parseString(xml_data)
313
+ # pretty_xml_str = xml_dom.toprettyxml(indent=" ")
314
+
315
+ # with open(filename, "w") as file:
316
+ # file.write(pretty_xml_str)
317
+
318
+ # return filename
319
+
235
320
236
321
@classmethod
237
322
def from_file (cls , filename : str ) -> "Base" :
@@ -251,6 +336,8 @@ def from_file(cls, filename: str) -> "Base":
251
336
return cls .from_json_file (filename )
252
337
elif filename .endswith (".bson" ):
253
338
return cls .from_bson_file (filename )
339
+ elif filename .endswith (".xml" ):
340
+ return cls .from_xml_file (filename )
254
341
else :
255
342
raise ValueError (
256
343
f"Cannot auto-detect modelspec serialization format from filename ({ filename } ). The filename "
@@ -303,6 +390,26 @@ def from_yaml_file(cls, filename: str) -> "Base":
303
390
d = yaml .safe_load (infile )
304
391
d = yaml_converter .structure (d , Dict )
305
392
return cls .from_dict (d )
393
+
394
+ @classmethod
395
+ def from_xml_file (cls , filename : str ) -> "Base" :
396
+ """
397
+ Create a Base from its XML representation stored in a file.
398
+
399
+ Args:
400
+ filename: The file from which to load the XML data.
401
+
402
+ Returns:
403
+ A modelspec Base for this XML.
404
+ """
405
+ from modelspec .utils import _parse_xml_element
406
+
407
+ with open (filename ) as infile :
408
+ tree = ET .parse (filename )
409
+ root = tree .getroot ()
410
+
411
+ data_dict = _parse_xml_element (root )
412
+ return cls .from_dict (data_dict )
306
413
307
414
def get_child (self , id : str , type_ : str ) -> Any :
308
415
"""
0 commit comments