Skip to content
/ fastxml Public

Fast Ruby Hash to XML and XML to Ruby Hash converter written in pure C

License

Notifications You must be signed in to change notification settings

yoreek/fastxml

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

10 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

FastXML

Fast Ruby Hash to XML and XML to Ruby Hash converter written in pure C.

Build Status

Installation

Add this line to your application's Gemfile:

gem 'fast-xml'

And then execute:

$ bundle

Or install it yourself as:

$ gem install fast-xml

Release Notes

See CHANGELOG.md

Usage

Convert hash toXML

require 'fastxml'

FastXML.hash2xml({ tag1: { tag2: 'content' } }, indent: 2)
# =>
# <?xml version="1.0" encoding="utf-8"?>
# <root>
#   <tag1>
#     <tag2>content</tag2>
#   </tag1>
# </root>

# use enumerator
FastXML.hash2xml({ enumerator: 3.times }, indent:  2)
# =>
# <?xml version="1.0" encoding="utf-8"?>
# <root>
#   <enumerator>0</enumerator>
#   <enumerator>1</enumerator>
#   <enumerator>2</enumerator>
# </root>

# output to file handle
# fh = StringIO.new
FastXML.hash2xml({ enumerator: 3.times }, indent:  2, output: fh)
fh.string
# =>
# <?xml version="1.0" encoding="utf-8"?>
# <root>
#   <enumerator>0</enumerator>
#   <enumerator>1</enumerator>
#   <enumerator>2</enumerator>
# </root>

Convert XML to hash

FastXML.xml2hash('<root><a>aaa</a><a>aaa2</a><b attr="bbb">bbb2</b></root>')
# => {"a"=>["aaa", "aaa2"], "b"=>{"attr"=>"bbb", "content"=>"bbb2"}}

# use filter
FastXML.xml2hash('<root><a>aaa</a><a>aaa2</a><b>bbb</b></root>', filter: '/root/a') do |node|
  p node
end
# =>
# {"a"=>"aaa"}
# {"a"=>"aaa2"}

Options

The following options are available to pass to FastXML.hash2xml(hash, options = {}).

  • :root => 'root' # hash2xml

    • Root node name.
  • :version => '1.0' # hash2xml

    • XML document version
  • :encoding => 'utf-8' # hash2xml + xml2hash

    • XML input/output encoding
  • :indent => 0 # hash2xml

    • if indent great than 0, XML output should be indented according to its hierarchic structure. This value determines the number of spaces.

    • if indent is 0, XML output will all be on one line.

  • :output => nil # hash2xml

    • XML output method

    • if output is nil, XML document dumped into string.

    • if output is filehandle, XML document writes directly to a filehandle or a stream.

  • :canonical => false # hash2xml

    • if canonical is true, the converter will be write hashes sorted by key.

    • if canonical is false, the order of the element will be pseudo-randomly.

  • :use_attr => false # hash2xml

    • if use_attr is true, the converter will be use the attributes.

    • if use_attr is fale, the converter will be use tags only.

  • :content => 'content' # hash2xml + xml2hash

    • The key name for the text content.
  • :force_array => nil # xml2hash

    • When this option is true, the converter will be to force nested elements to be represented as arrays even when there is only one.

      FastXML.xml2hash('<root><a>aaa</a></root>', force_array: true)

      will be converted to:

      { "a" => ["aaa"] }

      instead of:

      { "a" => "aaa" }

    • When this option is an array, this allows to specify a list of element names which should always be forced into an array representation, rather than the 'all or nothing' approach above.

      FastXML.xml2hash('<root><a>aaa</a><b>bbb</b></root>', force_array: ['a'])

      will be converted to:

      { "a" => ["aaa"], "b" => "bbb" }

      FastXML.xml2hash('<root><a>aaa</a><a2>aaa</a2><b>bbb</b></root>', force_array: [/^a/])

      will be converted to:

      { "a" => ["aaa"], "a2" => ["aaa"], "b" => "bbb" }

  • :force_content => false # xml2hash

    • When this options is true, this allows you to force text content to always convert to a hash value.

      FastXML.xml2hash('<root><a>value</a></root>', force_content: true)

      will be converted to:

      { "a" => { "content" => "value" } }

      instead of:

      { "a" => "value" }

  • :merge_text => false # xml2hash

    • Setting this option to true will cause merge adjacent text nodes.

      FastXML.xml2hash('<root>value1<!-- comment -->value2</root>', merge_text: true)

      will be converted to:

      "value1value2"

      instead of:

      ["value1", "value2"]

  • :xml_decl => true # hash2xml

    • if xml_decl is true, output will start with the XML declaration <?xml version="1.0" encoding="utf-8"?>

    • if xml_decl is false, XML declaration will not be output.

  • :trim => false # hash2xml + xml2hash

    • Trim leading and trailing whitespace from text nodes.
  • :utf8 => true # hash2xml + xml2hash

    • Turn on utf8 flag for strings if is true.
  • :max_depth => 1024 # xml2hash

    • Maximum recursion depth.
  • :buf_size => 4096 # hash2xml + xml2hash

    • Buffer size for reading end encoding data.
  • :keep_root => false # xml2hash

    • Keep root element.

      FastXML.xml2hash('<root>value1</root>', keep_root: true)

      will be converted to:

      { "root" => "value1" }

      instead of:

      "value1"

  • :filter => nil # xml2hash

    • Filter nodes matched by pattern and return an array of nodes.

      FastXML.xml2hash('<root><a>aaa</a><a>aaa2</a><b>bbb</b></root>', filter: '/root/a')

      will be converted to:

      [{ "a" => "aaa" }, { "a" => "aaa2" }]

      FastXML.xml2hash('<root><a>aaa</a><a>aaa2</a><b>bbb</b></root>', filter: /a|b/)

      will be converted to:

      [{ "a" => "aaa" }, { "a" => "aaa2" }, { "b" => "bbb" }]

      FastXML.xml2hash('<root><a>aaa</a><a>aaa2</a><b>bbb</b></root>', filter: ['/root/a', '/root/b'])

      will be converted to:

      [{ "a" => "aaa" }, { "a" => "aaa2" }, { "b" => "bbb" }]

    • You can pass a block as parameter.

      FastXML.xml2hash('<root><a>aaa</a><a>aaa2</a><b>bbb</b></root>', filter: '/root/a') do |node|
        p node
      end
      

      will be printed:

      {"a"=>"aaa"}
      {"a"=>"aaa2"}
      

      It may be used to parse large XML because does not require a lot of memory.

Configuration

  FastXML.configure do |config|
    config.trim = true
  end

Benchmarks

Performance benchmark in comparison with some popular gems:

Converting Hash to XML:
                           user     system      total        real
activesupport(rexml)    10.920000   0.010000  10.930000 ( 10.948205)
activesupport(libxml)   10.880000   0.000000  10.880000 ( 10.910649)
activesupport(nokogiri) 10.880000   0.000000  10.880000 ( 10.899013)
xmlsimple                1.490000   0.000000   1.490000 (  1.504655)
fastxml                  0.020000   0.000000   0.020000 (  0.018095)
Converting XML to Hash:
                 user     system      total        real
activesupport(rexml)     8.420000   0.000000   8.420000 (  8.441763)
activesupport(libxml)    1.110000   0.010000   1.120000 (  1.109242)
activesupport(nokogiri)  1.660000   0.000000   1.660000 (  1.666208)
xmlsimple                8.390000   0.010000   8.400000 (  8.427240)
nori                     2.010000   0.000000   2.010000 (  2.016399)
xmlhasher                0.440000   0.000000   0.440000 (  0.433211)
fastxml                  0.070000   0.000000   0.070000 (  0.073124)

License

The gem is available as open source under the terms of the MIT License.

About

Fast Ruby Hash to XML and XML to Ruby Hash converter written in pure C

Resources

License

Stars

Watchers

Forks

Packages

No packages published