Skip to content

Commit 7276447

Browse files
committed
Added option to output as XML
1 parent 4738130 commit 7276447

File tree

5 files changed

+143
-9
lines changed

5 files changed

+143
-9
lines changed

cmd/marcli/main.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ func main() {
5656
err = toJson(params)
5757
} else if format == "solr" {
5858
err = toSolr(params)
59+
} else if format == "xml" {
60+
err = toXML(params)
5961
} else {
6062
err = errors.New("Invalid format")
6163
}

cmd/marcli/mrk.go

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,8 @@ func toMrk(params ProcessFileParams) error {
3030

3131
if err != nil {
3232
str := "== RECORD WITH ERROR STARTS HERE\n"
33-
str += "ERROR:\n"
34-
str += err.Error() + "\n"
35-
str += "PARSED:\n"
36-
str += fmt.Sprintf("%s\r\n", r.Leader)
37-
for _, field := range r.Fields {
38-
str += fmt.Sprintf("%s\r\n", field)
39-
}
40-
str += "BINARY:\n"
41-
str += fmt.Sprintf("%s\n", r.Data)
33+
str += "ERROR:\n" + err.Error() + "\n"
34+
str += r.DebugString() + "\n"
4235
str += "== RECORD WITH ERROR ENDS HERE\n\n"
4336
fmt.Print(str)
4437
if params.debug {

cmd/marcli/xml.go

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
package main
2+
3+
import (
4+
"encoding/xml"
5+
"fmt"
6+
"io"
7+
"os"
8+
9+
"github.com/hectorcorrea/marcli/pkg/marc"
10+
)
11+
12+
type controlField struct {
13+
Tag string `xml:"tag,attr"`
14+
Value string `xml:",chardata"`
15+
}
16+
17+
type subfield struct {
18+
Code string `xml:"code,attr"`
19+
Value string `xml:",chardata"`
20+
}
21+
type dataField struct {
22+
Tag string `xml:"tag,attr"`
23+
Ind1 string `xml:"ind1,attr"`
24+
Ind2 string `xml:"ind2,attr"`
25+
Subfields []subfield `xml:"subfield"`
26+
}
27+
28+
type xmlRecord struct {
29+
XMLName xml.Name `xml:"record"`
30+
Leader string `xml:"leader"`
31+
ControlFields []controlField `xml:"controlfield"`
32+
DataFields []dataField `xml:"datafield"`
33+
}
34+
35+
const xmlProlog = `<?xml version="1.0" encoding="UTF-8"?>`
36+
const xmlRootBegin = `<collection xmlns="http://www.loc.gov/MARC21/slim" xmlns:marc="http://www.loc.gov/MARC21/slim">`
37+
const xmlRootEnd = `</collection>`
38+
39+
func toXML(params ProcessFileParams) error {
40+
if count == 0 {
41+
return nil
42+
}
43+
44+
file, err := os.Open(params.filename)
45+
if err != nil {
46+
return err
47+
}
48+
defer file.Close()
49+
50+
fmt.Printf("%s\n%s\n", xmlProlog, xmlRootBegin)
51+
52+
var i, out int
53+
marc := marc.NewMarcFile(file)
54+
for marc.Scan() {
55+
56+
r, err := marc.Record()
57+
if err == io.EOF {
58+
break
59+
}
60+
61+
if err != nil {
62+
printError(r, "PARSE ERROR", err)
63+
if params.debug {
64+
continue
65+
}
66+
return err
67+
}
68+
69+
if i++; i < start {
70+
continue
71+
}
72+
73+
if r.Contains(params.searchValue) && r.HasFields(params.hasFields) {
74+
str, err := recordToXML(r, params.debug)
75+
if err != nil {
76+
if params.debug {
77+
printError(r, "XML PARSE ERROR", err)
78+
continue
79+
}
80+
panic(err)
81+
}
82+
fmt.Printf("%s\r\n", str)
83+
if out++; out == count {
84+
break
85+
}
86+
}
87+
}
88+
fmt.Printf("%s\n", xmlRootEnd)
89+
90+
return marc.Err()
91+
}
92+
93+
func recordToXML(r marc.Record, debug bool) (string, error) {
94+
x := xmlRecord{
95+
Leader: r.Leader.Raw(),
96+
}
97+
98+
for _, f := range r.Fields {
99+
if f.IsControlField() {
100+
x.ControlFields = append(x.ControlFields, controlField{Tag: f.Tag, Value: f.Value})
101+
} else {
102+
df := dataField{Tag: f.Tag, Ind1: f.Indicator1, Ind2: f.Indicator2}
103+
for _, s := range f.SubFields {
104+
df.Subfields = append(df.Subfields, subfield{Code: s.Code, Value: s.Value})
105+
}
106+
x.DataFields = append(x.DataFields, df)
107+
}
108+
}
109+
110+
indent := ""
111+
if debug {
112+
indent = " "
113+
}
114+
b, err := xml.MarshalIndent(x, indent, indent)
115+
return string(b), err
116+
}
117+
118+
func printError(r marc.Record, errType string, err error) {
119+
str := "== RECORD WITH ERROR STARTS HERE\n"
120+
str += fmt.Sprintf("%s:\n%s\n", errType, err.Error())
121+
str += r.DebugString() + "\n"
122+
str += "== RECORD WITH ERROR ENDS HERE\n\n"
123+
fmt.Print(str)
124+
}

pkg/marc/leader.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,3 +51,7 @@ func NewLeader(bytes []byte) (Leader, error) {
5151
func (l Leader) String() string {
5252
return fmt.Sprintf("=LDR %s", string(l.raw))
5353
}
54+
55+
func (l Leader) Raw() string {
56+
return string(l.raw)
57+
}

pkg/marc/record.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,17 @@ func (r Record) String() string {
5151
return fmt.Sprintf("Leader: %s", r.Leader)
5252
}
5353

54+
func (r Record) DebugString() string {
55+
str := "PARSED:\n"
56+
str += fmt.Sprintf("%s\r\n", r.Leader)
57+
for _, field := range r.Fields {
58+
str += fmt.Sprintf("%s\r\n", field)
59+
}
60+
str += "BINARY:\n"
61+
str += fmt.Sprintf("%s", r.Data)
62+
return str
63+
}
64+
5465
// Filter returns the fields in the record that match
5566
// the given filter.
5667
func (r Record) Filter(include FieldFilters, exclude FieldFilters) []Field {

0 commit comments

Comments
 (0)