xml2csv 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 8298b0192e7c8d66809ddc3967c37f99ca21e0fb
4
+ data.tar.gz: f443ddcb8f6ea40cc08834778acc3fd564f6dbcd
5
+ SHA512:
6
+ metadata.gz: 20759360cac3a063fd5cbf955ef5624b21338cf67ac3304314f9ad4ddddfd877f1909791c86786810ada285098bf0f6d1c252ac19c49b826f945ad7bebc4603d
7
+ data.tar.gz: ebeca5de978ace25b946fd1e6435a4b9ab05bf9f13b8df727f71a7cbc8cad34dd7ab1933229c6b94a9de2c90b1bba991ba6eeb3e2296b3ee3e4b187dd3bebcd3
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in xml2csv.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Akira Ohnishi
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,89 @@
1
+ # xml2csv
2
+
3
+ xml2csv - Convert XML to CSV
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'xml2csv'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install xml2csv
18
+
19
+ ## Usage
20
+
21
+ ### Synopsis
22
+ $ xml2csv [-F sep] [--no-hedaer] [xml_file] [root_node] [params...]
23
+
24
+ ### Options
25
+ -F _sep_
26
+ set _sep_ as a field delimiter (default ",")
27
+
28
+ --no-header
29
+ Do not print header.
30
+ Default header is generated from params.
31
+
32
+ xml_file
33
+ path to XML file.
34
+
35
+ root_node
36
+ Set XML node name.
37
+ Expression's path are written relative to the _root_node_(see below.)
38
+
39
+ params
40
+ type:Expression[,...]
41
+
42
+ Describe node name, attribute, xpath, etc...
43
+ Expression can be written with delimiter ",".
44
+
45
+ _type_ are any of the following.
46
+
47
+ node
48
+ Describe node name.
49
+
50
+ xpath
51
+ Same with _node_.
52
+ Describe explicitly that it is a XPath.
53
+
54
+ attr
55
+ Describe attribute.
56
+
57
+ tag
58
+ Describe any characters.
59
+ You can use this when you add output CSV column that is not exist in XML.
60
+
61
+ join
62
+ Describe Expressions.
63
+ Join Expressions with "_".
64
+
65
+ pair
66
+ Describe Expressions.
67
+ Expressions arranged in pairs.
68
+
69
+ with
70
+ with:base_node:Expression[,...]
71
+ You can short cut long Expression.
72
+
73
+ with_order
74
+ with:Expression[,...]
75
+ Add Expression's order from parent element as output CSV's first column.
76
+
77
+ ## Todo
78
+ - Improve poor English.
79
+ - Refactoring.
80
+ - Should reconsider the raison d'etre of join, pair, with.
81
+ (They are still exist for historical reasons.)
82
+
83
+ ## Contributing
84
+
85
+ 1. Fork it ( http://github.com/ohnishiakira/xml2csv/fork )
86
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
87
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
88
+ 4. Push to the branch (`git push origin my-new-feature`)
89
+ 5. Create new Pull Request
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'xml2csv'
4
+
5
+ XML2CSV.xml2csv
@@ -0,0 +1,127 @@
1
+ require "xml2csv/version"
2
+
3
+ require "csv"
4
+ require "digest"
5
+
6
+ require "nokogiri"
7
+ require "slop"
8
+ require "active_support/core_ext"
9
+
10
+ module XML2CSV
11
+ module_function
12
+ def get_content(node, param)
13
+ key, values = param.to_a.first
14
+
15
+ case key
16
+ when "join"
17
+ values.split(/,/).map{|value|
18
+ node.xpath(value).map{|v| v.content.chomp}.join("-")
19
+ }.join("_")
20
+ when "pair"
21
+ values.split(/,/).map{|value|
22
+ node.xpath(value).map{|v| v.content.chomp}
23
+ }
24
+ when "with"
25
+ wkey, wvalues = values.split(/:/, 2)
26
+
27
+ wvalues.split(/,/).map{|value|
28
+ node.xpath([wkey, value].join("/")).map{|v| v.content.chomp}.join("-")
29
+ }
30
+ when "digest"
31
+ keys = values.split(/,/).map{|value|
32
+ node.xpath(value).map{|v| v.content.chomp}
33
+ }
34
+
35
+ Digest::MD5.hexdigest keys.join
36
+ when "with_order"
37
+ ret = values.split(/,/).map{|value|
38
+ if v = node.at_xpath(value)
39
+ v.content.chomp
40
+ else
41
+ ""
42
+ end
43
+ }
44
+
45
+ ret.empty? ? nil : ret.unshift(node.parent.children.index(node))
46
+ else
47
+ values.split(/,/).map{|value|
48
+ case key
49
+ when "tag"
50
+ value
51
+ when "node", "xpath" then
52
+ ret = node.xpath(value).map{|v| v.content.chomp}
53
+ ret.empty? ? nil : ret
54
+ when "attr" then
55
+ ret = node[value]
56
+ ret.nil? ? nil : ret.chomp
57
+ end
58
+ }
59
+ end
60
+ end
61
+
62
+ def parse_xml(xml_io, root_node, parameters)
63
+ Nokogiri::XML(xml_io).xpath("//#{root_node}").map do |node|
64
+ parameters.flat_map{|param|
65
+ get_content(node, param)
66
+ }
67
+ end
68
+ end
69
+
70
+ def parse_params(argv)
71
+ Hash[*argv.split(/:/, 2)]
72
+ end
73
+
74
+ def xml2csv
75
+ Signal.trap("PIPE", "EXIT")
76
+
77
+ args = Slop.parse{
78
+ on :h, :help
79
+ on :F=, '[field separater]'
80
+ on :"no-header"
81
+ }.to_hash
82
+
83
+ if args.delete(:help)
84
+ puts HELP
85
+ exit
86
+ end
87
+
88
+ if col_sep = args.delete(:F)
89
+ ["-F", col_sep].each{|s| ARGV.delete s}
90
+ col_sep = eval %Q{"#{col_sep}"}
91
+ end
92
+
93
+ if no_header = args.delete(:"no-header")
94
+ ARGV.delete "--no-header"
95
+ end
96
+
97
+ xml_io = $stdin.tty? ? File.read(ARGV.shift) : $stdin.read
98
+ root_node = ARGV.shift
99
+ parameters = ARGV.map{|argv| parse_params(argv)}
100
+
101
+ header = parameters.map{|h|
102
+ h.each_pair.map{|k,v|
103
+ v.split(/,/).map{|_v| File.basename _v}
104
+ }
105
+ }.flatten
106
+
107
+ csv_options = {force_quotes: true, headers: header, write_headers: true}
108
+
109
+ if col_sep
110
+ csv_options.merge! col_sep: col_sep
111
+ csv_options.delete :force_quotes
112
+ end
113
+
114
+ if no_header
115
+ [:headers, :write_headers].each{|key|
116
+ csv_options.delete key
117
+ }
118
+ end
119
+
120
+ print CSV.generate("", csv_options){|csv|
121
+ parse_xml(xml_io, root_node, parameters).each{|row|
122
+ row = row.flatten
123
+ csv << row unless row.blank?
124
+ }
125
+ }
126
+ end
127
+ end
@@ -0,0 +1,3 @@
1
+ module XML2CSV
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'xml2csv/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "xml2csv"
8
+ spec.version = XML2CSV::VERSION
9
+ spec.authors = ["Akira Ohnishi"]
10
+ spec.email = ["s06206ao@gmail.com"]
11
+ spec.summary = %q{Convert XML to CSV.}
12
+ spec.description = %q{Convert XML to CSV. Written in Ruby.}
13
+ spec.homepage = "https://github.com/ohnishiakira/xml2csv"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_runtime_dependency "activesupport", "~> 4.0"
22
+ spec.add_runtime_dependency "nokogiri", "~> 1.6"
23
+ spec.add_runtime_dependency "slop", "~> 3.4"
24
+
25
+ spec.add_development_dependency "bundler", "~> 1.5"
26
+ spec.add_development_dependency "rake", "~> 0"
27
+ end
metadata ADDED
@@ -0,0 +1,125 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: xml2csv
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Akira Ohnishi
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-02-17 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '4.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '4.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: nokogiri
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.6'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.6'
41
+ - !ruby/object:Gem::Dependency
42
+ name: slop
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.4'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.4'
55
+ - !ruby/object:Gem::Dependency
56
+ name: bundler
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.5'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.5'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: Convert XML to CSV. Written in Ruby.
84
+ email:
85
+ - s06206ao@gmail.com
86
+ executables:
87
+ - xml2csv
88
+ extensions: []
89
+ extra_rdoc_files: []
90
+ files:
91
+ - ".gitignore"
92
+ - Gemfile
93
+ - LICENSE.txt
94
+ - README.md
95
+ - Rakefile
96
+ - bin/xml2csv
97
+ - lib/xml2csv.rb
98
+ - lib/xml2csv/version.rb
99
+ - xml2csv.gemspec
100
+ homepage: https://github.com/ohnishiakira/xml2csv
101
+ licenses:
102
+ - MIT
103
+ metadata: {}
104
+ post_install_message:
105
+ rdoc_options: []
106
+ require_paths:
107
+ - lib
108
+ required_ruby_version: !ruby/object:Gem::Requirement
109
+ requirements:
110
+ - - ">="
111
+ - !ruby/object:Gem::Version
112
+ version: '0'
113
+ required_rubygems_version: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ requirements: []
119
+ rubyforge_project:
120
+ rubygems_version: 2.2.2
121
+ signing_key:
122
+ specification_version: 4
123
+ summary: Convert XML to CSV.
124
+ test_files: []
125
+ has_rdoc: