Mercurial > hg > lxmldump
annotate lxmldump.py @ 7:4b4299b62f7f
Moar work.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Tue, 11 May 2021 01:26:57 +0300 |
parents | 34a89d61dbe7 |
children | ce07bb2a247b |
rev | line source |
---|---|
0 | 1 #!/usr/bin/python3 -B |
2 # coding=utf-8 | |
3 ### | |
4 | 4 ### lxmldump - Dump ISO/FDIS 1951 XML file data |
5 ### Programmed and designed by Matti 'ccr' Hämäläinen <ccr@tnsp.org> | |
6 ### (C) Copyright 2021 Tecnic Software productions (TNSP) | |
7 ### | |
8 ### Python 3.7+ required! | |
0 | 9 ### |
10 import sys | |
11 import signal | |
12 import re | |
13 from pathlib import Path | |
14 import xml.etree.ElementTree as xmlET | |
5
274b2091137c
Some more work on cleaning this up.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
15 import unicodedata |
0 | 16 |
17 assert sys.version_info >= (3, 7) | |
18 | |
19 | |
20 ### | |
21 ### Default settings | |
22 ### | |
23 pkk_cfg = { | |
24 "dump": False, | |
5
274b2091137c
Some more work on cleaning this up.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
25 "normalize": False, |
7 | 26 |
27 "debug": False, | |
0 | 28 } |
29 | |
30 | |
7 | 31 pkk_str_fmap = { |
32 "Fragment" : ["<", ">"], | |
33 } | |
34 | |
35 | |
36 pkk_debug_list = [ | |
37 "ahas", | |
38 "ahavakkaine", | |
39 "ahavakala", | |
40 "ahavakoittuo", | |
41 "ahvaliha", | |
42 ] | |
43 | |
44 | |
0 | 45 ### |
46 ### Misc. helper functions, etc | |
47 ### | |
48 def pkk_cleanup(): | |
49 return 0 | |
50 | |
51 | |
52 ## Wrapper for print() | |
5
274b2091137c
Some more work on cleaning this up.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
53 def pkk_print(smsg): |
274b2091137c
Some more work on cleaning this up.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
54 if pkk_cfg["normalize"]: |
274b2091137c
Some more work on cleaning this up.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
55 sys.stdout.write(unicodedata.normalize("NFC", smsg)) |
274b2091137c
Some more work on cleaning this up.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
56 else: |
274b2091137c
Some more work on cleaning this up.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
57 sys.stdout.write(smsg) |
0 | 58 |
7 | 59 def pkk_printi(indent, smsg): |
60 pkk_print((" " * indent) + smsg) | |
61 | |
0 | 62 |
63 ## Fatal error handler | |
64 def pkk_fatal(smsg): | |
65 print(u"ERROR: "+ smsg) | |
66 sys.exit(1) | |
67 | |
68 | |
69 ## Handler for SIGINT signals | |
70 def pkk_signal_handler(signal, frame): | |
71 pkk_cleanup() | |
72 print(u"\nQuitting due to SIGINT / Ctrl+C!") | |
73 sys.exit(1) | |
74 | |
75 | |
7 | 76 def pkk_get_text(lnode): |
77 stmp = "" | |
78 for pnode in lnode.iter(): | |
79 if isinstance(pnode.text, str): | |
80 if isinstance(pnode.tag, str) and pnode.tag in pkk_str_fmap: | |
81 stmp += pkk_str_fmap[pnode.tag][0] + pnode.text + pkk_str_fmap[pnode.tag][1] | |
82 else: | |
83 stmp += pnode.text | |
84 | |
85 if isinstance(pnode.tail, str): | |
86 stmp += pnode.tail | |
87 | |
88 return stmp.strip() | |
89 | |
90 | |
6 | 91 ## |
7 | 92 def pkk_dump_recursive(indent, lnode): |
93 if lnode.tag in ["Example"]: | |
94 stmp = pkk_get_text(lnode) | |
95 pkk_printi(indent, "{} \"{}\"".format(lnode.tag, stmp)) | |
6 | 96 else: |
7 | 97 if isinstance(lnode.text, str): |
98 stmp = lnode.text.strip() | |
99 if stmp != "": | |
100 stmp = " \""+ stmp +"\"" | |
101 else: | |
102 stmp = "" | |
6 | 103 |
104 if len(lnode.attrib) > 0: | |
105 atmp = " "+str(lnode.attrib) | |
106 else: | |
107 atmp = "" | |
108 | |
7 | 109 pkk_printi(indent, "{}{}{}\n".format(lnode.tag, atmp, stmp)) |
6 | 110 for qnode in lnode.findall("./*"): |
7 | 111 pkk_dump_recursive(indent + 1, qnode) |
6 | 112 |
113 | |
114 ## | |
7 | 115 def pkk_output_one(indent, dnode, dsub): |
116 for qnode in dnode.findall(dsub): | |
117 pkk_printi(indent, "{}\n".format(pkk_get_text(qnode))) | |
118 | |
119 def pkk_output_subs(indent, dnode, dsub, dname): | |
120 for qnode in dnode.findall(dsub): | |
121 pkk_printi(indent, "{} \"{}\"\n".format(dname, pkk_get_text(qnode))) | |
122 | |
123 | |
124 def pkk_output_sense(indent, dnode): | |
125 pkk_output_subs(indent, dnode, "./SearchForm", "srch") | |
126 pkk_output_subs(indent, dnode, "./Definition", "defn") | |
127 | |
128 for wnode in dnode.findall("./ExampleBlock/ExampleCtn"): | |
129 sstr = pkk_get_text(wnode.find("./Example")) | |
130 ltmp = [] | |
131 for qnode in wnode.findall("./FreeTopic[@type='levikki']/GeographicalUsage"): | |
132 ltmp.append("{} [{}]".format(pkk_get_text(qnode), qnode.attrib["class"])) | |
6 | 133 |
7 | 134 if len(ltmp) > 0: |
135 lstr = " ({})".format(", ".join(ltmp)) | |
136 else: | |
137 lstr = "" | |
138 | |
139 pkk_printi(indent + 1, "{} \"{}\"{}\n".format("exmp", sstr, lstr)) | |
140 | |
141 | |
142 def pkk_output_node(indent, dnode): | |
6 | 143 |
7 | 144 for wnode in dnode.findall("./HeadwordCtn"): |
145 pkk_output_one (indent, wnode, "./Headword") | |
146 pkk_output_sense(indent + 1, wnode) | |
6 | 147 |
7 | 148 index = 1 |
149 for wnode in dnode.findall("./SenseGrp"): | |
150 pkk_printi(indent + 2, "sense #{}\n".format(index)) | |
151 pkk_output_sense(indent + 2, wnode) | |
152 index += 1 | |
6 | 153 |
154 | |
0 | 155 ### |
156 ### Main program starts | |
157 ### | |
158 signal.signal(signal.SIGINT, pkk_signal_handler) | |
159 | |
160 | |
161 ### Check if we have arguments | |
162 pkk_show_help = False | |
163 pkk_filenames = [] | |
164 argc = 1 | |
165 while argc < len(sys.argv): | |
166 arg = sys.argv[argc] | |
167 | |
168 needs_param = False | |
169 if argc + 1 < len(sys.argv): | |
170 param = sys.argv[argc + 1] | |
171 else: | |
172 param = None | |
173 | |
174 # Check for option type arg | |
175 if arg[0:1] == "-": | |
176 oarg = arg | |
177 arg = arg.lstrip("-") | |
178 | |
179 if arg == "help" or arg == "h": | |
180 pkk_show_help = True | |
181 elif arg == "dump" or arg == "d": | |
182 pkk_cfg["dump"] = True | |
5
274b2091137c
Some more work on cleaning this up.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
183 elif arg == "normalize" or arg == "n": |
274b2091137c
Some more work on cleaning this up.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
184 pkk_cfg["normalize"] = True |
7 | 185 elif arg == "p": |
186 pkk_cfg["debug"] = True | |
0 | 187 else: |
188 pkk_fatal(u"Invalid option argument '{0}'.".format(oarg)) | |
189 | |
190 if needs_param and param == None: | |
191 pkk_fatal(u"Option '{0}' requires an argument.".format(oarg)) | |
192 else: | |
193 # Non-option argument | |
194 pkk_filenames.append(arg) | |
195 | |
196 if needs_param: | |
197 argc += 2 | |
198 else: | |
199 argc += 1 | |
200 | |
201 | |
202 ### Show help if requested | |
203 if pkk_show_help or len(pkk_filenames) == 0: | |
204 print(u"lxmldump - Dump ISO/FDIS 1951 XML file data") | |
205 print(u"Usage: {0} <options> <input xml file(s)>". | |
206 format(str(Path(sys.argv[0]).name))) | |
207 print(u"") | |
208 print(u" --help Show this help") | |
209 print(u" -d, --dump Dump mode") | |
6 | 210 print(u" -n, --normalize Output NFC normalized Unicode") |
0 | 211 print(u"") |
212 sys.exit(0) | |
213 | |
214 | |
6 | 215 ### Handle each input file |
0 | 216 for filename in pkk_filenames: |
217 # Parse XML file into element tree | |
218 try: | |
219 uxml = xmlET.parse(filename) | |
220 except Exception as e: | |
221 pkk_fatal(u"SVG/XML parsing failed: {0}".format(str(e))) | |
222 | |
223 # Dump output | |
224 try: | |
225 xroot = uxml.getroot() | |
226 for dnode in xroot.findall("./DictionaryEntry"): | |
7 | 227 |
228 if pkk_cfg["debug"] and dnode.attrib["identifier"] not in pkk_debug_list: | |
229 continue | |
230 | |
0 | 231 if pkk_cfg["dump"]: |
7 | 232 pkk_dump_recursive(0, dnode) |
0 | 233 else: |
7 | 234 pkk_output_node(0, dnode) |
235 | |
236 print("\n") | |
0 | 237 |
238 except (BrokenPipeError, IOError) as e: | |
239 sys.stderr.close() | |
240 sys.exit(1) | |
241 | |
242 pkk_cleanup() | |
243 sys.exit(0) |