mirror of
https://github.com/astaxie/beego.git
synced 2024-11-25 19:20:54 +00:00
128 lines
3.5 KiB
Go
128 lines
3.5 KiB
Go
|
// Copyright 2012-2013 Charles Banning. All rights reserved.
|
||
|
// Use of this source code is governed by a BSD-style
|
||
|
// license that can be found in the LICENSE file
|
||
|
|
||
|
// x2j_bulk.go: Process files with multiple XML messages.
|
||
|
// Extends x2m_bulk.go to work with JSON strings rather than map[string]interface{}.
|
||
|
|
||
|
package x2j
|
||
|
|
||
|
import (
|
||
|
"bytes"
|
||
|
"encoding/json"
|
||
|
"io"
|
||
|
"os"
|
||
|
"regexp"
|
||
|
)
|
||
|
|
||
|
// XmlMsgsFromFileAsJson()
|
||
|
// 'fname' is name of file
|
||
|
// 'phandler' is the JSON string processing handler. Return of 'false' stops further processing.
|
||
|
// 'ehandler' is the parsing error handler. Return of 'false' stops further processing and returns error.
|
||
|
// Note: phandler() and ehandler() calls are blocking, so reading and processing of messages is serialized.
|
||
|
// This means that you can stop reading the file on error or after processing a particular message.
|
||
|
// To have reading and handling run concurrently, pass arguments to a go routine in handler and return true.
|
||
|
func XmlMsgsFromFileAsJson(fname string, phandler func(string)(bool), ehandler func(error)(bool), recast ...bool) error {
|
||
|
var r bool
|
||
|
if len(recast) == 1 {
|
||
|
r = recast[0]
|
||
|
}
|
||
|
fi, fierr := os.Stat(fname)
|
||
|
if fierr != nil {
|
||
|
return fierr
|
||
|
}
|
||
|
fh, fherr := os.Open(fname)
|
||
|
if fherr != nil {
|
||
|
return fherr
|
||
|
}
|
||
|
defer fh.Close()
|
||
|
buf := make([]byte,fi.Size())
|
||
|
_, rerr := fh.Read(buf)
|
||
|
if rerr != nil {
|
||
|
return rerr
|
||
|
}
|
||
|
doc := string(buf)
|
||
|
|
||
|
// xml.Decoder doesn't properly handle whitespace in some doc
|
||
|
// see songTextString.xml test case ...
|
||
|
reg,_ := regexp.Compile("[ \t\n\r]*<")
|
||
|
doc = reg.ReplaceAllString(doc,"<")
|
||
|
b := bytes.NewBufferString(doc)
|
||
|
|
||
|
for {
|
||
|
s, serr := XmlBufferToJson(b,r)
|
||
|
if serr != nil && serr != io.EOF {
|
||
|
if ok := ehandler(serr); !ok {
|
||
|
// caused reader termination
|
||
|
return serr
|
||
|
}
|
||
|
}
|
||
|
if s != "" {
|
||
|
if ok := phandler(s); !ok {
|
||
|
break
|
||
|
}
|
||
|
}
|
||
|
if serr == io.EOF {
|
||
|
break
|
||
|
}
|
||
|
}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// XmlBufferToJson - process XML message from a bytes.Buffer
|
||
|
// 'b' is the buffer
|
||
|
// Optional argument 'recast' coerces values to float64 or bool where possible.
|
||
|
func XmlBufferToJson(b *bytes.Buffer,recast ...bool) (string,error) {
|
||
|
var r bool
|
||
|
if len(recast) == 1 {
|
||
|
r = recast[0]
|
||
|
}
|
||
|
|
||
|
n,err := XmlBufferToTree(b)
|
||
|
if err != nil {
|
||
|
return "", err
|
||
|
}
|
||
|
|
||
|
m := make(map[string]interface{})
|
||
|
m[n.key] = n.treeToMap(r)
|
||
|
|
||
|
j, jerr := json.Marshal(m)
|
||
|
return string(j), jerr
|
||
|
}
|
||
|
|
||
|
// ============================= io.Reader version for stream processing ======================
|
||
|
|
||
|
// XmlMsgsFromReaderAsJson() - io.Reader version of XmlMsgsFromFileAsJson
|
||
|
// 'rdr' is an io.Reader for an XML message (stream)
|
||
|
// 'phandler' is the JSON string processing handler. Return of 'false' stops further processing.
|
||
|
// 'ehandler' is the parsing error handler. Return of 'false' stops further processing and returns error.
|
||
|
// Note: phandler() and ehandler() calls are blocking, so reading and processing of messages is serialized.
|
||
|
// This means that you can stop reading the file on error or after processing a particular message.
|
||
|
// To have reading and handling run concurrently, pass arguments to a go routine in handler and return true.
|
||
|
func XmlMsgsFromReaderAsJson(rdr io.Reader, phandler func(string)(bool), ehandler func(error)(bool), recast ...bool) error {
|
||
|
var r bool
|
||
|
if len(recast) == 1 {
|
||
|
r = recast[0]
|
||
|
}
|
||
|
|
||
|
for {
|
||
|
s, serr := ToJson(rdr,r)
|
||
|
if serr != nil && serr != io.EOF {
|
||
|
if ok := ehandler(serr); !ok {
|
||
|
// caused reader termination
|
||
|
return serr
|
||
|
}
|
||
|
}
|
||
|
if s != "" {
|
||
|
if ok := phandler(s); !ok {
|
||
|
break
|
||
|
}
|
||
|
}
|
||
|
if serr == io.EOF {
|
||
|
break
|
||
|
}
|
||
|
}
|
||
|
return nil
|
||
|
}
|
||
|
|