-
-
Notifications
You must be signed in to change notification settings - Fork 24
Expand file tree
/
Copy pathrender_xml.vy
More file actions
108 lines (83 loc) · 1.55 KB
/
render_xml.vy
File metadata and controls
108 lines (83 loc) · 1.55 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
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
99
100
101
102
103
104
105
106
107
108
let invalid-node = "invalid XML node"
let mapping = ... => ...
def qq (s) { str ('"', s, '"') }
let entities = byte^
[
'"': "quot",
'&': "amp",
'<': "lt",
'>': "gt",
]
def escaped (c: byte)
{
if c in entities then
{
return "&" entities[ c ] ";"
}
let code = str int c
return "&#" code ";"
}
def escape_text (text)
{
let echars = text map { if v in "<&" then {escaped v} else {v} }
return str echars
}
def get-name-attrs-content (node)
{
assert node isa mapping
let name = node.key
let data = node.value
var attrs = []
var content = data
if data isa mapping and data.key isa array then
{
# foo: [...]: bar
attrs = data.key
content = data.value
}
return name, attrs, content
}
def render_at_depth (printer, node, depth)
{
let print = printer % depth
if node isa string then
{
print escape_text node
return ()
}
if node isa mapping then
{
let (name, attrs, content) = get-name-attrs-content node
let attr = str( attrs map { " " v.key, "=", qq v.value } )
if content isa null then
{
print "<" name attr "/>"
}
else if content isa string then
{
let inner = escape_text content
print "<" name attr ">" inner "</" name ">"
}
else
{
print "<" name attr ">"
render_at_depth( printer, content, depth + 1 )
print "</" name ">"
}
return ()
}
if node isa array then
{
for subnode in node do
{
render_at_depth( printer, subnode, depth )
}
return ()
}
throw invalid-node
}
export
def render_xml (printer, doc)
{
render_at_depth( printer, doc, 0 )
}