Skip to content

Instantly share code, notes, and snippets.

@angch
Last active March 27, 2017 15:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save angch/ed3c8ba950d99a2adc7bd7f57283c247 to your computer and use it in GitHub Desktop.
Save angch/ed3c8ba950d99a2adc7bd7f57283c247 to your computer and use it in GitHub Desktop.
package main
/////////////////////////////////////////////////////////////////
//Code generated by chidley https://github.com/gnewton/chidley //
/////////////////////////////////////////////////////////////////
import (
"bufio"
"compress/bzip2"
"compress/gzip"
"encoding/json"
"encoding/xml"
"flag"
"fmt"
"io"
"io/ioutil"
"log"
"os"
"runtime"
"strings"
)
const (
JsonOut = iota
XmlOut
CountAll
)
var toJson bool = false
var toXml bool = false
var oneLevelDown bool = false
var countAll bool = false
var musage bool = false
var uniqueFlags = []*bool{
&toJson,
&toXml,
&countAll}
var filename = ""
func init() {
flag.BoolVar(&toJson, "j", toJson, "Convert to JSON")
flag.BoolVar(&toXml, "x", toXml, "Convert to XML")
flag.BoolVar(&countAll, "c", countAll, "Count each instance of XML tags")
flag.BoolVar(&oneLevelDown, "s", oneLevelDown, "Stream XML by using XML elements one down from the root tag. Good for huge XML files (see http://blog.davidsingleton.org/parsing-huge-xml-files-with-go/")
flag.BoolVar(&musage, "h", musage, "Usage")
flag.StringVar(&filename, "f", filename, "XML file or URL to read in")
}
var out int = -1
var counters map[string]*int
func main() {
runtime.GOMAXPROCS(runtime.NumCPU())
flag.Parse()
if musage {
flag.Usage()
return
}
numSetBools, outFlag := numberOfBoolsSet(uniqueFlags)
if numSetBools == 0 {
flag.Usage()
return
}
if numSetBools != 1 {
flag.Usage()
log.Fatal("Only one of ", uniqueFlags, " can be set at once")
}
reader, xmlFile, err := genericReader(filename)
if err != nil {
log.Fatal(err)
return
}
if true {
xmlBytes, err := ioutil.ReadAll(reader)
rss := Rss{}
err = xml.Unmarshal(xmlBytes, &rss)
if err != nil {
fmt.Println("Can't Unmarshal", err)
}
//
for _, i := range rss.Channel.Item {
fmt.Println(i.Category)
i.Category.Text = "FunNews"
}
//out, err := json.MarshalIndent(rss, " ", " ")
out, err := xml.Marshal(rss)
fmt.Println(string(out))
//fmt.Printf("%s", rss.Channel.Item)
return
}
decoder := xml.NewDecoder(reader)
counters = make(map[string]*int)
for {
token, _ := decoder.Token()
if token == nil {
break
}
switch se := token.(type) {
case xml.StartElement:
handleFeed(se, decoder, outFlag)
}
}
if xmlFile != nil {
defer xmlFile.Close()
}
if countAll {
for k, v := range counters {
fmt.Println(*v, k)
}
}
}
func handleFeed(se xml.StartElement, decoder *xml.Decoder, outFlag *bool) {
if outFlag == &countAll {
incrementCounter(se.Name.Space, se.Name.Local)
} else {
if !oneLevelDown {
if se.Name.Local == "rss" && se.Name.Space == "" {
var item Rss
decoder.DecodeElement(&item, &se)
switch outFlag {
case &toJson:
writeJson(item)
case &toXml:
writeXml(item)
}
}
} else {
if se.Name.Local == "channel" && se.Name.Space == "" {
var item Channel
decoder.DecodeElement(&item, &se)
switch outFlag {
case &toJson:
writeJson(item)
case &toXml:
writeXml(item)
}
}
}
}
}
func makeKey(space string, local string) string {
if space == "" {
space = "_"
}
return space + ":" + local
}
func incrementCounter(space string, local string) {
key := makeKey(space, local)
counter, ok := counters[key]
if !ok {
n := 1
counters[key] = &n
} else {
newv := *counter + 1
counters[key] = &newv
}
}
func writeJson(item interface{}) {
b, err := json.MarshalIndent(item, "", " ")
if err != nil {
log.Fatal(err)
}
fmt.Println(string(b))
}
func writeXml(item interface{}) {
output, err := xml.MarshalIndent(item, " ", " ")
if err != nil {
fmt.Printf("error: %v\n", err)
}
os.Stdout.Write(output)
}
func genericReader(filename string) (io.Reader, *os.File, error) {
if filename == "" {
return bufio.NewReader(os.Stdin), nil, nil
}
file, err := os.Open(filename)
if err != nil {
return nil, nil, err
}
if strings.HasSuffix(filename, "bz2") {
return bufio.NewReader(bzip2.NewReader(bufio.NewReader(file))), file, err
}
if strings.HasSuffix(filename, "gz") {
reader, err := gzip.NewReader(bufio.NewReader(file))
if err != nil {
return nil, nil, err
}
return bufio.NewReader(reader), file, err
}
return bufio.NewReader(file), file, err
}
func numberOfBoolsSet(a []*bool) (int, *bool) {
var setBool *bool
counter := 0
for i := 0; i < len(a); i++ {
if *a[i] {
counter += 1
setBool = a[i]
}
}
return counter, setBool
}
///////////////////////////
/// structs
///////////////////////////
type Category struct {
Text string `xml:",chardata" json:",omitempty"`
}
type Channel struct {
//Atom10_link []*Atom10_link `xml:"http://www.w3.org/2005/Atom link,omitempty" json:"link,omitempty"`
Copyright *Copyright `xml:" copyright,omitempty" json:"copyright,omitempty"`
Description *Description `xml:" description,omitempty" json:"description,omitempty"`
Feedburner_feedFlare []*Feedburner_feedFlare `xml:"http://rssnamespace.org/feedburner/ext/1.0 feedFlare,omitempty" json:"feedFlare,omitempty"`
Feedburner_info *Feedburner_info `xml:"http://rssnamespace.org/feedburner/ext/1.0 info,omitempty" json:"info,omitempty"`
Image *Image `xml:" image,omitempty" json:"image,omitempty"`
Item []*Item `xml:" item,omitempty" json:"item,omitempty"`
Language *Language `xml:" language,omitempty" json:"language,omitempty"`
LastBuildDate *LastBuildDate `xml:" lastBuildDate,omitempty" json:"lastBuildDate,omitempty"`
Link *Link `xml:" link,omitempty" json:"link,omitempty"`
Title *Title `xml:" title,omitempty" json:"title,omitempty"`
}
type Copyright struct {
Text string `xml:",chardata" json:",omitempty"`
}
type Description struct {
Text string `xml:",chardata" json:",omitempty"`
}
type Guid struct {
Attr_isPermaLink string `xml:" isPermaLink,attr" json:",omitempty"`
Text string `xml:",chardata" json:",omitempty"`
}
type Height struct {
Text string `xml:",chardata" json:",omitempty"`
}
type Image struct {
Height *Height `xml:" height,omitempty" json:"height,omitempty"`
Link *Link `xml:" link,omitempty" json:"link,omitempty"`
Title *Title `xml:" title,omitempty" json:"title,omitempty"`
Url *Url `xml:" url,omitempty" json:"url,omitempty"`
Width *Width `xml:" width,omitempty" json:"width,omitempty"`
}
type Item struct {
Category *Category `xml:" category,omitempty" json:"category,omitempty"`
Description *Description `xml:" description,omitempty" json:"description,omitempty"`
Feedburner_origLink *Feedburner_origLink `xml:"http://rssnamespace.org/feedburner/ext/1.0 origLink,omitempty" json:"origLink,omitempty"`
Guid *Guid `xml:" guid,omitempty" json:"guid,omitempty"`
Link *Link `xml:" link,omitempty" json:"link,omitempty"`
PubDate *PubDate `xml:" pubDate,omitempty" json:"pubDate,omitempty"`
Title *Title `xml:" title,omitempty" json:"title,omitempty"`
}
type Language struct {
Text string `xml:",chardata" json:",omitempty"`
}
type LastBuildDate struct {
Text string `xml:",chardata" json:",omitempty"`
}
type Link struct {
Text string `xml:",chardata" json:",omitempty"`
}
type PubDate struct {
Text string `xml:",chardata" json:",omitempty"`
}
type Root struct {
Rss *Rss `xml:" rss,omitempty" json:"rss,omitempty"`
}
type Rss struct {
Attr_feedburner string `xml:"xmlns feedburner,attr" json:",omitempty"`
Attr_version string `xml:" version,attr" json:",omitempty"`
Channel *Channel `xml:" channel,omitempty" json:"channel,omitempty"`
}
type Title struct {
Text string `xml:",chardata" json:",omitempty"`
}
type Url struct {
Text string `xml:",chardata" json:",omitempty"`
}
type Width struct {
Text string `xml:",chardata" json:",omitempty"`
}
type Feedburner_feedFlare struct {
Attr_href string `xml:" href,attr" json:",omitempty"`
Attr_src string `xml:" src,attr" json:",omitempty"`
Text string `xml:",chardata" json:",omitempty"`
XMLName xml.Name `xml:"http://rssnamespace.org/feedburner/ext/1.0 feedFlare,omitempty" json:"feedFlare,omitempty"`
}
type Feedburner_info struct {
Attr_uri string `xml:" uri,attr" json:",omitempty"`
XMLName xml.Name `xml:"http://rssnamespace.org/feedburner/ext/1.0 info,omitempty" json:"info,omitempty"`
}
type Feedburner_origLink struct {
Text string `xml:",chardata" json:",omitempty"`
XMLName xml.Name `xml:"http://rssnamespace.org/feedburner/ext/1.0 origLink,omitempty" json:"origLink,omitempty"`
}
/*
type Atom10_link struct {
Attr_atom10 string `xml:"xmlns atom10,attr" json:",omitempty"`
Attr_href string `xml:" href,attr" json:",omitempty"`
Attr_rel string `xml:" rel,attr" json:",omitempty"`
Attr_type string `xml:" type,attr" json:",omitempty"`
XMLName xml.Name `xml:"http://www.w3.org/2005/Atom link,omitempty" json:"link,omitempty"`
}
*/
///////////////////////////
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment