0
# Data Export and Import
1
2
Comprehensive functionality for exporting tree structures to various formats including JSON, dictionaries, and GraphViz DOT files. Enables integration with other systems, data persistence, and visualization workflows.
3
4
## Capabilities
5
6
### JSON Export
7
8
Export tree structure and data to JSON format for serialization and data exchange.
9
10
```python { .api }
11
def to_json(with_data=False, sort=True, reverse=False) -> str:
12
"""
13
Export tree structure to JSON string.
14
15
Parameters:
16
- with_data: bool, include node data in output
17
- sort: bool, sort nodes by tag for consistent output
18
- reverse: bool, reverse sort order
19
20
Returns:
21
str, JSON representation of tree structure
22
"""
23
```
24
25
**Usage Examples:**
26
27
```python
28
# Basic JSON export (structure only)
29
json_structure = tree.to_json()
30
print(json_structure)
31
32
# Export with node data included
33
json_with_data = tree.to_json(with_data=True)
34
35
# Sorted export for consistent output
36
json_sorted = tree.to_json(sort=True, reverse=False)
37
38
# Save to file
39
import json
40
tree_data = json.loads(tree.to_json(with_data=True))
41
with open("organization.json", "w") as f:
42
json.dump(tree_data, f, indent=2)
43
44
# Load and process JSON data
45
import json
46
json_str = tree.to_json(with_data=True)
47
parsed_data = json.loads(json_str)
48
print(f"Root node: {parsed_data}")
49
```
50
51
### Dictionary Export
52
53
Convert tree to nested dictionary structure for programmatic manipulation.
54
55
```python { .api }
56
def to_dict(nid=None, key=None, sort=True, reverse=False, with_data=False) -> dict:
57
"""
58
Convert tree to nested dictionary representation.
59
60
Parameters:
61
- nid: str, root node for subtree export (default: entire tree)
62
- key: callable, function for sorting nodes (node) -> comparable
63
- sort: bool, sort nodes for consistent output
64
- reverse: bool, reverse sort order
65
- with_data: bool, include node data in output
66
67
Returns:
68
dict, nested dictionary representation of tree
69
"""
70
```
71
72
**Usage Examples:**
73
74
```python
75
# Export entire tree to dictionary
76
tree_dict = tree.to_dict()
77
print(tree_dict)
78
79
# Export specific subtree
80
dept_dict = tree.to_dict(nid="engineering")
81
82
# Export with custom sorting
83
sorted_dict = tree.to_dict(
84
key=lambda node: node.tag.lower(),
85
sort=True
86
)
87
88
# Export with node data
89
data_dict = tree.to_dict(with_data=True)
90
91
# Process dictionary data
92
def analyze_tree_dict(tree_dict, level=0):
93
"""Recursively analyze tree dictionary."""
94
indent = " " * level
95
for key, value in tree_dict.items():
96
print(f"{indent}{key}")
97
if isinstance(value, dict):
98
analyze_tree_dict(value, level + 1)
99
100
analyze_tree_dict(tree.to_dict())
101
102
# Convert to pandas DataFrame for analysis
103
import pandas as pd
104
105
def tree_to_dataframe(tree_dict, parent=None, level=0):
106
"""Convert tree dictionary to flat DataFrame."""
107
rows = []
108
for key, children in tree_dict.items():
109
row = {"node": key, "parent": parent, "level": level}
110
rows.append(row)
111
if isinstance(children, dict):
112
rows.extend(tree_to_dataframe(children, key, level + 1))
113
return rows
114
115
df = pd.DataFrame(tree_to_dataframe(tree.to_dict()))
116
print(df)
117
```
118
119
### GraphViz DOT Export
120
121
Export tree to GraphViz DOT format for advanced graph visualization and layout.
122
123
```python { .api }
124
def to_graphviz(filename=None, shape="circle", graph="digraph", filter=None,
125
key=None, reverse=False, sorting=True) -> None:
126
"""
127
Export tree to GraphViz DOT format.
128
129
Parameters:
130
- filename: str, output filename (prints to stdout if None)
131
- shape: str, node shape ("circle", "box", "ellipse", etc.)
132
- graph: str, graph type ("digraph" or "graph")
133
- filter: callable, function to filter nodes (node) -> bool
134
- key: callable, function for sorting nodes (node) -> comparable
135
- reverse: bool, reverse sort order
136
- sorting: bool, enable/disable sorting
137
"""
138
```
139
140
**Usage Examples:**
141
142
```python
143
# Export to GraphViz DOT format
144
tree.to_graphviz("organization.dot")
145
146
# Customize node appearance
147
tree.to_graphviz("org_boxes.dot", shape="box")
148
149
# Create undirected graph
150
tree.to_graphviz("org_undirected.dot", graph="graph")
151
152
# Export with filtering
153
tree.to_graphviz(
154
"managers_only.dot",
155
filter=lambda node: node.data and node.data.get("is_manager", False)
156
)
157
158
# Generate and view GraphViz output
159
import subprocess
160
import os
161
162
# Export to DOT file
163
tree.to_graphviz("tree.dot", shape="box")
164
165
# Generate SVG using GraphViz
166
if os.system("which dot") == 0: # Check if GraphViz installed
167
subprocess.run(["dot", "-Tsvg", "tree.dot", "-o", "tree.svg"])
168
print("Generated tree.svg")
169
170
# Custom DOT generation for complex styling
171
def custom_graphviz_export(tree, filename):
172
"""Generate custom DOT file with advanced styling."""
173
with open(filename, "w") as f:
174
f.write("digraph Tree {\n")
175
f.write(" node [fontname=\"Arial\"];\n")
176
f.write(" edge [color=gray];\n")
177
178
for node_id in tree.expand_tree():
179
node = tree[node_id]
180
# Custom node styling based on data
181
if node.data and node.data.get("role") == "manager":
182
style = "filled,style=filled,color=lightblue"
183
else:
184
style = "filled,style=filled,color=lightgray"
185
186
f.write(f' "{node_id}" [label="{node.tag}",{style}];\n')
187
188
# Add edges
189
children = tree.children(node_id)
190
for child in children:
191
f.write(f' "{node_id}" -> "{child.identifier}";\n')
192
193
f.write("}\n")
194
195
custom_graphviz_export(tree, "custom_tree.dot")
196
```
197
198
### Tree Construction from Data
199
200
Create trees from various data formats and sources.
201
202
```python { .api }
203
@classmethod
204
def from_map(cls, child_parent_dict, id_func=None, data_func=None) -> Tree:
205
"""
206
Create tree from child-parent mapping dictionary.
207
208
Parameters:
209
- child_parent_dict: dict, mapping of child -> parent relationships
210
- id_func: callable, function to generate node identifiers from keys
211
- data_func: callable, function to generate node data from keys
212
213
Returns:
214
Tree, constructed tree object
215
"""
216
```
217
218
**Usage Examples:**
219
220
```python
221
# Create tree from relationship mapping
222
org_structure = {
223
"alice": "engineering",
224
"bob": "engineering",
225
"carol": "sales",
226
"dave": "sales",
227
"engineering": "company",
228
"sales": "company",
229
"company": None # Root node
230
}
231
232
tree = Tree.from_map(org_structure)
233
234
# With custom ID function
235
file_structure = {
236
"/home/user/doc.txt": "/home/user",
237
"/home/user/photo.jpg": "/home/user",
238
"/home/user": "/home",
239
"/home": None
240
}
241
242
file_tree = Tree.from_map(
243
file_structure,
244
id_func=lambda path: path.replace("/", "_").strip("_")
245
)
246
247
# With data function
248
employee_data = {
249
"alice": {"role": "engineer", "salary": 120000},
250
"bob": {"role": "engineer", "salary": 110000},
251
"carol": {"role": "sales", "salary": 95000}
252
}
253
254
org_mapping = {
255
"alice": "engineering",
256
"bob": "engineering",
257
"carol": "sales",
258
"engineering": "company",
259
"sales": "company",
260
"company": None
261
}
262
263
tree_with_data = Tree.from_map(
264
org_mapping,
265
data_func=lambda name: employee_data.get(name, {})
266
)
267
```
268
269
### Data Persistence and Serialization
270
271
Save and load tree structures for persistence and backup.
272
273
**Usage Examples:**
274
275
```python
276
import json
277
import pickle
278
from datetime import datetime
279
280
# JSON persistence
281
def save_tree_json(tree, filename):
282
"""Save tree to JSON file with metadata."""
283
tree_data = {
284
"metadata": {
285
"created": datetime.now().isoformat(),
286
"node_count": len(tree),
287
"tree_depth": tree.depth()
288
},
289
"structure": json.loads(tree.to_json()),
290
"data": {}
291
}
292
293
# Save node data separately
294
for node_id in tree.expand_tree():
295
node = tree[node_id]
296
if node.data:
297
tree_data["data"][node_id] = node.data
298
299
with open(filename, "w") as f:
300
json.dump(tree_data, f, indent=2)
301
302
def load_tree_json(filename):
303
"""Load tree from JSON file."""
304
with open(filename, "r") as f:
305
tree_data = json.load(f)
306
307
# Reconstruct tree from structure
308
# (Implementation would depend on JSON structure format)
309
print(f"Loaded tree with {tree_data['metadata']['node_count']} nodes")
310
return tree_data
311
312
# Binary persistence with pickle
313
def save_tree_pickle(tree, filename):
314
"""Save tree using pickle for exact preservation."""
315
with open(filename, "wb") as f:
316
pickle.dump(tree, f)
317
318
def load_tree_pickle(filename):
319
"""Load tree from pickle file."""
320
with open(filename, "rb") as f:
321
return pickle.load(f)
322
323
# Usage
324
save_tree_json(tree, "organization.json")
325
save_tree_pickle(tree, "organization.pkl")
326
327
loaded_tree = load_tree_pickle("organization.pkl")
328
```
329
330
### Format Conversion and Integration
331
332
Convert between different tree formats and integrate with external systems.
333
334
**Usage Examples:**
335
336
```python
337
# Convert to networkx graph
338
try:
339
import networkx as nx
340
341
def tree_to_networkx(tree):
342
"""Convert treelib Tree to networkx DiGraph."""
343
G = nx.DiGraph()
344
345
for node_id in tree.expand_tree():
346
node = tree[node_id]
347
G.add_node(node_id,
348
tag=node.tag,
349
data=node.data)
350
351
parent = tree.parent(node_id)
352
if parent:
353
G.add_edge(parent.identifier, node_id)
354
355
return G
356
357
nx_graph = tree_to_networkx(tree)
358
print(f"NetworkX graph with {nx_graph.number_of_nodes()} nodes")
359
360
except ImportError:
361
print("NetworkX not available")
362
363
# Export to CSV for spreadsheet analysis
364
import csv
365
366
def tree_to_csv(tree, filename):
367
"""Export tree to CSV with hierarchical information."""
368
with open(filename, "w", newline="") as f:
369
writer = csv.writer(f)
370
writer.writerow(["node_id", "tag", "parent_id", "level", "is_leaf", "data"])
371
372
for node_id in tree.expand_tree():
373
node = tree[node_id]
374
parent = tree.parent(node_id)
375
parent_id = parent.identifier if parent else None
376
377
writer.writerow([
378
node_id,
379
node.tag,
380
parent_id,
381
tree.level(node_id),
382
node.is_leaf(tree.identifier),
383
str(node.data) if node.data else ""
384
])
385
386
tree_to_csv(tree, "organization.csv")
387
388
# Import from external hierarchical data
389
def import_from_filesystem(root_path):
390
"""Create tree from filesystem structure."""
391
import os
392
393
tree = Tree()
394
tree.create_node(root_path, root_path)
395
396
def add_directory_tree(parent_path, parent_id):
397
try:
398
for item in os.listdir(parent_path):
399
item_path = os.path.join(parent_path, item)
400
item_id = item_path
401
402
if os.path.isdir(item_path):
403
tree.create_node(f"π {item}", item_id, parent=parent_id)
404
add_directory_tree(item_path, item_id)
405
else:
406
tree.create_node(f"π {item}", item_id, parent=parent_id)
407
except PermissionError:
408
pass # Skip inaccessible directories
409
410
add_directory_tree(root_path, root_path)
411
return tree
412
413
# Usage
414
fs_tree = import_from_filesystem("/tmp")
415
fs_tree.show()
416
```
417
418
### Advanced Export Patterns
419
420
Sophisticated export scenarios for complex use cases.
421
422
**Usage Examples:**
423
424
```python
425
# Multi-format export pipeline
426
def export_tree_all_formats(tree, base_filename):
427
"""Export tree to multiple formats."""
428
formats = {
429
"json": lambda: tree.to_json(with_data=True),
430
"dict": lambda: str(tree.to_dict(with_data=True)),
431
"dot": lambda: tree.to_graphviz(f"{base_filename}.dot")
432
}
433
434
results = {}
435
for fmt, export_func in formats.items():
436
try:
437
if fmt == "dot":
438
export_func() # Writes to file
439
results[fmt] = f"{base_filename}.dot"
440
else:
441
content = export_func()
442
filename = f"{base_filename}.{fmt}"
443
with open(filename, "w") as f:
444
f.write(content)
445
results[fmt] = filename
446
except Exception as e:
447
results[fmt] = f"Error: {e}"
448
449
return results
450
451
# Incremental export for large trees
452
def export_tree_incremental(tree, chunk_size=1000):
453
"""Export large tree in chunks."""
454
all_nodes = list(tree.expand_tree())
455
chunks = [all_nodes[i:i+chunk_size] for i in range(0, len(all_nodes), chunk_size)]
456
457
for i, chunk in enumerate(chunks):
458
chunk_data = {}
459
for node_id in chunk:
460
node = tree[node_id]
461
chunk_data[node_id] = {
462
"tag": node.tag,
463
"data": node.data,
464
"parent": tree.parent(node_id).identifier if tree.parent(node_id) else None
465
}
466
467
with open(f"tree_chunk_{i}.json", "w") as f:
468
json.dump(chunk_data, f, indent=2)
469
470
print(f"Exported {len(chunks)} chunks")
471
472
# Usage
473
export_results = export_tree_all_formats(tree, "organization")
474
print("Export results:", export_results)
475
```