Giter Site home page Giter Site logo

empact / roxml Goto Github PK

View Code? Open in Web Editor NEW
224.0 7.0 178.0 1.19 MB

ROXML is a module for binding Ruby classes to XML. It supports custom mapping and bidirectional marshalling between Ruby and XML using annotation-style class methods, via Nokogiri or LibXML.

Home Page: http://roxml.rubyforge.org/

License: MIT License

Ruby 97.71% HTML 2.29%

roxml's Introduction

ROXML Ruby Object to XML mapping library.

For more information visit:

http://rdoc.info/projects/Empact/roxml
http://empact.github.com/roxml/

Please submit bugs here:

http://github.com/Empact/roxml/issues

Quick Start Guide

This is a short usage example. See ROXML::ClassMethods::Declarations and packaged test cases for more information.

Basic Mapping

Consider an XML document representing a Library containing a number of Books. You can map this structure to Ruby classes that provide addition useful behavior. With ROXML, you can annotate the Ruby classes as follows:

class Book
  include ROXML

  xml_accessor :isbn, :from => "@ISBN" # attribute with name 'ISBN'
  xml_accessor :title
  xml_accessor :description, :cdata => true  # text node with cdata protection
  xml_accessor :author
end

class Library
  include ROXML

  xml_accessor :name, :from => "NAME", :cdata => true
  xml_accessor :books, :as => [Book] # by default roxml searches for books for in <book> child nodes, then, if none are present, in ./books/book children
end

To create a library and put a number of books in it we could run the following code:

book = Book.new
book.isbn = "0201710897"
book.title = "The PickAxe"
book.description = "Best Ruby book out there!"
book.author = "David Thomas, Andrew Hunt, Dave Thomas"

lib = Library.new
lib.name = "Favorite Books"
lib.books = [book]

To save this information to an XML file:

doc = Nokogiri::XML::Document.new
doc.root = lib.to_xml
open("library.xml", 'w') do |file|
  file << doc.serialize
end

or

doc = LibXML::XML::Document.new
doc.root = lib.to_xml
doc.save("library.xml")

To later populate the library object from the XML file:

lib = Library.from_xml(File.read("library.xml"))

Similarly, to do a one-to-one mapping between XML objects, such as book and publisher, you would add a reference to another ROXML class. For example:

<book isbn="0974514055">
  <title>Programming Ruby - 2nd Edition</title>
  <description>Second edition of the great book.</description>
  <publisher>
    <name>Pragmatic Bookshelf</name>
  </publisher>
</book>

can be mapped using the following code:

class Publisher
  include ROXML

  xml_accessor :name

  # other important functionality
end

class BookWithPublisher
  include ROXML

  xml_name 'book'
  xml_reader :publisher, :as => Publisher

  #  or, alternatively, if no class is needed to hang functionality on:
  # xml_reader :publisher, :from => 'name', :in => 'publisher'
end

Note: In the above example, xml_name annotation tells ROXML to set the element name to “book” for mapping to XML. The default is XML element name is the class name in lowercase; “bookwithpublisher” in this case.

Namespace Support

Namespaced nodes are supported via the xml_namespace and xml_namespaces declarations and the :from and :namespace attr options. See spec/xml/namespace_spec.rb for usage.

Note that ROXML does not currently support outputting namespaced nodes. This is planned for a future version.

Manipulation

Extending the above examples, say you want to parse a book’s page count and have it available as an Integer. In such a case, you can extend any object with a block to manipulate it’s value at parse time. For example:

class Dog
  include ROXML

  xml_reader(:age, :from => '@human_years', :as => Integer) {|years| years * 7 }
end

The result of the block above is stored, rather than the actual value parsed from the document.

Construction

Object life-cycle is as follows: .from_xml is called with a first argument representing the xml in file, string, or path form, and with optional initialization_args following.

Firt .new and thus #initialize, is called with those same initialization_args, or no args if none are present. Then the object is populated with the attribute values from xml. Then the #after_parse callback is called, with no arguments.

In #after_parse you can ensure that your object initialization is complete, including initialization which requires more than one variable in concert.

E.g.:

class Measurement
  include ROXML

  xml_reader :units, :from => :attr
  xml_reader :value, :from => :content

  def initialize(value = 0, units = 'meters')
    to_metric
  end

private
  def after_parse
    # xml attributes of self are already valid
    to_metric
  end

  def to_metric
    # translate units & value into metric, for example
  end
end

One important use of this approach is to make ROXML object which may or may not include an xml backing, which may be used via new construction as well as from_xml construction.

Selecting a parser

By default, ROXML will use Nokogiri if it is available, followed by LibXML. If you’d like to explicitly require one or the other, you may do the following:

module ROXML
  XML_PARSER = 'nokogiri' # or 'libxml'
end
require 'roxml'

For more information on available annotations, see ROXML::ClassMethods::Declarations

Note on Patches/Pull Requests

  • Fork the project.

  • Make your feature addition or bug fix.

  • Add specs for it. This is important so I don’t break it in a future version unintentionally.

  • Commit, do not mess with rakefile, version, or history. (if you want to have your own version, that is fine but

    bump version in a commit by itself I can ignore when I pull)
  • Send me a pull request. Bonus points for topic branches.

Copyright © 2004-2024 Ben Woosley, Zak Mandhro and Anders Engstrom. See LICENSE for details.

roxml's People

Contributors

angelo0000 avatar chewi avatar dbarros avatar dependabot[bot] avatar empact avatar findchris avatar greis avatar ibrahim-saifee avatar jarib avatar jnunemaker avatar jpshackelford avatar lostapathy avatar lucaskanashiro avatar megle avatar mrkcor avatar nakajima avatar pat avatar rmacklin avatar romuloceccon avatar ryanong avatar timriley avatar vihai avatar yob avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

roxml's Issues

Generating XML from object without indentation

Hi @Empact,
I want to generate xml from ruby object without indentation('\n'), but I could not find any option.

book = Book.new
book.isbn = "0201710897"
book.title = "The PickAxe"
book.description = "Best Ruby book out there!"
book.author = "David Thomas, Andrew Hunt, Dave Thomas"

doc = Nokogiri::XML::Document.new
doc.root = book.to_xml

Is there a way I can remove indentation as below in ROXML as similar to to_xml in ActiveSupport :
doc.root = book.to_xml(:indent =>0)

After marshalling/unmarshalling nil is frozen

Marshalling or unmarshalling an XML document using ROXML is freezing nil.

I have included a failing spec that demonstrates the issue and a copy of the Gemfile and rvm config that was used to run the spec.

frozen_nil_spec.rb

require 'rubygems'
require 'roxml'

describe 'roxml' do
  let(:xml_file) { File.open(File.expand_path('library.xml', File.dirname(__FILE__))) }

  context 'before unmarshalling an XML document' do
    it { nil.should_not be_frozen }
  end

  context 'after unmarshalling an XML document' do
    before do
      lib = Library.from_xml(xml_file)
    end

    it { nil.should_not be_frozen }
  end
end

class Book
  include ROXML

  xml_accessor :isbn, :from => "@ISBN" # attribute with name 'ISBN'
  xml_accessor :title
  xml_accessor :description, :cdata => true  # text node with cdata protection
  xml_accessor :author
end


class Library
  include ROXML

  xml_accessor :name, :from => "NAME", :cdata => true
  xml_accessor :books, :as => [Book] # by default roxml searches for books for in <book> child nodes, then, if none are present, in ./books/book children
end

rspec output

.F

Failures:

  1) roxml after unmarshalling an XML document 
     Failure/Error: it { nil.should_not be_frozen }
       expected frozen? to return false, got true
     # ./spec/frozen_nil_spec.rb:16:in `block (3 levels) in <top (required)>'

Finished in 0.00151 seconds
2 examples, 1 failure

Failed examples:

rspec ./spec/frozen_nil_spec.rb:16 # roxml after unmarshalling an XML document 

library.xml

<?xml version="1.0"?>
<library>
  <NAME><![CDATA[Favorite Books]]></NAME>
  <book ISBN="0201710897">
    <title>The PickAxe</title>
    <description><![CDATA[Best Ruby book out there!]]></description>
    <author>David Thomas, Andrew Hunt, Dave Thomas</author>
  </book>
</library>

Gemfile

source 'http://rubygems.org'

gem 'roxml', '3.2.0'
gem 'rspec', '2.6.0'
gem 'i18n'

Gemfile.lock

GEM
  remote: http://rubygems.org/
  specs:
    activesupport (3.1.3)
      multi_json (~> 1.0)
    diff-lcs (1.1.3)
    i18n (0.6.0)
    multi_json (1.0.4)
    nokogiri (1.5.0)
    roxml (3.2.0)
      activesupport (>= 2.3.0)
      nokogiri (>= 1.3.3)
    rspec (2.6.0)
      rspec-core (~> 2.6.0)
      rspec-expectations (~> 2.6.0)
      rspec-mocks (~> 2.6.0)
    rspec-core (2.6.4)
    rspec-expectations (2.6.0)
      diff-lcs (~> 1.1.2)
    rspec-mocks (2.6.0)

PLATFORMS
  ruby

DEPENDENCIES
  i18n
  roxml (= 3.2.0)
  rspec (= 2.6.0)

.rvmrc

rvm 1.9.2-p290@roxml --create

One test is failing: ROXML::XML should raise on malformed xml

Running tests for ruby1.9.1 using debian/ruby-tests.rb...
/usr/lib/ruby/1.9.1/rubygems/custom_require.rb:36:in `require': iconv will be deprecated in the future, use String#encode instead.
/media/forge/debian/diaspora/ruby-roxml-3.2.2/spec/support/nokogiri.rb:2: warning: already initialized constant XML_PARSER
/media/forge/debian/diaspora/ruby-roxml-3.2.2/spec/support/libxml.rb:2: warning: already initialized constant XML_PARSER
......**.........................*..**.*..**....*...*F..*..............................******........................................................*..............................*................................

Pending:
  ROXML#xml overriding output with :to_xml option should output with to_xml filtering
    # Not Yet Implemented
    # 
  ROXML#xml overriding output with #to_xml on the object should output with to_xml filtering
    # Not Yet Implemented
    # 
  ROXML::XMLAttributeRef plain vanilla should output one instance
    # Not Yet Implemented
    # 
  ROXML::XMLAttributeRef when the namespaces are different with :namespace => '*' should collect all instances
    # Test bug?
    # 
  ROXML::XMLAttributeRef when the namespaces are different with :namespace => '*' should output all instances with namespaces
    # Full namespace write support
    # 
  ROXML::XMLObjectRef plain vanilla should output one instance
    # Not Yet Implemented
    # 
  ROXML::XMLObjectRef when the namespaces are different with :namespace => '*' should collect all instances
    # Test bug?
    # 
  ROXML::XMLObjectRef when the namespaces are different with :namespace => '*' should output all instances with namespaces
    # Full namespace write support
    # 
  ROXML::XMLTextRef plain vanilla should output one instance
    # Not Yet Implemented
    # 
  ROXML::XMLTextRef when the namespaces are different with :namespace => '*' should output all instances with namespaces
    # Full namespace write support
    # 
  ROXML with namespaces for writing#to_xml should reproduce the input xml
    # Full namespace write support
    # 
  ROXML#xml_namespaces when an included namespace is not defined in the xml where the missing namespace is the default should raise
    # Not Yet Implemented
    # 
  ROXML#xml_namespaces when an included namespace is not defined in the xml where the missing namespace is the default but the namespace is declared in the body should succeed
    # Not Yet Implemented
    # 
  ROXML#xml_namespaces when an included namespace is not defined in the xml where the missing namespace is included in a namespacey from should raise
    # Not Yet Implemented
    # 
  ROXML#xml_namespaces when an included namespace is not defined in the xml where the missing namespace is included in a namespacey from but the namespace is declared in the body should succeed
    # Not Yet Implemented
    # 
  ROXML#xml_namespaces when an included namespace is not defined in the xml where the missing namespace is included in an explicit :namespace should raise
    # Not Yet Implemented
    # 
  ROXML#xml_namespaces when an included namespace is not defined in the xml where the missing namespace is included in an explicit :namespace but the namespace is declared in the body should succeed
    # Not Yet Implemented
    # 
  ROXML::Definition :as for block shorthand :bool when no value is detected when a literal block is available should pass the value itself to the block
    # Not Yet Implemented
    # 
  WeatherObservation#current_condition should extract icon attribute
    # need to think options through for HappyMapper-style :attributes extensions
    # 

Failures:

  1) ROXML::XML should raise on malformed xml
     Failure/Error: Unable to find matching line from backtrace
     NameError:
       uninitialized constant LibXML
     # ./spec/xml/parser_spec.rb:6:in `block (2 levels) in <top (required)>'

Finished in 0.72903 seconds
213 examples, 1 failure, 19 pending
/media/forge/debian/diaspora/ruby-roxml-3.2.2/lib/roxml.rb:449:in `block (2 levels) in xml_attr': Accessor role is already defined as XML accessor in class Contributor (RuntimeError)
    from /media/forge/debian/diaspora/ruby-roxml-3.2.2/lib/roxml.rb:447:in `tap'
    from /media/forge/debian/diaspora/ruby-roxml-3.2.2/lib/roxml.rb:447:in `block in xml_attr'
    from /media/forge/debian/diaspora/ruby-roxml-3.2.2/lib/roxml.rb:446:in `map'
    from /media/forge/debian/diaspora/ruby-roxml-3.2.2/lib/roxml.rb:446:in `xml_attr'
    from /media/forge/debian/diaspora/ruby-roxml-3.2.2/lib/roxml.rb:462:in `xml_reader'
    from /media/forge/debian/diaspora/ruby-roxml-3.2.2/test/mocks/mocks.rb:26:in `<class:Contributor>'
    from /media/forge/debian/diaspora/ruby-roxml-3.2.2/test/mocks/mocks.rb:23:in `<top (required)>'
    from /media/forge/debian/diaspora/ruby-roxml-3.2.2/test/test_helper.rb:3:in `require_relative'
    from /media/forge/debian/diaspora/ruby-roxml-3.2.2/test/test_helper.rb:3:in `<top (required)>'
    from /media/forge/debian/diaspora/ruby-roxml-3.2.2/test/unit/xml_text_test.rb:1:in `require_relative'
    from /media/forge/debian/diaspora/ruby-roxml-3.2.2/test/unit/xml_text_test.rb:1:in `<top (required)>'
    from /usr/lib/ruby/1.9.1/rubygems/custom_require.rb:36:in `require'
    from /usr/lib/ruby/1.9.1/rubygems/custom_require.rb:36:in `require'
    from /usr/lib/ruby/vendor_ruby/active_support/dependencies.rb:182:in `block in require'
    from /usr/lib/ruby/vendor_ruby/active_support/dependencies.rb:547:in `new_constants_in'
    from /usr/lib/ruby/vendor_ruby/active_support/dependencies.rb:182:in `require'
    from debian/ruby-tests.rb:7:in `block in <main>'
    from debian/ruby-tests.rb:7:in `each'
    from debian/ruby-tests.rb:7:in `<main>'

Remove use of deprecated child_add methods

ROXML 2.5.3 has 5 different places where XML::Node.child_add is being called. That has been in deprecated in favor of XML::Node.<< instead. I believe they are functionally equivalent, making this mostly a find and replace effort. It would be great to switch over to the new preferred method, because the deprecation warnings get a little tedious to wade through when running tests.

Note that the reference that shows up for libxml.rb below is a comment, not code.

[user@hostname roxml-2.5.3]$ find . -name *.rb | grep child_add
[user@hostname roxml-2.5.3]$ find . -name *.rb | xargs grep child_add
./lib/roxml/xml/parsers/libxml.rb:        # libxml 1.1.3 changed child_add from returning child to returning self
./lib/roxml/xml/references.rb: dest.child_add(XML::Node.new_cdata(value.to_s.to_utf_without_deprecation))
./lib/roxml/xml/references.rb:        node = xml.child_add(XML::Node.new(hash.wrapper))
./lib/roxml/xml/references.rb:          xml.child_add(v.to_xml(name))
./lib/roxml/xml/references.rb:        xml.child_add(value.to_xml(name))
./lib/roxml/xml/references.rb:        xml.child_add(node)
[user@hostname roxml-2.5.3]$

Roxml with Rails3 gives - `initialize': undefined method `ends_with?' for "url":String (NoMethodError)

When using roxml with ruby-1.9.2 and rails3, we get following error.

/home/neduma/.rvm/gems/ruby-1.9.2-head@rails3/gems/roxml-3.1.5/lib/roxml/definition.rb:35:in `initialize': undefined method `ends_with?' for "url":String (NoMethodError)
    from /home/neduma/.rvm/gems/ruby-1.9.2-head@rails3/gems/roxml-3.1.5/lib/roxml.rb:438:in `new'
    from /home/neduma/.rvm/gems/ruby-1.9.2-head@rails3/gems/roxml-3.1.5/lib/roxml.rb:438:in `block in xml_attr'
    from /home/neduma/.rvm/gems/ruby-1.9.2-head@rails3/gems/roxml-3.1.5/lib/roxml.rb:437:in `map'
    from /home/neduma/.rvm/gems/ruby-1.9.2-head@rails3/gems/roxml-3.1.5/lib/roxml.rb:437:in `xml_attr'
    from /home/neduma/.rvm/gems/ruby-1.9.2-head@rails3/gems/roxml-3.1.5/lib/roxml.rb:453:in `xml_reader'
    from /home/neduma/.rvm/gems/ruby-1.9.2-head@rails3/gems/linkedin-0.1.7/lib/linked_in/api_standard_profile_request.rb:5:in `'
    from /home/neduma/.rvm/gems/ruby-1.9.2-head@rails3/gems/linkedin-0.1.7/lib/linked_in/api_standard_profile_request.rb:2:in `'
    from /home/neduma/.rvm/gems/ruby-1.9.2-head@rails3/gems/linkedin-0.1.7/lib/linked_in/api_standard_profile_request.rb:1:in `'
    from /home/neduma/.rvm/gems/ruby-1.9.2-head@rails3/gems/linkedin-0.1.7/lib/linkedin.rb:70:in `require'
    from /home/neduma/.rvm/gems/ruby-1.9.2-head@rails3/gems/linkedin-0.1.7/lib/linkedin.rb:70:in `'
    from /home/neduma/.rvm/gems/ruby-1.9.2-head@rails3/gems/bundler-0.9.24/lib/bundler/runtime.rb:46:in `require'
    from /home/neduma/.rvm/gems/ruby-1.9.2-head@rails3/gems/bundler-0.9.24/lib/bundler/runtime.rb:46:in `block (2 levels) in require'
    from /home/neduma/.rvm/gems/ruby-1.9.2-head@rails3/gems/bundler-0.9.24/lib/bundler/runtime.rb:41:in `each'
    from /home/neduma/.rvm/gems/ruby-1.9.2-head@rails3/gems/bundler-0.9.24/lib/bundler/runtime.rb:41:in `block in require'
    from /home/neduma/.rvm/gems/ruby-1.9.2-head@rails3/gems/bundler-0.9.24/lib/bundler/runtime.rb:40:in `each'
    from /home/neduma/.rvm/gems/ruby-1.9.2-head@rails3/gems/bundler-0.9.24/lib/bundler/runtime.rb:40:in `require'
    from /home/neduma/.rvm/gems/ruby-1.9.2-head@rails3/gems/bundler-0.9.24/lib/bundler.rb:89:in `gem_require'
    from /home/neduma/r/dotprofile/config/application.rb:7:in `'
    from /home/neduma/.rvm/gems/ruby-1.9.2-head@rails3/gems/railties-3.0.0.beta3/lib/rails/commands.rb:39:in `require'
    from /home/neduma/.rvm/gems/ruby-1.9.2-head@rails3/gems/railties-3.0.0.beta3/lib/rails/commands.rb:39:in `'
    from script/rails:9:in `require'
    from script/rails:9:in `'

wishlist: port spec suite to RSpec3

Hi,

Please port the specs to RSpec v3. The Debian project wrote a patch for basic support. I'll send the link to the patch for reference.

Cheers,

Cédric

RequiredElementMissing is a subclass of Exception

The custom exception class RequiredElementMissing is raised when a required xml accessor is missing during parsing. It is currently a subclass of Exception, meaning that you can't use "rescue => e" to rescue an exception. Instead you'd have to directly rescue it or use "rescue Exception => e". My take is that this behavior is too surprising. It might be a good idea to at least document the difference in the rdocs.

unable to run any tests

/usr/bin/ruby1.9.1 -I/usr/lib/ruby/vendor_ruby /usr/lib/ruby/vendor_ruby/gem2deb/test_runner.rb
Running tests for ruby1.9.1 using debian/ruby-tests.rb...
/usr/lib/ruby/1.9.1/rubygems/custom_require.rb:36:in require': iconv will be deprecated in the future, use String#encode instead. /media/forge/debian/diaspora/ruby-roxml-3.2.1/lib/roxml.rb:4:in<top (required)>': undefined method version' for nil:NilClass (NoMethodError) from /media/forge/debian/diaspora/ruby-roxml-3.2.1/spec/spec_helper.rb:7:inrequire_relative'
from /media/forge/debian/diaspora/ruby-roxml-3.2.1/spec/spec_helper.rb:7:in <top (required)>' from /usr/lib/ruby/1.9.1/rubygems/custom_require.rb:36:inrequire'
from /usr/lib/ruby/1.9.1/rubygems/custom_require.rb:36:in require' from debian/ruby-tests.rb:7:inblock in

'
from debian/ruby-tests.rb:7:in each' from debian/ruby-tests.rb:7:in'

and debian/ruby-tests.rb is

Dir['{spec,test}/*/.rb'].each { |f| require f }

$ ruby1.9.1 -v
ruby 1.9.3p0 (2011-10-30 revision 33570) [x86_64-linux]

I'm creating a debian package of roxml using gem2deb tool.

Flesh out Namespaced Attribute support

Reported by James Healy:

I’m trying to generate an XML that has a root element like so:

I can add the version attribute no worries, but can’t quite work out the
namespaced attributes. I guessed at the following lines, but they cause
a libxml segfault:

xml_accessor :xsi, :from => “@xmlns:xsi” xml_accessor :schema_location, :from => “@xsi:schemaLocation”

Obsolete references to URI.escape and URI.unescape

I'm seeing the following two deprecation warnings (Ruby 2.7.1, Rails 6.0.3.1), both from /app/vendor/bundle/ruby/2.7.0/gems/roxml-4.1.0/lib/roxml/xml/references.rb:50:

warning: URI.unescape is obsolete
warning: URI.escape is obsolete

URI.unescape(convention.call(URI.escape(what, /\/|::/)))

xmlns in root node

Hi there,

how do I have to use roxml to get

 xmlns:namespace=example.com

as parameter in root node when using

Object.to_xml.to_s

I tried to figure out how to do it by myself, but I didn't find a way to do it (I had a look at spec/namespaces).

I used the following input file (btw: this is how the output should look like)

<?xml version="1.0" encoding="UTF-8"?>
<ns2:user xmlns:ns2="http://foo.example.com">                                                                                               
  <attribute>attr</attribute>
</ns2:user>

and the following script

require 'roxml'
require 'pry'
require 'pp'

class User
  include ROXML

 #not needed but my real classes look like UserSimple etc.
  xml_name 'user'
  xml_namespace :ns2
  xml_namespaces :ns2 => 'http://foo.example.com'

  xml_accessor :attribute, :namespace => false                                                                                              
end


user = User.from_xml(File.read(File.expand_path('example-user.xml', File.dirname(__FILE__))))
pp user.to_xml.to_s

Help would be very welcome, as I'm stuck in the moment and need the stuff working for my master thesis.

Thanks.

Cheers,
Max meyer

Can't have an array with plural names ?

Hi, I'm consuming a WebService that gives me some weird XML.
I have something like

    <root_node>
      <some_node>
        <books><id>5</id><name>Book 5</name></books>
        <books><id>9</id><name>Book 9</name></books>
      </some_node>
    </root_node>

I'd like to have an array of "books", but it seems impossible (as far as I can tell) because the "books" node name is already a plural.
I know, I should be singular in the first place, but I don't control this, it comes from a major player in the tourism industry.

I've tried many things, including specifying an explicit :from, … but it doesn't work.
If I create a copy of the XML and change "books" into a singular node, it's working great.

Any idea on how I can do this ?

cannot load such file -- rexml/xpath_parser

Reference ruckus/quickbooks-ruby#598

When using gem quickbooks-ruby, with the xml at bottom, roxml throws error:

$HOME/lib/roxml/xml/references.rb:62:in `require': cannot load such file -- rexml/xpath_parser (LoadError)

Failing XML:

<Customer domain="QBO" sparse="false">
  <Id>58</Id>
  <SyncToken>0</SyncToken>
  <MetaData>
    <CreateTime>2024-05-21T02:37:36-07:00</CreateTime>
    <LastUpdatedTime>2024-05-21T02:37:36-07:00</LastUpdatedTime>
  </MetaData>
  <FullyQualifiedName>Company B</FullyQualifiedName>
  <CompanyName>Company B</CompanyName>
  <DisplayName>Company B</DisplayName>
  <PrintOnCheckName>Company B</PrintOnCheckName>
  <Active>true</Active>
  <PrimaryEmailAddr>
    <Address>[email protected]</Address>
  </PrimaryEmailAddr>
  <Taxable>true</Taxable>
  <Job>false</Job>
  <BillWithParent>false</BillWithParent>
  <Balance>0</Balance>
  <BalanceWithJobs>0</BalanceWithJobs>
  <CurrencyRef name="United States Dollar">USD</CurrencyRef>
  <PreferredDeliveryMethod>Print</PreferredDeliveryMethod>
  <IsProject>false</IsProject>
  <ClientEntityId>0</ClientEntityId>
</Customer>

Can't require ROXML outside of Rails

Hi,

I'd like to use ROXML in a simple Ruby script (or in irb)
When I require it I get an error "NoMethodError: undefined method `delegate' for ROXML::XMLRef:Class"

The only things I do before I get the error are :
require 'rubygems'
require 'roxml'

Ability to traverse to the parent object

Just a quick question regarding the traversal of the object graph, I would like to traverse up to the parent from a leaf object. For example

Blog has-many Posts

<blog>
   <post>...</post>
   <post>...</post>
</blog>

Can an instance of Post traverse to it's parent Blog?

Any help would be much appreciated

cheers

Please release new gem version

@Empact can we cut a new gem version that includes the recent fixes to trunk? Specifically, the ruby-2.4 compatibility changes would get a lot of warnings out of logs for people.

thanks!

Content stored as XML instead of String

I have some deep XML that I would like to store as XML instead of Text.

<books>
  <book>The story of my life</book>
  <book>The story of your life</book>
</books>

If xml_accessor :books, :from => :content it is stored like : The story of my life The story of your life

is it possible to store or get the element as XML

<book>The story of my life</book>
<book>The story of your life</book>

Thanks,

Christopher

undefined method `each' for "":String in ruby 1.9.3

roxml (3.3.1) lib/roxml/xml/references.rb:179:in block in update_xml' roxml (3.3.1) lib/roxml/xml/references.rb:173:intap'
roxml (3.3.1) lib/roxml/xml/references.rb:173:in update_xml' roxml (3.3.1) lib/roxml.rb:42:inblock (2 levels) in to_xml'
roxml (3.3.1) lib/roxml.rb:39:in each' roxml (3.3.1) lib/roxml.rb:39:inblock in to_xml'
roxml (3.3.1) lib/roxml.rb:35:in tap' roxml (3.3.1) lib/roxml.rb:35:into_xml'
roxml (3.3.1) lib/roxml/xml/references.rb:295:in block (2 levels) in update_xml' roxml (3.3.1) lib/roxml/xml/references.rb:294:ineach'
roxml (3.3.1) lib/roxml/xml/references.rb:294:in block in update_xml' roxml (3.3.1) lib/roxml/xml/references.rb:291:intap'
roxml (3.3.1) lib/roxml/xml/references.rb:291:in update_xml' roxml (3.3.1) lib/roxml.rb:42:inblock (2 levels) in to_xml'
roxml (3.3.1) lib/roxml.rb:39:in each' roxml (3.3.1) lib/roxml.rb:39:inblock in to_xml'
roxml (3.3.1) lib/roxml.rb:35:in tap' roxml (3.3.1) lib/roxml.rb:35:into_xml'

Need to upgrade as per latest ruby.

rails3 compatible gem release?

Hi Ben,

I know you're not keen on supporting this gem going forward, but I'm hoping you can release a snapshot of the current repo and make it compatible with activesupport 3.0. It looks like there's aa fork that has the necesary changes.

I've got a branch of our app for testing on rails3 and roxml requiring activesupport 2.3 is a sticking point.

cheers!

Don't rely on ActiveSupport, for Merb and others' sake

Ideally, we’d carry our own extensions with us, or not extend at all.

Reported by gconaty:

Any way you can not include all of active support? I’m using ROXML with Merb and the active support JSON being included by ROXML is breaking my app :) Having the gem worked before because you were just requiring specific modules.

I know you can turn off Merb’s use of the JSON gem, but it actually produces valid JSON in some cases where ActiveSupport is breaking down.

Avoid redefining standard rake calls

We've vendored roxml in our Rails app, and since you have a /tasks directory, Rails treats that as rake tasks available to the whole app. Since you're redefining a lot of standard stuff — rake spec, rake rcov — it ended up chaining onto and double-running our entire spec library when we ran our own root-level rake spec.

xml_name - missing letter s

I have found that the last letter s is dropped from the XML produced when the xml_name ends with the letter s.

xml_name 'Address' --> xml Addres
xml_name 'Demographics' --> xml Demographic

to fix this i have added a space and the s shows along with the space.

on a side note your library is awesome - thanks.

Thanks

Unable to read collection into Array

Hello,

I am facing an issue trying to read book from books into an object.

twist@tintin /tmp/go >cat books.rb

require 'rubygems'
require 'roxml'

class Publisher
include ROXML
xml_reader :name
end

class Book
include ROXML
end

class Library
include ROXML
xml_reader :books, :as=>[Book]
end

text="foobar"
lib = Library.from_xml(text)
puts lib.books.size

twist@tintin /tmp/go >which ruby
/home/twist/.rvm/rubies/ruby-1.8.7-p334/bin/ruby

twist@tintin /tmp/go >ruby books.rb
1

The expected output should be 2 in this case and not 1.

I am using 1.8.7 and unable to run specs. I looked at the log and found that the tests were only 1.8.7 compatible. Can somebody confirm this issue on 1.8.7?

Please let me know.

Thank you,

crafty

Could you avoid modifying the behavior of Nokogiri ?

The commit http://github.com/Empact/roxml/commit/9f0d49613f3337a7232d9d5cbebb44ffef34b10a monkey-patches Nokogiri::XML::Node.search, by adding "./" to every given xpath.

  • module NodeExtensions
  •  def search(xpath)
    
  •    super("./#{xpath}")
    
  •  end
    
  • end

Is this really necessary ? It simply breaks any other code in the same project that will use Nokogiri. For example, it breaks Mechanize in this case: getting all the fields in an HTML form. The patch forbids the search of child nodes in the

tag.

Collections automatically-wrapped on input aren't output with their wrappers

From gorism:

BTW, I noticed that I still need to use an ”:in” option to enclose a collection of elements in an outer element. E.g.
xml_accessor :errors, :as => [Error], :in => ‘errors’

I tried using something like:
xml_accessor :errors, :as => [Error]

But it wouldn’t include an enclosing element.

Mongrel + Rails 2.3.1 interaction?

Reported by James Healy:

On an unrelated note, I’m seeing an odd interation with ROXML 2.5.1 and
rails 2.3.1. I’ve got a test branch where I’m trying out my app on rails
2.3.1, and mongrel is refusing to boot since I started using 2.5.1.
Everything still works as expected with rails 2.2.2.

=> Booting Mongrel
=> Rails 2.3.1 application starting on http://0.0.0.0:3000
/var/lib/gems/1.8/gems/roxml-2.5.1/lib/roxml/definition.rb:48:in `try’: undefined method`xml_name_without_deprecation?’ for :text:Symbol (NoMethodError)
from /var/lib/gems/1.8/gems/roxml-2.5.1/lib/roxml/definition.rb:48:in `initialize’
from /var/lib/gems/1.8/gems/roxml-2.5.1/lib/roxml.rb:445:in`new’
from /var/lib/gems/1.8/gems/roxml-2.5.1/lib/roxml.rb:445:in `xml_attr’
from /var/lib/gems/1.8/gems/roxml-2.5.1/lib/roxml.rb:474:in`xml_accessor’
from /var/lib/gems/1.8/gems/onix-0.5.1/lib/onix/sender_identifier.rb:7
from /usr/lib/ruby/1.8/rubygems/custom_require.rb:31:in `gem_original_require’
from /usr/lib/ruby/1.8/rubygems/custom_require.rb:31:in`require’
from /var/lib/gems/1.8/gems/activesupport-2.3.1/lib/active_support/dependencies.rb:156:in `require’
from /var/lib/gems/1.8/gems/activesupport-2.3.1/lib/active_support/dependencies.rb:521:in`new_constants_in’
from /var/lib/gems/1.8/gems/activesupport-2.3.1/lib/active_support/dependencies.rb:156:in `require’
from /var/lib/gems/1.8/gems/onix-0.5.1/lib/onix.rb:65
from /usr/lib/ruby/1.8/rubygems/custom_require.rb:31:in`gem_original_require’
from /usr/lib/ruby/1.8/rubygems/custom_require.rb:31:in `require’
from /var/lib/gems/1.8/gems/activesupport-2.3.1/lib/active_support/dependencies.rb:156:in`require’
from /var/lib/gems/1.8/gems/activesupport-2.3.1/lib/active_support/dependencies.rb:521:in `new_constants_in’
from /var/lib/gems/1.8/gems/activesupport-2.3.1/lib/active_support/dependencies.rb:156:in`require’
from /var/lib/gems/1.8/gems/rails-2.3.1/lib/rails/gem_dependency.rb:96:in `load’
from /var/lib/gems/1.8/gems/rails-2.3.1/lib/initializer.rb:304:in`load_gems’
from /var/lib/gems/1.8/gems/rails-2.3.1/lib/initializer.rb:304:in `each’
from /var/lib/gems/1.8/gems/rails-2.3.1/lib/initializer.rb:304:in`load_gems’
from /var/lib/gems/1.8/gems/rails-2.3.1/lib/initializer.rb:162:in `process’
from /var/lib/gems/1.8/gems/rails-2.3.1/lib/initializer.rb:113:in`send’
from /var/lib/gems/1.8/gems/rails-2.3.1/lib/initializer.rb:113:in `run’
from /home/jh/git/rba_staff_site/config/environment.rb:13
from /usr/lib/ruby/1.8/rubygems/custom_require.rb:31:in`gem_original_require’
from /usr/lib/ruby/1.8/rubygems/custom_require.rb:31:in `require’
from /var/lib/gems/1.8/gems/activesupport-2.3.1/lib/active_support/dependencies.rb:156:in`require’
from /var/lib/gems/1.8/gems/activesupport-2.3.1/lib/active_support/dependencies.rb:521:in `new_constants_in’
from /var/lib/gems/1.8/gems/activesupport-2.3.1/lib/active_support/dependencies.rb:156:in`require’
from /var/lib/gems/1.8/gems/rails-2.3.1/lib/commands/server.rb:84
from /usr/lib/ruby/1.8/rubygems/custom_require.rb:31:in `gem_original_require’
from /usr/lib/ruby/1.8/rubygems/custom_require.rb:31:in`require’
from ./script/server:3

Cannot override autoparsed DateTime (e.g. 'created_at') class using :as option

From History.txt:
Default attrs ending in '_at' to DateTime. This can be overriden via :as

I have a ROXML class with a 'created_at' XML accessor. I do not want the value to be auto-parsed to a DateTime. So I tried to override this use the :as option (per the History.txt) two different ways. See below:
xml_accessor :created_at, :as => :text
xml_accessor :created_at, :as => String

In both cases, I get an:
ArgumentError: Invalid :as argument

Either this is a bug or my syntax is off. Any guidance?

Cheers.

ROXML encoding

I've created this simple class:
class TestResult
include ROXML
xml_accessor :message
end

My controller code looks like this:
def test
res = TestResult.new
res.message = "Žlutý kůň"
respond_to do |format|
format.xml {render :xml=>res.to_xml}
end
end
Output in a browser is (UTF-8):
<testresult>
Žlutý ků�
</testresult>

Output should be:

Žlutý kůň�

I am using libxml.
Thanks.
Pavel

Can't Marshal a ROXML object because of Proc variables

Hi there.

Just recently, I started getting this error when trying to put my class in memcache:
no marshal_dump is defined for class Proc

I inspected some of the objects, and sometimes an object does indeed contain a Proc. See below:
@blocks=[#Proc:0x0197eff4@/path_to/gems/roxml-3.1.5/lib/roxml/definition.rb:186]

Is there anything I can do to eagerly call these procs to avoid this issue? Can you shed any light on what this variable is used for?

Cheers.

Mapping ActiveRecords to non-AR ruby objects => SystemStackError

Hi there.

I have two (Rails) applications: One is using ActiveRecord, the other is not.

In the DB-backed app I have models like:

class Post < ActiveRecord::Base
  has_many :comments

  include ROXML
  xml_attr :id
  xml_attr :body
  xml_attr :comments, :as => [Comment], :in => "comments"
end

class Comment < ActiveRecord::Base
  belongs_to :post

  include ROXML
  xml_attr :id
  xml_attr :body
  xml_attr :post, :as => Post
end 

In the non-AR-based app, which will consume the XML generated from the AR-based app, I have:

class Post
  include ROXML

  xml_accessor :id
  xml_accessor :body
  xml_accessor :comments, :as => [Comment]
end
class Comment
  include ROXML

  xml_accessor :id
  xml_accessor :body
  xml_accessor :post, :as => Post
end

The problem is, when I try to generate the XML, I (not so unexpectedly) get this:

>> Post.first.to_xml.to_s
SystemStackError: stack level too deep

So the question is: How to map ActiveRecord objects (with associations) to non-ActiveRecord objects using ROXML?

In the app not using ActiveRecord, I'd like to be able to go through relations, such as in:

the_post.comments.post.name

Not sure if this is possible, but I'd appreciate your insight.

Cheers.
-Chris

#to_latin and #to_utf are backwards

From [Rubyforge](http://rubyforge.org/tracker/index.php?func=detail&aid=24258&group_id=305&atid=1244):

The to_utf and to_latin functions are back to front. This means that any string containing non-ascii sequences will be trashed. I think we just need to switch the 2 function definition names and we are good.

Example:

utf_string = “ROXML\342\204\242” # that codes for trademark symbol in UTF-8.
puts utf_string.to_utf.inspect # Should do nothing. it’s already utf8.

→ “ROXML\303\242\302\204\302\242” # YIKES !

should return

→ “ROXML\342\204\242”

know if a tag is empty or not

Let's say I have an XML snippet like this :

<article>
  <title>My Title</title>
  <author/>
</article>

and this mapping :

class Author
  include ROXML

  xml_reader :whatever
end

class Article
  include ROXML

  xml_reader :title
  xml_reader :author, :as => Author
end

Is it possible to know that the author is present without looking inside?
I wish I could something like this

article = Article.from_xml(xml)
puts article.author.whatever if article.author.present?

Thanks for this really great gem. I use it a lot, and am very happy with it.

lambda support for XML -> Ruby conversion

For reference, the Product class in my ONIX library: http://github.com/yob/onix/blob/master/lib/onix/product.rb, lines 31-37.

The ONIX spec requires all dates to be formatted as YYYYMMDD.

I handle the to_xml conversion from a Date class to a string by defining a lambda method and passing it to the attribute using the :to_xml option.

For marshalling xml strings into Date objects, I was using ":as => Date", but that would raise an exception when I tried to parse a file that containing invalid dates ( like "00000000"). To define my own XML->Ruby process, I have to pass a block into the attribute definition. This works, but has lead to some duplication.

It would be awesome if I could pass a lambda object into :as, just like I can with :to_xml.

Conditionally combining multiple attributes

Using ROXML with dm-core here. I am dealing with a poorly designed XML schema so I need to conditionally set a DM property from one of two xml attributes.

class Sample < Model
  include ROXML
  include DatamMapper::Resource

  xml_name "SAMPLE"
  xml_convention :upcase

  property :name, String
  xml_reader :name

  property :amount, String

  xml_reader :display_amount
  xml_reader :uncast_amount, :from => "AMOUNT"

  def amount
    display_amount || "#{uncast_amount} liters"
  end

end

I was trying to do this via DataMappers after :create hook but this does not get fired until I explicitly save the object. I know I can use a block to set a value but cannot get this to work. In my case AMOUNT is "always" present so I've tried something like:

xml_reader :display_amount
xml_reader(:amount) { |x| x = display_amount || x}

This obviously doesn't work as the block only receives the value returned from xml_reader.

Any suggestions?

Rails class reloading leads to attribute redefinition errors

Reported by gorism:

I feel bad for continuing to pester you with questions, but I ran into another issue. This time it has to do with the buildup of accessors for a given class (that happens to include ROXML). Here is the class in all it’s glory:

class BatchRequest include ROXML

xml_name ‘batch_request’ xml_reader :batch_identifier xml_reader :batch_file, :cdata => true

end

Note that this class is defined within a Controller class file, so it’s not in a stand-alone .rb file.

Now, if I start the Rails application and submit a request to the Controller (which ends up loading and initializing the BatchRequest class, obviously), it works the first time. The second time, I get the following error:

Accessor batch_identifier is already defined as XML accessor in class BatchRequest

If I restart Mongrel, it works again the first time, fails the next time. Obviously something is sticking around between invocations. Also note that I can execute an Rspec test built to test the Controller class, with multiple “examples” within a single Rspec file testing the controller. That works fine.

I’ve tried a number of things:
1. Rolled back to the 2.4.3 version of ROXML (I’m currently using 2.5.1)
2. Forced using of REXML, just in case libxml was doing something odd (I’m currently at libxml-ruby 1.1.1)
3. Tried a different version of libxml-ruby

I pursued all of these things, because I could have sworn I wasn’t getting this behavior before, but the code hasn’t changed.

Maybe I don’t understand something about Ruby classloading (or perhaps Mongrel classloading), but this behavior is confusing.

Ignoring attribute when converting object to xml

Hi,
I want to ignore attributes when converting the object to xml? Is there a way I can specify something in annotation so attribute is excluded at the time of xml conversion?

Thanks in advance

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.