-
Notifications
You must be signed in to change notification settings - Fork 1
/
run-parser.xq
123 lines (120 loc) · 5.17 KB
/
run-parser.xq
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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
xquery version "4.0";
import module namespace ms = "__marc-scraper__" at "src/marc-scraper.xqm";
(: Path to the output directory :)
declare variable $ms:DIR as xs:string external := "";
for $p in ms:parse-docs()
let $db := $p/data(@db)
return file:write-text($ms:DIR||"marc21_"||$db||"_schema.json",
serialize(
<fn:map>
<fn:string key="title">MARC21 {$db} format</fn:string>
<fn:string key="url">https://www.loc.gov/marc/{$db}/</fn:string>
<fn:string key="language">en</fn:string>
<fn:string key="family">marc</fn:string>
<fn:map key="fields">{
for $field in $p/*
let $key := if ($field/data(@code) = "leader") then "LDR" else $field/data(@code)
let $name := $field/data(title)
let $positions := <fn:map key="positions">{
if ($field/positions/group)
then
for $group in $field/positions/group
let $code := $group/data(@code)
return
<fn:array key="{$code}">{
for $data in $group/data
let $name := $data/data(name)
let $start := xs:integer($data/start)
let $end := xs:integer($data/stop)
return (
<fn:map key="{$start}-{$end}">
<fn:string key="label">{$name}</fn:string>
<fn:number key="start">{$start}</fn:number>
<fn:number key="end">{$end}</fn:number>
</fn:map>
)
}</fn:array>
else if ($field/data/positions)
then
for $data in $field/data
let $name := $data/data(name)
let $start := xs:integer($data/positions/start)
let $end := xs:integer($data/positions/stop)
let $values :=
<fn:map key="codes">{
for $entry in $data/values/entry[normalize-space(name)]
let $code := if ($entry/data(code) = "#") then " " else $entry/data(code)
return
<fn:string key="{$code}">{data($entry/data(name))}</fn:string>
}</fn:map>
return
<fn:map key="{$start}-{$end}">
<fn:string key="label">{$name}</fn:string>
<fn:number key="start">{$start}</fn:number>
<fn:number key="end">{$end}</fn:number>
{$values}
</fn:map>
}</fn:map>
let $repeatable := $field/data(repeat)
let $indicators := <fn:map key="indicators">{
if ($field/indicators/*)
then (
for $ind in $field/indicators/entry
return
<fn:map key="indicator{$ind/@n}">
<fn:string key="label">{$ind/data(name)}</fn:string>
<fn:map key="codes">{
for $value in $ind/data
let $code := if ($value/key = "#") then " " else $value/key
return
<fn:string key="{$code}">{$value/data(value)}</fn:string>
}</fn:map>
</fn:map>
)
else ()
}</fn:map>
let $subfields := <fn:map key="subfields">{
for $sf in $field/subfields[1]/subfield[normalize-space(data/key)]/data
let $name := $sf/data(name)
let $repeat := $sf/data(repeat)
return
<fn:map key="{$sf/key}">
<fn:string key="label">{$name}</fn:string>
<fn:boolean key="repeatable">{
if (exists($repeat)) {$repeat} else {false()}
}</fn:boolean>
{
if ($sf/static-values)
then <fn:map key="codes">{
for $sv at $p in $sf/static-values/data
let $key :=
if (normalize-space($sv/key))
then $sv/data(key)
else $p - 1
let $name := $sv/data(name)
return <fn:map key="{$key}">
<fn:string key="label">{$name}</fn:string>
<fn:string key="code">{$key}</fn:string>
</fn:map>
}</fn:map>
}
</fn:map>
}</fn:map>
return
<fn:map key="{$key}">
<fn:string key="label">{$name}</fn:string>
{if ($positions/*) {$positions}}
{if ($indicators/*) {$indicators/*}}
{if ($subfields/*) {$subfields}}
<fn:boolean key="repeatable">{$repeatable}</fn:boolean>
</fn:map>
}</fn:map>
</fn:map>
,
map {
"method": "json", "escape-solidus": "no", "json": map {
"format": "basic", "indent": "yes"
}
}
) ! proc:execute("jq", ("-sS", ., "."))/output/text()
)