xml_to_json 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile ADDED
@@ -0,0 +1,14 @@
1
+ source "http://rubygems.org"
2
+
3
+ gem 'nokogiri'
4
+
5
+ group :development do
6
+ gem 'yajl-ruby'
7
+ gem 'activesupport', "3.0.1"
8
+ gem 'builder'
9
+
10
+ gem "rspec", "2.1.0"
11
+ gem "bundler", "~> 1.0.0"
12
+ gem "jeweler", "~> 1.5.0.pre6"
13
+ gem "rcov", ">= 0"
14
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,36 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ activesupport (3.0.1)
5
+ builder (2.1.2)
6
+ diff-lcs (1.1.2)
7
+ git (1.2.5)
8
+ jeweler (1.5.0.pre6)
9
+ bundler (~> 1.0.0)
10
+ git (>= 1.2.5)
11
+ rake
12
+ nokogiri (1.4.3.1)
13
+ rake (0.8.7)
14
+ rcov (0.9.9)
15
+ rspec (2.1.0)
16
+ rspec-core (~> 2.1.0)
17
+ rspec-expectations (~> 2.1.0)
18
+ rspec-mocks (~> 2.1.0)
19
+ rspec-core (2.1.0)
20
+ rspec-expectations (2.1.0)
21
+ diff-lcs (~> 1.1.2)
22
+ rspec-mocks (2.1.0)
23
+ yajl-ruby (0.7.8)
24
+
25
+ PLATFORMS
26
+ ruby
27
+
28
+ DEPENDENCIES
29
+ activesupport (= 3.0.1)
30
+ builder
31
+ bundler (~> 1.0.0)
32
+ jeweler (~> 1.5.0.pre6)
33
+ nokogiri
34
+ rcov
35
+ rspec (= 2.1.0)
36
+ yajl-ruby
data/Rakefile ADDED
@@ -0,0 +1,57 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ begin
4
+ Bundler.setup(:default, :development)
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts "Run `bundle install` to install missing gems"
8
+ exit e.status_code
9
+ end
10
+ require 'rake'
11
+
12
+ require 'jeweler'
13
+ Jeweler::Tasks.new do |gem|
14
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
15
+ gem.name = "xml_to_json"
16
+ gem.homepage = "http://github.com/mtodd/xml_to_json"
17
+ gem.license = "MIT"
18
+ gem.summary = %Q{Transforms XML to JSON}
19
+ gem.description = %Q{Transforms a string of XML into a string of JSON}
20
+ gem.email = "chiology@gmail.com"
21
+ gem.authors = ["Matt Todd"]
22
+
23
+ gem.add_runtime_dependency 'nokogiri', '1.4.3.1'
24
+
25
+ gem.add_development_dependency 'yajl-ruby', '0.7.8'
26
+ gem.add_development_dependency 'activesupport', '3.0.1'
27
+ gem.add_development_dependency 'builder', '2.1.2'
28
+
29
+ gem.add_development_dependency 'rspec', '2.1.0'
30
+ gem.add_development_dependency 'bundler', '~> 1.0.0'
31
+ gem.add_development_dependency 'jeweler', '~> 1.5.0.pre6'
32
+ gem.add_development_dependency 'rcov', '>= 0'
33
+ end
34
+ Jeweler::RubygemsDotOrgTasks.new
35
+
36
+ require 'rspec/core'
37
+ require 'rspec/core/rake_task'
38
+ RSpec::Core::RakeTask.new(:spec) do |spec|
39
+ spec.pattern = FileList['spec/**/*_spec.rb']
40
+ end
41
+
42
+ RSpec::Core::RakeTask.new(:rcov) do |spec|
43
+ spec.pattern = 'spec/**/*_spec.rb'
44
+ spec.rcov = true
45
+ end
46
+
47
+ task :default => :spec
48
+
49
+ require 'rake/rdoctask'
50
+ Rake::RDocTask.new do |rdoc|
51
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
52
+
53
+ rdoc.rdoc_dir = 'rdoc'
54
+ rdoc.title = "xml_to_json #{version}"
55
+ rdoc.rdoc_files.include('README*')
56
+ rdoc.rdoc_files.include('lib/**/*.rb')
57
+ end
data/Readme.textile ADDED
@@ -0,0 +1,89 @@
1
+ h1. XML to JSON
2
+
3
+ Transforms strings of XML to JSON using a simple XSLT.
4
+
5
+ h2. Usage
6
+
7
+ <pre>
8
+ require 'xml_to_json'
9
+
10
+ puts XmlToJson.transform(<<-XML)
11
+ <items>
12
+ <item>
13
+ <id>1</id>
14
+ <name>Foo</name>
15
+ </item>
16
+ <item>
17
+ <id>2</id>
18
+ <name>Bar</name>
19
+ </item>
20
+ </items>
21
+ XML
22
+ </pre>
23
+
24
+ Transforms into:
25
+
26
+ <pre>
27
+ {"items":[
28
+ {
29
+ "id":1,
30
+ "name":"Foo"
31
+ },
32
+ {
33
+ "id":2,
34
+ "name":"Bar"
35
+ }
36
+ ]}
37
+ </pre>
38
+
39
+ Or:
40
+
41
+ <pre>
42
+ require 'xml_to_json/string'
43
+
44
+ xml.to_json
45
+ </pre>
46
+
47
+ h2. TODO
48
+
49
+ * Nokogiri::Document#to_json
50
+
51
+ h2. Contributing to xml_to_json
52
+
53
+ # Fork on GitHub
54
+ # Write a failing spec
55
+ # OPTIONAL: Make the failing spec pass
56
+ # Send a pull request
57
+
58
+ Bonus points for topic branches.
59
+
60
+ If you prove something is broken, I'll be happy to try to fix it. A failing
61
+ spec is sufficient!
62
+
63
+ The Rakefile, version, and history files are generated by Jeweler. Don't modify
64
+ them or I won't accept your patch. (Exceptions are made when the situation is
65
+ exceptional.)
66
+
67
+ h2. License
68
+
69
+ The MIT License
70
+
71
+ Copyright (c) 2010 Matt Todd.
72
+
73
+ Permission is hereby granted, free of charge, to any person obtaining a copy
74
+ of this software and associated documentation files (the "Software"), to deal
75
+ in the Software without restriction, including without limitation the rights
76
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
77
+ copies of the Software, and to permit persons to whom the Software is
78
+ furnished to do so, subject to the following conditions:
79
+
80
+ The above copyright notice and this permission notice shall be included in
81
+ all copies or substantial portions of the Software.
82
+
83
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
84
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
85
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
86
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
87
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
88
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
89
+ THE SOFTWARE.
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.0
@@ -0,0 +1,17 @@
1
+ require 'nokogiri'
2
+
3
+ module XmlToJson
4
+ module_function
5
+
6
+ def transform(xml)
7
+ stylesheet.transform(Nokogiri::XML(xml)).text
8
+ end
9
+
10
+ def root
11
+ @root ||= Pathname.new(__FILE__).dirname.parent
12
+ end
13
+
14
+ def stylesheet
15
+ @stylesheet ||= Nokogiri::XSLT(root.join('vendor', 'xml2json-xslt', 'xml2json-patched.xslt').read)
16
+ end
17
+ end
@@ -0,0 +1,7 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'xml_to_json')
2
+
3
+ class String
4
+ def to_json
5
+ XmlToJson.transform(self)
6
+ end
7
+ end
@@ -0,0 +1,10 @@
1
+ $:.unshift(File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib')))
2
+ require 'rubygems'
3
+ require 'bundler/setup'
4
+ require 'xml_to_json'
5
+
6
+ require 'rspec'
7
+
8
+ require 'active_support/core_ext/array/conversions'
9
+ require 'active_support/core_ext/hash/conversions'
10
+ require 'yajl/json_gem'
@@ -0,0 +1,22 @@
1
+ require 'spec_helper'
2
+ require 'xml_to_json/string'
3
+
4
+ describe "String#to_json" do
5
+ before :each do
6
+ @source = [
7
+ {
8
+ :id => 1,
9
+ :name => "Foo"
10
+ },
11
+ {
12
+ :id => 2,
13
+ :name => "Bar"
14
+ }
15
+ ]
16
+ @xml = @source.to_xml(:root => "items")
17
+ end
18
+
19
+ it "should transform an XML string to JSON" do
20
+ @xml.to_json.should == {:items => @source}.to_json
21
+ end
22
+ end
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+
3
+ describe "XmlToJson" do
4
+ before :each do
5
+ @source = [
6
+ {
7
+ :id => 1,
8
+ :name => "Foo"
9
+ },
10
+ {
11
+ :id => 2,
12
+ :name => "Bar"
13
+ }
14
+ ]
15
+ @xml = @source.to_xml(:root => "items")
16
+ end
17
+
18
+ it "should transform an array of items into a hash of items" do
19
+ XmlToJson.transform(@xml).should == {:items => @source}.to_json
20
+ end
21
+ end
@@ -0,0 +1,26 @@
1
+ Copyright (c) 2006, Doeke Zanstra
2
+ All rights reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without modification,
5
+ are permitted provided that the following conditions are met:
6
+
7
+ Redistributions of source code must retain the above copyright notice, this
8
+ list of conditions and the following disclaimer. Redistributions in binary
9
+ form must reproduce the above copyright notice, this list of conditions and the
10
+ following disclaimer in the documentation and/or other materials provided with
11
+ the distribution.
12
+
13
+ Neither the name of the dzLib nor the names of its contributors may be used to
14
+ endorse or promote products derived from this software without specific prior
15
+ written permission.
16
+
17
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20
+ IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
21
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
22
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
25
+ OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
26
+ THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,107 @@
1
+ ====== xml2json.xslt ======
2
+
3
+ version 0.3, Copyright (c) 2006, Doeke Zanstra, see COPYRIGHT.txt
4
+
5
+ xml2json.xslt is a XSLT 1.0 stylesheet to transform arbitrary XML to JSON. There is also a version for javascript. The workings are demonstrated with the accompanied xml files. The target of this library is to create javascript-like JSON, not XML-like JSON, like the BadgerFish convention (see Resources).
6
+
7
+ The downside is it won't translate all markup, and there's a chance the JSON is invalid. However, if you control the XML, you will enjoy the merits of javascript. Enjoy ;-)
8
+
9
+ I will call this the Parker convention, after the comic Parker & Badger by Cuadrado. I can really recommend the comic, also in relation to this work and the BadgerFish convention.
10
+
11
+ ====== Using ======
12
+
13
+ You can load the xml files in your browser (Firefox/Camino work, Safari doesn't, Internet Explorer 6 works, except test-js.xml). On windows, you can also try the commandline Msxsl utility (see resources). And of course you can fire up your favorite transformation engine.
14
+
15
+ ====== Translation JSON ======
16
+
17
+ 1. The root element will be absorbed, for there is only one
18
+ <root>test</root>
19
+ becomes
20
+ "test"
21
+
22
+ 2. Element names become object properties:
23
+ <root><name>Xml</name><encoding>ASCII</encoding></root>
24
+ becomes
25
+ {"name":"Xml","encoding":"ASCII"}
26
+
27
+ 3. Numbers are recognized (integers and decimals):
28
+ <root><age>12</age><height>1.73</height></root>
29
+ becomes
30
+ {"age":12,"height":1.73}
31
+
32
+ 4. Booleans are recognized case insensitive:
33
+ <root><checked>True</checked><answer>FALSE</answer></root>
34
+ becomes
35
+ {"checked":true,"answer":false}
36
+
37
+ 5. Strings are escaped:
38
+ <root>Quote: &quot; New-line:
39
+ </root>
40
+ becomes
41
+ "Quote: \" New-line:\n"
42
+
43
+ 6. Empty elements will become null:
44
+ <root><nil/><empty></empty></root>
45
+ becomes
46
+ {"nil":null,"empty":null}
47
+
48
+ 7. If all sibling elements have the same name, they become an array
49
+ <root><item>1</item><item>2</item><item>three</item></root>
50
+ becomes
51
+ [1,2,"three"]
52
+
53
+ 8. Mixed mode text-nodes, comments and attributes get absorbed:
54
+ <root version="1.0">testing<!--comment--><element test="true">1</element></root>
55
+ becomes
56
+ {element:true}
57
+
58
+ 9. Namespaces get absorbed, and prefixes will just be part of the property name:
59
+ <root xmlns:ding="http://zanstra.com/ding"><ding:dong>binnen</ding:dong></root>
60
+ becomes
61
+ {"ding:dong":"binnen"}
62
+
63
+ ====== Translation JS extra ======
64
+
65
+ All the same as the JSON translation, but with these extra's:
66
+
67
+ 1. Property names are only escaped when necessary
68
+ <root><while>true</while><wend>false</wend><only-if/></root>
69
+ becomes
70
+ {"while":true,wend:false,"only-if":null}
71
+
72
+ 2. Within a string, closing elements "</" are escaped as "<\/"
73
+ <root><![CDATA[<script>alert("YES");</script>]]></root>
74
+ becomes
75
+ {script:"<script>alert(\"YES\")<\/script>"}
76
+
77
+ 3. Dates are created as new Date() objects
78
+ <root>2006-12-25</root>
79
+ becomes
80
+ new Date(2006,12-1,25)
81
+
82
+ 4. Attributes and comments are shown as comments (for testing-purposes):
83
+ <!--testing--><root><test version="1.0">123</test></root>
84
+ becomes
85
+ /*testing*/{test/*@version="1.0"*/:123}
86
+
87
+ 5. A bit of indentation is done, to keep things ledgible
88
+
89
+ ====== Plans ======
90
+
91
+ I don't really have much plans with this library. It was mere a result of learning XSLT and XPath better. However, I will perform bug-fixes. Issues I might address, if I can find a satisfactory solution:
92
+
93
+ - convert attributes to properties in some way
94
+
95
+ - handle siblings with duplicate names, when there are also other names:
96
+ <root><item>1</item><item>2</item><name>test</name></root>
97
+ becomes (faulty JSON)
98
+ {"item":1,"item":2,"name":"test"}
99
+
100
+ ====== Resources ======
101
+
102
+ * Xml: http://www.w3.org/TR/xml/
103
+ * Xslt: http://www.w3.org/TR/xslt
104
+ * XPath: http://www.w3.org/TR/xpath
105
+ * Json: http://www.json.org
106
+ * BadgerFish: http://badgerfish.ning.com/
107
+ * Msxsl: http://www.microsoft.com/downloads/details.aspx?FamilyId=2FB55371-C94E-4373-B0E9-DB4816552E41&displaylang=en
@@ -0,0 +1,53 @@
1
+ <?xml-stylesheet type="text/xsl" href="xml2js.xslt"?>
2
+ <!--
3
+ Test XML markup for converting xml to JS using XSLT.
4
+ By Doeke Zanstra, 2006
5
+ -->
6
+ <root version="1.0" xmlns:ding="http://zanstra.com/ding">
7
+ this text should be ignored
8
+ <birthdate>2006-11-14</birthdate>
9
+ <appointment>2006-11-14T12:30</appointment>
10
+ <appointment>2006-11-14T12:30:00</appointment>
11
+ <script><![CDATA[<script>alert("YES")</script>]]></script>
12
+ <positive>123</positive>
13
+ <negative>-12</negative>
14
+ <zero>0</zero>
15
+ <fixed>10.25</fixed>
16
+ <fixed-neg>-10.25</fixed-neg>
17
+ <padded_zero>01</padded_zero>
18
+ <ding:dong-dang.dung>Namespaced element with dash and dot</ding:dong-dang.dung>
19
+ <yo123-ho456/>
20
+ <string>Zooi</string>
21
+ <string>Tab Text</string>
22
+ <string>Quote "test"</string>
23
+ <string>Backslash \ test</string>
24
+ <string>Quote " en \ test</string>
25
+ <string>"Begin/end quote"</string>
26
+ <escape>Line one (één in Dutch)
27
+ Line two: tab
28
+ He said: "Much fun with a €"
29
+ More unicode&#8224;</escape>
30
+ <int>123</int>
31
+ <float>-12.123</float>
32
+ <exp>-1.234e5</exp>
33
+ <boolean>true</boolean>
34
+ <nil/>
35
+ <empty></empty>
36
+ <object test="true" attributes="are commented">
37
+ <zooi>jaja</zooi>
38
+ <zut>frot</zut>
39
+ </object>
40
+ <array>
41
+ <item/>
42
+ <item>true</item>
43
+ <item>2</item>
44
+ <item>3</item>
45
+ <item>4</item>
46
+ <item>5</item>
47
+ <item>six</item>
48
+ <item>
49
+ <key>item</key>
50
+ <value>7</value>
51
+ </item>
52
+ </array>
53
+ </root>