-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathxml2json.php
More file actions
90 lines (78 loc) · 2.9 KB
/
Copy pathxml2json.php
File metadata and controls
90 lines (78 loc) · 2.9 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
<?php
/*
* xml2json.php: Convert publist XML database to JSON format
* Usage: php xml2json.php <input.xml> [output.json]
* If output.json is omitted, writes to stdout.
*
* JSON format differences from XML:
* - author and editor are arrays of name strings instead of " and "-delimited strings
* - [[...]] HTML escaping is expanded to actual HTML characters
* - All other fields are plain strings (month and year as integers)
*
* Copyright 2026--2026 by Eitan Frachtenberg (publist@frachtenberg.org)
* This program is distributed under the terms of the GNU General Public License
*/
if ($argc < 2) {
fwrite(STDERR, "Usage: php xml2json.php <input.xml> [output.json]\n");
exit(1);
}
$fn = $argv[1];
$data = file_get_contents($fn);
if ($data === false) {
fwrite(STDERR, "Error: cannot read file '$fn'\n");
exit(1);
}
$parser = xml_parser_create();
xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
$ok = xml_parse_into_struct($parser, $data, $values, $tags);
xml_parser_free($parser);
if (!$ok) {
fwrite(STDERR, "Error: failed to parse XML in '$fn'\n");
exit(1);
}
$pubs = [];
if (isset($tags['publication'])) {
$ranges = $tags['publication'];
for ($i = 0; $i < count($ranges); $i += 2) {
$offset = $ranges[$i] + 1;
$len = $ranges[$i + 1] - $offset;
$slice = array_slice($values, $offset, $len);
$pub = [];
foreach ($slice as $item) {
$value = isset($item['value']) ? trim($item['value']) : '';
if ($value === '') continue;
// Expand [[...]] HTML escaping to real HTML
$value = str_replace('[[', '<', $value);
$value = str_replace(']]', '>', $value);
$pub[$item['tag']] = $value;
}
// Normalize author(s)/editor(s) to arrays; keep canonical field names
foreach (['author' => ['author', 'authors'],
'editor' => ['editor', 'editors']] as $dst => $srcs) {
foreach ($srcs as $src) {
if (!isset($pub[$src])) continue;
$names = array_values(array_filter(array_map('trim', explode(' and ', $pub[$src]))));
$pub[$dst] = $names;
if ($src !== $dst) unset($pub[$src]);
break;
}
}
// Store month and year as integers for natural JSON
foreach (['month', 'year'] as $numfield) {
if (isset($pub[$numfield]) && ctype_digit($pub[$numfield])) {
$pub[$numfield] = (int) $pub[$numfield];
}
}
$pubs[] = $pub;
}
}
$json = json_encode($pubs, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
if ($argc >= 3) {
if (file_put_contents($argv[2], $json . "\n") === false) {
fwrite(STDERR, "Error: cannot write to '$argv[2]'\n");
exit(1);
}
} else {
echo $json . "\n";
}