oxm 0.1.0
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.
- data/.document +5 -0
- data/CHANGELOG.markdown +15 -0
- data/Gemfile +15 -0
- data/Gemfile.lock +25 -0
- data/LICENSE.txt +20 -0
- data/README.markdown +81 -0
- data/Rakefile +53 -0
- data/VERSION +1 -0
- data/lib/oxm/object.rb +154 -0
- data/lib/oxm/sax_handler.rb +57 -0
- data/lib/oxm.rb +16 -0
- data/test/helper.rb +17 -0
- data/test/test_oxm.rb +166 -0
- metadata +118 -0
    
        data/.document
    ADDED
    
    
    
        data/CHANGELOG.markdown
    ADDED
    
    | @@ -0,0 +1,15 @@ | |
| 1 | 
            +
            ### 0.1.0 / 2011/09/19
         | 
| 2 | 
            +
            * Disclaimer: Not compatible to the previous versions
         | 
| 3 | 
            +
            ** Removed: OXM::Object#cdata, OXM::Object#text, OXM::Object#text=
         | 
| 4 | 
            +
            ** Added: OXM::Object#content, OXM::Object#content=
         | 
| 5 | 
            +
            ** Changed: OXM::Object#to_s never returns nil
         | 
| 6 | 
            +
            ** Changed: OXM::Object#compact! removes empty elements as well (no text value, no attributes at all)
         | 
| 7 | 
            +
            ** Fix: Allows assignment of nil/empty string as element values
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            ### 0.0.2 / 2011/09/15
         | 
| 10 | 
            +
            * OXM::Object#compact! added
         | 
| 11 | 
            +
            * OXM::Object#elements as an alias of OXM::Object#children
         | 
| 12 | 
            +
             | 
| 13 | 
            +
            ### 0.0.1 / 2011/09/15
         | 
| 14 | 
            +
            * Initial release
         | 
| 15 | 
            +
             | 
    
        data/Gemfile
    ADDED
    
    | @@ -0,0 +1,15 @@ | |
| 1 | 
            +
            source "http://rubygems.org"
         | 
| 2 | 
            +
            # Add dependencies required to use your gem here.
         | 
| 3 | 
            +
            # Example:
         | 
| 4 | 
            +
            #   gem "activesupport", ">= 2.3.5"
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            # Add dependencies to develop your gem here.
         | 
| 7 | 
            +
            # Include everything needed to run rake, tests, features, etc.
         | 
| 8 | 
            +
            group :development do
         | 
| 9 | 
            +
              gem "bundler", "~> 1.0.0"
         | 
| 10 | 
            +
              gem "jeweler", "~> 1.6.4"
         | 
| 11 | 
            +
              gem "rcov", ">= 0"
         | 
| 12 | 
            +
            end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
            gem "builder", ">= 3.0.0"
         | 
| 15 | 
            +
            gem "nokogiri", ">= 1.5.0"
         | 
    
        data/Gemfile.lock
    ADDED
    
    | @@ -0,0 +1,25 @@ | |
| 1 | 
            +
            GEM
         | 
| 2 | 
            +
              remote: http://rubygems.org/
         | 
| 3 | 
            +
              specs:
         | 
| 4 | 
            +
                builder (3.0.0)
         | 
| 5 | 
            +
                git (1.2.5)
         | 
| 6 | 
            +
                jeweler (1.6.4)
         | 
| 7 | 
            +
                  bundler (~> 1.0)
         | 
| 8 | 
            +
                  git (>= 1.2.5)
         | 
| 9 | 
            +
                  rake
         | 
| 10 | 
            +
                nokogiri (1.5.0)
         | 
| 11 | 
            +
                nokogiri (1.5.0-java)
         | 
| 12 | 
            +
                rake (0.9.2)
         | 
| 13 | 
            +
                rcov (0.9.10)
         | 
| 14 | 
            +
                rcov (0.9.10-java)
         | 
| 15 | 
            +
             | 
| 16 | 
            +
            PLATFORMS
         | 
| 17 | 
            +
              java
         | 
| 18 | 
            +
              ruby
         | 
| 19 | 
            +
             | 
| 20 | 
            +
            DEPENDENCIES
         | 
| 21 | 
            +
              builder (>= 3.0.0)
         | 
| 22 | 
            +
              bundler (~> 1.0.0)
         | 
| 23 | 
            +
              jeweler (~> 1.6.4)
         | 
| 24 | 
            +
              nokogiri (>= 1.5.0)
         | 
| 25 | 
            +
              rcov
         | 
    
        data/LICENSE.txt
    ADDED
    
    | @@ -0,0 +1,20 @@ | |
| 1 | 
            +
            Copyright (c) 2011 Junegunn Choi
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            Permission is hereby granted, free of charge, to any person obtaining
         | 
| 4 | 
            +
            a copy of this software and associated documentation files (the
         | 
| 5 | 
            +
            "Software"), to deal in the Software without restriction, including
         | 
| 6 | 
            +
            without limitation the rights to use, copy, modify, merge, publish,
         | 
| 7 | 
            +
            distribute, sublicense, and/or sell copies of the Software, and to
         | 
| 8 | 
            +
            permit persons to whom the Software is furnished to do so, subject to
         | 
| 9 | 
            +
            the following conditions:
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            The above copyright notice and this permission notice shall be
         | 
| 12 | 
            +
            included in all copies or substantial portions of the Software.
         | 
| 13 | 
            +
             | 
| 14 | 
            +
            THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
         | 
| 15 | 
            +
            EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
         | 
| 16 | 
            +
            MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
         | 
| 17 | 
            +
            NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
         | 
| 18 | 
            +
            LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
         | 
| 19 | 
            +
            OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
         | 
| 20 | 
            +
            WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
         | 
    
        data/README.markdown
    ADDED
    
    | @@ -0,0 +1,81 @@ | |
| 1 | 
            +
            # oxm
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            A tiny, easy-to-use Object-XML-Mapper for Ruby. 
         | 
| 4 | 
            +
            Internally uses Nokogiri SAX parser which allows handling of large XML documents.
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            ## Installation
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            ```
         | 
| 9 | 
            +
            gem install oxm
         | 
| 10 | 
            +
            ```
         | 
| 11 | 
            +
             | 
| 12 | 
            +
            ## Examples
         | 
| 13 | 
            +
             | 
| 14 | 
            +
            ```xml
         | 
| 15 | 
            +
            <orders>
         | 
| 16 | 
            +
              <order date="2011/08/27">
         | 
| 17 | 
            +
                <item amount="5">Apple</item>
         | 
| 18 | 
            +
                <item amount="2">Banana</item>
         | 
| 19 | 
            +
                <customer id="100">Alice</customer>
         | 
| 20 | 
            +
              </order>
         | 
| 21 | 
            +
              <order date="2011/08/27">
         | 
| 22 | 
            +
                <item amount="1">Zoltax</item>
         | 
| 23 | 
            +
                <customer id="200">Bob</customer>
         | 
| 24 | 
            +
              </order>
         | 
| 25 | 
            +
            </orders>
         | 
| 26 | 
            +
            ```
         | 
| 27 | 
            +
             | 
| 28 | 
            +
            ```ruby
         | 
| 29 | 
            +
            require 'oxm'
         | 
| 30 | 
            +
             | 
| 31 | 
            +
            # With block
         | 
| 32 | 
            +
            OXM.from_xml(xml_data_or_io, 'orders/order') do |order|
         | 
| 33 | 
            +
              # Accessing attributes of the element
         | 
| 34 | 
            +
              order['date']
         | 
| 35 | 
            +
              order.attributes
         | 
| 36 | 
            +
             | 
| 37 | 
            +
              # Accessing attributes and text/cdata values of child elements
         | 
| 38 | 
            +
              order.item.first['amount']
         | 
| 39 | 
            +
              order.item.first.content
         | 
| 40 | 
            +
              order.item.first.to_s
         | 
| 41 | 
            +
              order.item.first.cdata?
         | 
| 42 | 
            +
             | 
| 43 | 
            +
              # Traverses child elements
         | 
| 44 | 
            +
              order.elements.each do |tag, elements_for_the_tag|
         | 
| 45 | 
            +
                # ...
         | 
| 46 | 
            +
              end
         | 
| 47 | 
            +
             | 
| 48 | 
            +
              # Compaction: collapse single-element Arrays
         | 
| 49 | 
            +
              order.customer.first.to_s
         | 
| 50 | 
            +
              order.customer.first['id']
         | 
| 51 | 
            +
              order.compact!
         | 
| 52 | 
            +
              order.customer.to_s
         | 
| 53 | 
            +
              order.customer['id']
         | 
| 54 | 
            +
             | 
| 55 | 
            +
              # XML expression for the element
         | 
| 56 | 
            +
              order.to_xml
         | 
| 57 | 
            +
              order.item.first.to_xml
         | 
| 58 | 
            +
            end
         | 
| 59 | 
            +
             | 
| 60 | 
            +
            # Array of elements are returned when block is not given
         | 
| 61 | 
            +
            items = OXM.from_xml(xml_data_or_io, 'orders/order/item')
         | 
| 62 | 
            +
            ```
         | 
| 63 | 
            +
             | 
| 64 | 
            +
            ## TODO
         | 
| 65 | 
            +
            * When block is not given, make from_xml return an Enumerator instead of an Array
         | 
| 66 | 
            +
             | 
| 67 | 
            +
            ## Contributing to oxm
         | 
| 68 | 
            +
             
         | 
| 69 | 
            +
            * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
         | 
| 70 | 
            +
            * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
         | 
| 71 | 
            +
            * Fork the project
         | 
| 72 | 
            +
            * Start a feature/bugfix branch
         | 
| 73 | 
            +
            * Commit and push until you are happy with your contribution
         | 
| 74 | 
            +
            * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
         | 
| 75 | 
            +
            * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
         | 
| 76 | 
            +
             | 
| 77 | 
            +
            ## Copyright
         | 
| 78 | 
            +
             | 
| 79 | 
            +
            Copyright (c) 2011 Junegunn Choi. See LICENSE.txt for
         | 
| 80 | 
            +
            further details.
         | 
| 81 | 
            +
             | 
    
        data/Rakefile
    ADDED
    
    | @@ -0,0 +1,53 @@ | |
| 1 | 
            +
            # encoding: utf-8
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require 'rubygems'
         | 
| 4 | 
            +
            require 'bundler'
         | 
| 5 | 
            +
            begin
         | 
| 6 | 
            +
              Bundler.setup(:default, :development)
         | 
| 7 | 
            +
            rescue Bundler::BundlerError => e
         | 
| 8 | 
            +
              $stderr.puts e.message
         | 
| 9 | 
            +
              $stderr.puts "Run `bundle install` to install missing gems"
         | 
| 10 | 
            +
              exit e.status_code
         | 
| 11 | 
            +
            end
         | 
| 12 | 
            +
            require 'rake'
         | 
| 13 | 
            +
             | 
| 14 | 
            +
            require 'jeweler'
         | 
| 15 | 
            +
            Jeweler::Tasks.new do |gem|
         | 
| 16 | 
            +
              # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
         | 
| 17 | 
            +
              gem.name = "oxm"
         | 
| 18 | 
            +
              gem.homepage = "http://github.com/junegunn/oxm"
         | 
| 19 | 
            +
              gem.license = "MIT"
         | 
| 20 | 
            +
              gem.summary = %Q{A tiny Object-XML-Mapper}
         | 
| 21 | 
            +
              gem.description = %Q{A tiny Object-XML-Mapper using Nokogiri SAX parser}
         | 
| 22 | 
            +
              gem.email = "junegunn.c@gmail.com"
         | 
| 23 | 
            +
              gem.authors = ["Junegunn Choi"]
         | 
| 24 | 
            +
              # dependencies defined in Gemfile
         | 
| 25 | 
            +
            end
         | 
| 26 | 
            +
            Jeweler::RubygemsDotOrgTasks.new
         | 
| 27 | 
            +
             | 
| 28 | 
            +
            require 'rake/testtask'
         | 
| 29 | 
            +
            Rake::TestTask.new(:test) do |test|
         | 
| 30 | 
            +
              test.libs << 'lib' << 'test'
         | 
| 31 | 
            +
              test.pattern = 'test/**/test_*.rb'
         | 
| 32 | 
            +
              test.verbose = true
         | 
| 33 | 
            +
            end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
            require 'rcov/rcovtask'
         | 
| 36 | 
            +
            Rcov::RcovTask.new do |test|
         | 
| 37 | 
            +
              test.libs << 'test'
         | 
| 38 | 
            +
              test.pattern = 'test/**/test_*.rb'
         | 
| 39 | 
            +
              test.verbose = true
         | 
| 40 | 
            +
              test.rcov_opts << '--exclude "gems/*"'
         | 
| 41 | 
            +
            end
         | 
| 42 | 
            +
             | 
| 43 | 
            +
            task :default => :test
         | 
| 44 | 
            +
             | 
| 45 | 
            +
            require 'rake/rdoctask'
         | 
| 46 | 
            +
            Rake::RDocTask.new do |rdoc|
         | 
| 47 | 
            +
              version = File.exist?('VERSION') ? File.read('VERSION') : ""
         | 
| 48 | 
            +
             | 
| 49 | 
            +
              rdoc.rdoc_dir = 'rdoc'
         | 
| 50 | 
            +
              rdoc.title = "oxm #{version}"
         | 
| 51 | 
            +
              rdoc.rdoc_files.include('README*')
         | 
| 52 | 
            +
              rdoc.rdoc_files.include('lib/**/*.rb')
         | 
| 53 | 
            +
            end
         | 
    
        data/VERSION
    ADDED
    
    | @@ -0,0 +1 @@ | |
| 1 | 
            +
            0.1.0
         | 
    
        data/lib/oxm/object.rb
    ADDED
    
    | @@ -0,0 +1,154 @@ | |
| 1 | 
            +
            module OXM
         | 
| 2 | 
            +
              class Object
         | 
| 3 | 
            +
                attr_reader :tag
         | 
| 4 | 
            +
             | 
| 5 | 
            +
                # @return [String/NilClass]
         | 
| 6 | 
            +
                def content
         | 
| 7 | 
            +
                  @data
         | 
| 8 | 
            +
                end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                # @param [String] val Text
         | 
| 11 | 
            +
                # @param [String] val
         | 
| 12 | 
            +
                # @return [String]
         | 
| 13 | 
            +
                def content= val
         | 
| 14 | 
            +
                  @cdata = false
         | 
| 15 | 
            +
                  process val
         | 
| 16 | 
            +
                end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                # @param [String] val CDATA content
         | 
| 19 | 
            +
                # @return [String]
         | 
| 20 | 
            +
                def cdata= val
         | 
| 21 | 
            +
                  @cdata = true
         | 
| 22 | 
            +
                  process val
         | 
| 23 | 
            +
                end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                # @return [Boolean]
         | 
| 26 | 
            +
                def cdata?
         | 
| 27 | 
            +
                  @cdata
         | 
| 28 | 
            +
                end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                # @return [String] XML expression for this object
         | 
| 31 | 
            +
                def to_xml
         | 
| 32 | 
            +
                  io = StringIO.new
         | 
| 33 | 
            +
                  builder = Builder::XmlMarkup.new(:target => io)
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                  build_node = lambda do |node|
         | 
| 36 | 
            +
                    builder.tag!(node.tag, node.attributes) do
         | 
| 37 | 
            +
                      node.elements.each do |tag, elements|
         | 
| 38 | 
            +
                        next if elements.nil?
         | 
| 39 | 
            +
                        elements = [elements] unless elements.is_a? Array
         | 
| 40 | 
            +
                        elements.each do |child|
         | 
| 41 | 
            +
                          build_node.call child
         | 
| 42 | 
            +
                        end
         | 
| 43 | 
            +
                      end
         | 
| 44 | 
            +
                      if node.content
         | 
| 45 | 
            +
                        if node.cdata?
         | 
| 46 | 
            +
                          builder.cdata! node.content
         | 
| 47 | 
            +
                        else
         | 
| 48 | 
            +
                          builder.text! node.content
         | 
| 49 | 
            +
                        end
         | 
| 50 | 
            +
                      end
         | 
| 51 | 
            +
                    end
         | 
| 52 | 
            +
                  end
         | 
| 53 | 
            +
             | 
| 54 | 
            +
                  build_node.call self
         | 
| 55 | 
            +
                  io.string
         | 
| 56 | 
            +
                end
         | 
| 57 | 
            +
             | 
| 58 | 
            +
                # @return [String]
         | 
| 59 | 
            +
                def to_s
         | 
| 60 | 
            +
                  @data.to_s
         | 
| 61 | 
            +
                end
         | 
| 62 | 
            +
             | 
| 63 | 
            +
                # @return [String]
         | 
| 64 | 
            +
                def inspect
         | 
| 65 | 
            +
                  to_xml
         | 
| 66 | 
            +
                end
         | 
| 67 | 
            +
             | 
| 68 | 
            +
                # @param [String] attr
         | 
| 69 | 
            +
                # @return [String]
         | 
| 70 | 
            +
                def [] attr
         | 
| 71 | 
            +
                  @attrs[attr.to_s]
         | 
| 72 | 
            +
                end
         | 
| 73 | 
            +
             | 
| 74 | 
            +
                # @param [String] attr
         | 
| 75 | 
            +
                # @param [String] val
         | 
| 76 | 
            +
                # @return [String]
         | 
| 77 | 
            +
                def []= attr, val
         | 
| 78 | 
            +
                  @attrs[attr.to_s] = val
         | 
| 79 | 
            +
                end
         | 
| 80 | 
            +
             | 
| 81 | 
            +
                # @return [Hash]
         | 
| 82 | 
            +
                def attributes
         | 
| 83 | 
            +
                  @attrs
         | 
| 84 | 
            +
                end
         | 
| 85 | 
            +
             | 
| 86 | 
            +
                # @return [Hash]
         | 
| 87 | 
            +
                def elements
         | 
| 88 | 
            +
                  @nodes
         | 
| 89 | 
            +
                end
         | 
| 90 | 
            +
                alias children elements
         | 
| 91 | 
            +
             | 
| 92 | 
            +
                # @param [String] tag
         | 
| 93 | 
            +
                # @param [OXM::Object] object
         | 
| 94 | 
            +
                # @return [OXM::Object]
         | 
| 95 | 
            +
                def add_node tag, object
         | 
| 96 | 
            +
                  @nodes[tag] ||= []
         | 
| 97 | 
            +
                  @nodes[tag] << object
         | 
| 98 | 
            +
                  self
         | 
| 99 | 
            +
                end
         | 
| 100 | 
            +
             | 
| 101 | 
            +
                # Compacts the object by removing empty child elements and then collapsing element Arrays. 
         | 
| 102 | 
            +
                # After compaction, single-element arrays are collapsed, and empty arrays become nil.
         | 
| 103 | 
            +
                # @return [OXM::Object]
         | 
| 104 | 
            +
                def compact!
         | 
| 105 | 
            +
                  @nodes.each do |key, value|
         | 
| 106 | 
            +
                    if value.is_a?(Array)
         | 
| 107 | 
            +
                      value = value.reject(&:empty?)
         | 
| 108 | 
            +
                      @nodes[key] =
         | 
| 109 | 
            +
                        case value.length
         | 
| 110 | 
            +
                        when 0
         | 
| 111 | 
            +
                          nil
         | 
| 112 | 
            +
                        when 1
         | 
| 113 | 
            +
                          value.first
         | 
| 114 | 
            +
                        else
         | 
| 115 | 
            +
                          value
         | 
| 116 | 
            +
                        end
         | 
| 117 | 
            +
                    end
         | 
| 118 | 
            +
                  end
         | 
| 119 | 
            +
                  self
         | 
| 120 | 
            +
                end
         | 
| 121 | 
            +
             | 
| 122 | 
            +
                # @param [String] tag
         | 
| 123 | 
            +
                # @param [Hash] attrs
         | 
| 124 | 
            +
                # @return [OXM::Object]
         | 
| 125 | 
            +
                def initialize tag, attrs = {}
         | 
| 126 | 
            +
                  @tag = tag
         | 
| 127 | 
            +
                  @attrs = attrs
         | 
| 128 | 
            +
                  @nodes = {}
         | 
| 129 | 
            +
                  @cdata = false
         | 
| 130 | 
            +
                  @data  = nil
         | 
| 131 | 
            +
                end
         | 
| 132 | 
            +
             | 
| 133 | 
            +
                # @return [Boolean] Return if the element is empty (no text value and no attributes)
         | 
| 134 | 
            +
                def empty?
         | 
| 135 | 
            +
                  self.to_s.empty? && self.attributes.empty?
         | 
| 136 | 
            +
                end
         | 
| 137 | 
            +
             | 
| 138 | 
            +
              private
         | 
| 139 | 
            +
                def method_missing(symb, *args)
         | 
| 140 | 
            +
                  if @nodes.has_key?(symb.to_s)
         | 
| 141 | 
            +
                    return @nodes[symb.to_s]
         | 
| 142 | 
            +
                  else
         | 
| 143 | 
            +
                    raise NoMethodError.new("undefined method or attribute `#{symb}'")
         | 
| 144 | 
            +
                  end
         | 
| 145 | 
            +
                end
         | 
| 146 | 
            +
             | 
| 147 | 
            +
                def process str
         | 
| 148 | 
            +
                  str = str.to_s.strip
         | 
| 149 | 
            +
                  @data = str
         | 
| 150 | 
            +
                end
         | 
| 151 | 
            +
             | 
| 152 | 
            +
              end#Object
         | 
| 153 | 
            +
            end#OXM
         | 
| 154 | 
            +
             | 
| @@ -0,0 +1,57 @@ | |
| 1 | 
            +
            module OXM
         | 
| 2 | 
            +
              class SaxHandler < Nokogiri::XML::SAX::Document
         | 
| 3 | 
            +
                attr_reader :outputs
         | 
| 4 | 
            +
             | 
| 5 | 
            +
                def initialize loop_node, &block
         | 
| 6 | 
            +
                  @loop_node = loop_node
         | 
| 7 | 
            +
                  @block = block
         | 
| 8 | 
            +
                  @tags = []
         | 
| 9 | 
            +
                  @objects = []
         | 
| 10 | 
            +
                  @outputs = []
         | 
| 11 | 
            +
                end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                def start_element tag, attributes
         | 
| 14 | 
            +
                  @tags << tag
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                  # Met loop element
         | 
| 17 | 
            +
                  if @objects.empty?
         | 
| 18 | 
            +
                    if match?
         | 
| 19 | 
            +
                      @objects << @object = OXM::Object.new(tag, Hash[*attributes.flatten])
         | 
| 20 | 
            +
                    end
         | 
| 21 | 
            +
                  elsif @object
         | 
| 22 | 
            +
                    @object.add_node tag, node_obj = OXM::Object.new(tag, Hash[*attributes.flatten])
         | 
| 23 | 
            +
                    @objects << @object = node_obj
         | 
| 24 | 
            +
                  end
         | 
| 25 | 
            +
                end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                def cdata_block str
         | 
| 28 | 
            +
                  @object.cdata = @object.to_s + str if @object
         | 
| 29 | 
            +
                end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                def characters str
         | 
| 32 | 
            +
                  @object.content = @object.to_s + str if @object
         | 
| 33 | 
            +
                end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                def end_element tag
         | 
| 36 | 
            +
                  unless @objects.empty?
         | 
| 37 | 
            +
                    if match?
         | 
| 38 | 
            +
                      obj = @objects.pop
         | 
| 39 | 
            +
                      if @block
         | 
| 40 | 
            +
                        @block.call obj
         | 
| 41 | 
            +
                      else
         | 
| 42 | 
            +
                        @outputs << obj
         | 
| 43 | 
            +
                      end
         | 
| 44 | 
            +
                      @object = nil
         | 
| 45 | 
            +
                    else
         | 
| 46 | 
            +
                      @objects.pop
         | 
| 47 | 
            +
                      @object = @objects.last
         | 
| 48 | 
            +
                    end
         | 
| 49 | 
            +
                  end
         | 
| 50 | 
            +
                  @tags.pop
         | 
| 51 | 
            +
                end
         | 
| 52 | 
            +
             | 
| 53 | 
            +
                def match?
         | 
| 54 | 
            +
                  @tags.join('/') == @loop_node
         | 
| 55 | 
            +
                end
         | 
| 56 | 
            +
              end
         | 
| 57 | 
            +
            end#OXM
         | 
    
        data/lib/oxm.rb
    ADDED
    
    | @@ -0,0 +1,16 @@ | |
| 1 | 
            +
            require 'nokogiri'
         | 
| 2 | 
            +
            require 'builder'
         | 
| 3 | 
            +
            require 'oxm/sax_handler'
         | 
| 4 | 
            +
            require 'oxm/object'
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            module OXM
         | 
| 7 | 
            +
              # @param [IO/String] xml XML data
         | 
| 8 | 
            +
              # @param [String] loop_element
         | 
| 9 | 
            +
              # @return [Array] Array of OXM::Objects
         | 
| 10 | 
            +
              def self.from_xml xml, loop_element, &block
         | 
| 11 | 
            +
                handler = OXM::SaxHandler.new(loop_element, &block)
         | 
| 12 | 
            +
                parser = Nokogiri::XML::SAX::Parser.new(handler)
         | 
| 13 | 
            +
                parser.parse xml
         | 
| 14 | 
            +
                handler.outputs unless block_given?
         | 
| 15 | 
            +
              end
         | 
| 16 | 
            +
            end
         | 
    
        data/test/helper.rb
    ADDED
    
    | @@ -0,0 +1,17 @@ | |
| 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 'test/unit'
         | 
| 11 | 
            +
             | 
| 12 | 
            +
            $LOAD_PATH.unshift(File.dirname(__FILE__))
         | 
| 13 | 
            +
            $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
         | 
| 14 | 
            +
            require 'oxm'
         | 
| 15 | 
            +
             | 
| 16 | 
            +
            class Test::Unit::TestCase
         | 
| 17 | 
            +
            end
         | 
    
        data/test/test_oxm.rb
    ADDED
    
    | @@ -0,0 +1,166 @@ | |
| 1 | 
            +
            require 'helper'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            class TestOxm < Test::Unit::TestCase
         | 
| 4 | 
            +
              def test_from_xml_string
         | 
| 5 | 
            +
                str = <<-EOF
         | 
| 6 | 
            +
                <container attr1="1" attr2="2">
         | 
| 7 | 
            +
                  <item dept="A">
         | 
| 8 | 
            +
                    <volume unit="ml"><![CDATA[ 100 ]]></volume>
         | 
| 9 | 
            +
                    <volume unit="ml"><![CDATA[200]]></volume>
         | 
| 10 | 
            +
                  </item>
         | 
| 11 | 
            +
                  <item dept="B">
         | 
| 12 | 
            +
                    <volume unit="l">200</volume>
         | 
| 13 | 
            +
                    <volume unit="l">300</volume>
         | 
| 14 | 
            +
                  </item>
         | 
| 15 | 
            +
                  <item dept="C">
         | 
| 16 | 
            +
                    <volume unit="l">300</volume>
         | 
| 17 | 
            +
                    <volume unit="ml">400</volume>
         | 
| 18 | 
            +
                  </item>
         | 
| 19 | 
            +
                  <item dept="D">
         | 
| 20 | 
            +
                    <volume unit="L">500</volume>
         | 
| 21 | 
            +
                    <volume></volume>
         | 
| 22 | 
            +
                  </item>
         | 
| 23 | 
            +
                </container>
         | 
| 24 | 
            +
                EOF
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                require 'tempfile'
         | 
| 27 | 
            +
                tf = Tempfile.new('oxm')
         | 
| 28 | 
            +
                tf << str
         | 
| 29 | 
            +
                tf.flush
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                [str, File.open(tf.path)].each do |input|
         | 
| 32 | 
            +
                  result = OXM.from_xml(input, 'container')
         | 
| 33 | 
            +
                  assert       result.is_a?(Array)
         | 
| 34 | 
            +
                  assert_equal 1, result.length
         | 
| 35 | 
            +
                  assert_equal "", result.first.to_s
         | 
| 36 | 
            +
                  assert_equal({'attr1' => '1', 'attr2' => '2'}, result.first.attributes)
         | 
| 37 | 
            +
                  assert_equal(result.first.children, result.first.elements)
         | 
| 38 | 
            +
                  assert_equal(%w[item], result.first.children.keys)
         | 
| 39 | 
            +
                  assert_equal(4, result.first.elements.values.first.length)
         | 
| 40 | 
            +
                  assert_equal '1', result.first['attr1']
         | 
| 41 | 
            +
                  assert_equal '2', result.first['attr2']
         | 
| 42 | 
            +
                  assert_equal nil, result.first['attr3']
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                  assert       result.map(&:item).all? { |items| items.is_a? Array }
         | 
| 45 | 
            +
                  assert       result.map(&:item).map(&:first).all? { |i| i.tag == 'item' }
         | 
| 46 | 
            +
                  assert       result.first.item.first.volume.all? { |i| i.cdata? }
         | 
| 47 | 
            +
                  assert       result.first.item.first.volume.all? { |i| i.content == i.to_s }
         | 
| 48 | 
            +
                  assert       result.first.item.last.volume.all? { |i| i.cdata? == false }
         | 
| 49 | 
            +
             | 
| 50 | 
            +
                  container = result.first
         | 
| 51 | 
            +
                  assert container.compact!.equal?(container) # Object identity
         | 
| 52 | 
            +
                  assert container.item.is_a?(Array)
         | 
| 53 | 
            +
             | 
| 54 | 
            +
                  result = OXM.from_xml(str, 'container/item')
         | 
| 55 | 
            +
                  assert_equal 4, result.length
         | 
| 56 | 
            +
             | 
| 57 | 
            +
                  item = result.last
         | 
| 58 | 
            +
                  item.compact!
         | 
| 59 | 
            +
                  assert item.volume.is_a?(OXM::Object)
         | 
| 60 | 
            +
                  assert_equal '500', item.volume.to_s
         | 
| 61 | 
            +
                  assert_equal 'L', item.volume['unit']
         | 
| 62 | 
            +
             | 
| 63 | 
            +
                  result = OXM.from_xml(str, 'container/item/volume')
         | 
| 64 | 
            +
                  assert_equal 8, result.length
         | 
| 65 | 
            +
                  assert_equal %w[100 200 200 300 300 400 500] + [""], result.map(&:to_s)
         | 
| 66 | 
            +
                  assert_equal %w[ml ml l l l ml L] + [nil], result.map { |e| e['unit'] }
         | 
| 67 | 
            +
                  assert_equal result.map { |e| e['unit'] }, result.map { |e| e[:unit] }
         | 
| 68 | 
            +
                  assert_equal '<volume unit="ml"><![CDATA[100]]></volume>', result.first.to_xml
         | 
| 69 | 
            +
             | 
| 70 | 
            +
                  vol = result[-3]
         | 
| 71 | 
            +
                  assert_equal '<volume unit="ml">400</volume>', vol.to_xml
         | 
| 72 | 
            +
                  vol['unit'] = 'L'
         | 
| 73 | 
            +
                  assert_equal '<volume unit="L">400</volume>', vol.to_xml
         | 
| 74 | 
            +
                  vol.content = 500
         | 
| 75 | 
            +
                  assert_equal '<volume unit="L">500</volume>', vol.to_xml
         | 
| 76 | 
            +
                  vol.content = 550
         | 
| 77 | 
            +
                  assert_equal '<volume unit="L">550</volume>', vol.to_xml
         | 
| 78 | 
            +
                  vol.cdata = 600
         | 
| 79 | 
            +
                  assert_equal '<volume unit="L"><![CDATA[600]]></volume>', vol.to_xml
         | 
| 80 | 
            +
                  vol.cdata = 660
         | 
| 81 | 
            +
                  assert_equal '<volume unit="L"><![CDATA[660]]></volume>', vol.to_xml
         | 
| 82 | 
            +
             | 
| 83 | 
            +
                  long_str = "_" * 1000000
         | 
| 84 | 
            +
                  vol.content = long_str
         | 
| 85 | 
            +
                  assert_equal '<volume unit="L">' + long_str + '</volume>', vol.to_xml
         | 
| 86 | 
            +
             | 
| 87 | 
            +
                  vol.cdata = long_str
         | 
| 88 | 
            +
                  assert_equal '<volume unit="L"><![CDATA[' + long_str + ']]></volume>', vol.to_xml
         | 
| 89 | 
            +
             | 
| 90 | 
            +
                  vol.cdata = ""
         | 
| 91 | 
            +
                  assert_equal '<volume unit="L"><![CDATA[]]></volume>', vol.to_xml
         | 
| 92 | 
            +
             | 
| 93 | 
            +
                  # invalid stripping might occur
         | 
| 94 | 
            +
                  long_str = "_" + ' ' * 1000000 + '_'
         | 
| 95 | 
            +
                  vol.content = long_str
         | 
| 96 | 
            +
                  assert_equal '<volume unit="L">' + long_str + '</volume>', vol.to_xml
         | 
| 97 | 
            +
             | 
| 98 | 
            +
                  vol.content = nil
         | 
| 99 | 
            +
                  assert_equal '<volume unit="L"></volume>', vol.to_xml
         | 
| 100 | 
            +
             | 
| 101 | 
            +
                  cnt = 0
         | 
| 102 | 
            +
                  result = OXM.from_xml(str, 'container/item/volume') do |obj|
         | 
| 103 | 
            +
                    assert_equal 'volume', obj.tag
         | 
| 104 | 
            +
                    assert obj.is_a?(OXM::Object)
         | 
| 105 | 
            +
                    cnt += 1
         | 
| 106 | 
            +
                  end
         | 
| 107 | 
            +
                  assert_equal 8, cnt
         | 
| 108 | 
            +
                  assert_nil result
         | 
| 109 | 
            +
                end
         | 
| 110 | 
            +
              end
         | 
| 111 | 
            +
             | 
| 112 | 
            +
              def test_compaction
         | 
| 113 | 
            +
                str = <<-EOF
         | 
| 114 | 
            +
                <container attr1="1" attr2="2">
         | 
| 115 | 
            +
                  <item dept="array">
         | 
| 116 | 
            +
                    <volume unit="ml"><![CDATA[ 100 ]]></volume>
         | 
| 117 | 
            +
                    <volume unit="ml"><![CDATA[200]]></volume>
         | 
| 118 | 
            +
                  </item>
         | 
| 119 | 
            +
             | 
| 120 | 
            +
                  <item dept="single">
         | 
| 121 | 
            +
                    <volume unit="l">200</volume>
         | 
| 122 | 
            +
                  </item>
         | 
| 123 | 
            +
             | 
| 124 | 
            +
                  <item dept="single">
         | 
| 125 | 
            +
                    <volume unit="ML"></volume>
         | 
| 126 | 
            +
                  </item>
         | 
| 127 | 
            +
             | 
| 128 | 
            +
                  <item dept="single">
         | 
| 129 | 
            +
                    <volume unit="l">200</volume>
         | 
| 130 | 
            +
                    <volume></volume>
         | 
| 131 | 
            +
                  </item>
         | 
| 132 | 
            +
             | 
| 133 | 
            +
                  <item dept="nil">
         | 
| 134 | 
            +
                    <volume></volume>
         | 
| 135 | 
            +
                    <volume></volume>
         | 
| 136 | 
            +
                  </item>
         | 
| 137 | 
            +
                </container>
         | 
| 138 | 
            +
                EOF
         | 
| 139 | 
            +
             | 
| 140 | 
            +
                items = OXM.from_xml(str, 'container/item')
         | 
| 141 | 
            +
                assert_equal 5, items.length
         | 
| 142 | 
            +
             | 
| 143 | 
            +
                items[0].compact!
         | 
| 144 | 
            +
                assert_equal Array, items[0].volume.class
         | 
| 145 | 
            +
             | 
| 146 | 
            +
                items[1].compact!
         | 
| 147 | 
            +
                assert_equal OXM::Object, items[1].volume.class
         | 
| 148 | 
            +
             | 
| 149 | 
            +
                items[2].compact!
         | 
| 150 | 
            +
                assert_equal OXM::Object, items[2].volume.class
         | 
| 151 | 
            +
                assert_equal nil, items[2].volume.content
         | 
| 152 | 
            +
                assert_equal 'ML', items[2].volume['unit']
         | 
| 153 | 
            +
             | 
| 154 | 
            +
                items[3].compact!
         | 
| 155 | 
            +
                assert_equal OXM::Object, items[3].volume.class
         | 
| 156 | 
            +
                assert_equal '<item dept="single"><volume unit="l">200</volume></item>', items[3].inspect
         | 
| 157 | 
            +
                assert_equal "200", items[3].volume.content
         | 
| 158 | 
            +
             | 
| 159 | 
            +
                items[4].compact!
         | 
| 160 | 
            +
                assert_equal nil, items[4].volume
         | 
| 161 | 
            +
             | 
| 162 | 
            +
                assert_raise(NoMethodError) {
         | 
| 163 | 
            +
                  items[4].voll
         | 
| 164 | 
            +
                }
         | 
| 165 | 
            +
              end
         | 
| 166 | 
            +
            end
         | 
    
        metadata
    ADDED
    
    | @@ -0,0 +1,118 @@ | |
| 1 | 
            +
            --- !ruby/object:Gem::Specification
         | 
| 2 | 
            +
            name: oxm
         | 
| 3 | 
            +
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            +
              version: 0.1.0
         | 
| 5 | 
            +
              prerelease: 
         | 
| 6 | 
            +
            platform: ruby
         | 
| 7 | 
            +
            authors:
         | 
| 8 | 
            +
            - Junegunn Choi
         | 
| 9 | 
            +
            autorequire: 
         | 
| 10 | 
            +
            bindir: bin
         | 
| 11 | 
            +
            cert_chain: []
         | 
| 12 | 
            +
            date: 2011-09-19 00:00:00.000000000Z
         | 
| 13 | 
            +
            dependencies:
         | 
| 14 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 15 | 
            +
              name: builder
         | 
| 16 | 
            +
              requirement: &2160763840 !ruby/object:Gem::Requirement
         | 
| 17 | 
            +
                none: false
         | 
| 18 | 
            +
                requirements:
         | 
| 19 | 
            +
                - - ! '>='
         | 
| 20 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 21 | 
            +
                    version: 3.0.0
         | 
| 22 | 
            +
              type: :runtime
         | 
| 23 | 
            +
              prerelease: false
         | 
| 24 | 
            +
              version_requirements: *2160763840
         | 
| 25 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 26 | 
            +
              name: nokogiri
         | 
| 27 | 
            +
              requirement: &2160755540 !ruby/object:Gem::Requirement
         | 
| 28 | 
            +
                none: false
         | 
| 29 | 
            +
                requirements:
         | 
| 30 | 
            +
                - - ! '>='
         | 
| 31 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 32 | 
            +
                    version: 1.5.0
         | 
| 33 | 
            +
              type: :runtime
         | 
| 34 | 
            +
              prerelease: false
         | 
| 35 | 
            +
              version_requirements: *2160755540
         | 
| 36 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 37 | 
            +
              name: bundler
         | 
| 38 | 
            +
              requirement: &2160753840 !ruby/object:Gem::Requirement
         | 
| 39 | 
            +
                none: false
         | 
| 40 | 
            +
                requirements:
         | 
| 41 | 
            +
                - - ~>
         | 
| 42 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 43 | 
            +
                    version: 1.0.0
         | 
| 44 | 
            +
              type: :development
         | 
| 45 | 
            +
              prerelease: false
         | 
| 46 | 
            +
              version_requirements: *2160753840
         | 
| 47 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 48 | 
            +
              name: jeweler
         | 
| 49 | 
            +
              requirement: &2160752880 !ruby/object:Gem::Requirement
         | 
| 50 | 
            +
                none: false
         | 
| 51 | 
            +
                requirements:
         | 
| 52 | 
            +
                - - ~>
         | 
| 53 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 54 | 
            +
                    version: 1.6.4
         | 
| 55 | 
            +
              type: :development
         | 
| 56 | 
            +
              prerelease: false
         | 
| 57 | 
            +
              version_requirements: *2160752880
         | 
| 58 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 59 | 
            +
              name: rcov
         | 
| 60 | 
            +
              requirement: &2160752000 !ruby/object:Gem::Requirement
         | 
| 61 | 
            +
                none: false
         | 
| 62 | 
            +
                requirements:
         | 
| 63 | 
            +
                - - ! '>='
         | 
| 64 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 65 | 
            +
                    version: '0'
         | 
| 66 | 
            +
              type: :development
         | 
| 67 | 
            +
              prerelease: false
         | 
| 68 | 
            +
              version_requirements: *2160752000
         | 
| 69 | 
            +
            description: A tiny Object-XML-Mapper using Nokogiri SAX parser
         | 
| 70 | 
            +
            email: junegunn.c@gmail.com
         | 
| 71 | 
            +
            executables: []
         | 
| 72 | 
            +
            extensions: []
         | 
| 73 | 
            +
            extra_rdoc_files:
         | 
| 74 | 
            +
            - LICENSE.txt
         | 
| 75 | 
            +
            - README.markdown
         | 
| 76 | 
            +
            files:
         | 
| 77 | 
            +
            - .document
         | 
| 78 | 
            +
            - CHANGELOG.markdown
         | 
| 79 | 
            +
            - Gemfile
         | 
| 80 | 
            +
            - Gemfile.lock
         | 
| 81 | 
            +
            - LICENSE.txt
         | 
| 82 | 
            +
            - README.markdown
         | 
| 83 | 
            +
            - Rakefile
         | 
| 84 | 
            +
            - VERSION
         | 
| 85 | 
            +
            - lib/oxm.rb
         | 
| 86 | 
            +
            - lib/oxm/object.rb
         | 
| 87 | 
            +
            - lib/oxm/sax_handler.rb
         | 
| 88 | 
            +
            - test/helper.rb
         | 
| 89 | 
            +
            - test/test_oxm.rb
         | 
| 90 | 
            +
            homepage: http://github.com/junegunn/oxm
         | 
| 91 | 
            +
            licenses:
         | 
| 92 | 
            +
            - MIT
         | 
| 93 | 
            +
            post_install_message: 
         | 
| 94 | 
            +
            rdoc_options: []
         | 
| 95 | 
            +
            require_paths:
         | 
| 96 | 
            +
            - lib
         | 
| 97 | 
            +
            required_ruby_version: !ruby/object:Gem::Requirement
         | 
| 98 | 
            +
              none: false
         | 
| 99 | 
            +
              requirements:
         | 
| 100 | 
            +
              - - ! '>='
         | 
| 101 | 
            +
                - !ruby/object:Gem::Version
         | 
| 102 | 
            +
                  version: '0'
         | 
| 103 | 
            +
                  segments:
         | 
| 104 | 
            +
                  - 0
         | 
| 105 | 
            +
                  hash: 1267901525051297766
         | 
| 106 | 
            +
            required_rubygems_version: !ruby/object:Gem::Requirement
         | 
| 107 | 
            +
              none: false
         | 
| 108 | 
            +
              requirements:
         | 
| 109 | 
            +
              - - ! '>='
         | 
| 110 | 
            +
                - !ruby/object:Gem::Version
         | 
| 111 | 
            +
                  version: '0'
         | 
| 112 | 
            +
            requirements: []
         | 
| 113 | 
            +
            rubyforge_project: 
         | 
| 114 | 
            +
            rubygems_version: 1.8.6
         | 
| 115 | 
            +
            signing_key: 
         | 
| 116 | 
            +
            specification_version: 3
         | 
| 117 | 
            +
            summary: A tiny Object-XML-Mapper
         | 
| 118 | 
            +
            test_files: []
         |