https://github.com/savonrb/nori
XML to Hash translator
https://github.com/savonrb/nori
Keywords from Contributors
rubygems feature-flag activerecord activejob mvc rspec sidekiq crash-reporting soap-client gem
Last synced: about 10 hours ago
JSON representation
Repository metadata
XML to Hash translator
- Host: GitHub
- URL: https://github.com/savonrb/nori
- Owner: savonrb
- License: mit
- Created: 2011-02-27T14:40:01.000Z (over 15 years ago)
- Default Branch: main
- Last Pushed: 2026-09-22T06:53:14.000Z (3 days ago)
- Last Synced: 2026-09-23T23:55:46.376Z (1 day ago)
- Language: Ruby
- Homepage:
- Size: 339 KB
- Stars: 264
- Watchers: 6
- Forks: 74
- Open Issues: 15
- Releases: 5
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Contributing: CONTRIBUTING.md
- License: LICENSE
- Security: SECURITY.md
README.md
Nori
Really simple XML parsing ripped from Crack, which ripped it from Merb.
Nori supports pluggable parsers and ships with both REXML and Nokogiri implementations.
It defaults to Nokogiri since v2.0.0, but you can change it to use REXML via:
Nori.new(:parser => :rexml) # or :nokogiri
Make sure Nokogiri is in your LOAD_PATH when parsing XML, because Nori tries to load it when it's needed.
Examples
Nori.new.parse("<tag>This is the content</tag>")
# => {"tag"=>"This is the content"}
Nori.new.parse('<foo />')
#=> {"foo"=>nil}
Nori.new.parse('<foo bar />')
#=> {}
Nori.new.parse('<foo bar="baz"/>')
#=> {"foo"=>{"@bar"=>"baz"}}
Nori.new.parse('<foo bar="baz">Content</foo>')
#=> {"foo"=>"Content"}
Nori::StringWithAttributes
You can access a string node's attributes via attributes.
result = Nori.new.parse('<foo bar="baz">Content</foo>')
#=> {"foo"=>"Content"}
result["foo"].class
# => Nori::StringWithAttributes
result["foo"].attributes
# => {"bar"=>"baz"}
Because StringWithAttributes hides the attributes on an accessor, they are
lost on a plain to_json and callers have to type-check each value. The
serializable profile returns a plain Hash instead and will
probably be the default in 3.0.
advanced_typecasting
Nori can automatically convert string values to TrueClass, FalseClass, Time, Date, and DateTime:
# "true" and "false" String values are converted to `TrueClass` and `FalseClass`.
Nori.new.parse("<value>true</value>")
# => {"value"=>true}
# String values matching xs:time, xs:date and xs:dateTime are converted to `Time`, `Date` and `DateTime` objects.
Nori.new.parse("<value>09:33:55.7Z</value>")
# => {"value"=>2022-09-29 09:33:55.7 UTC
# disable with advanced_typecasting: false
Nori.new(advanced_typecasting: false).parse("<value>true</value>")
# => {"value"=>"true"}
strip_namespaces
Nori can strip the namespaces from your XML tags. This feature is disabled by default.
Nori.new.parse('<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"></soap:Envelope>')
# => {"soap:Envelope"=>{"@xmlns:soap"=>"http://schemas.xmlsoap.org/soap/envelope/"}}
Nori.new(:strip_namespaces => true).parse('<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"></soap:Envelope>')
# => {"Envelope"=>{"@xmlns:soap"=>"http://schemas.xmlsoap.org/soap/envelope/"}}
convert_tags_to
Nori lets you specify a custom formula to convert XML tags to Hash keys using convert_tags_to.
Nori.new.parse('<userResponse><accountStatus>active</accountStatus></userResponse>')
# => {"userResponse"=>{"accountStatus"=>"active"}}
parser = Nori.new(:convert_tags_to => lambda { |tag| Nori::StringUtils.snakecase(tag).to_sym })
parser.parse('<userResponse><accountStatus>active</accountStatus></userResponse>')
# => {:user_response=>{:account_status=>"active"}}
convert_dashes_to_underscores
By default, Nori will automatically convert dashes in tag names to underscores.
Nori.new.parse('<any-tag>foo bar</any-tag>')
# => {"any_tag"=>"foo bar"}
# disable with convert_dashes_to_underscores
parser = Nori.new(:convert_dashes_to_underscores => false)
parser.parse('<any-tag>foo bar</any-tag>')
# => {"any-tag"=>"foo bar"}
empty_tag_value
By default, an empty tag becomes nil. The empty_tag_value option replaces that value.
Nori.new.parse('<foo/>')
# => {"foo"=>nil}
Nori.new(:empty_tag_value => "").parse('<foo/>')
# => {"foo"=>""}
The option does not apply to empty tags with attributes.
They become a hash of their prefixed attributes instead.
Nori.new(:empty_tag_value => "").parse('<foo bar="baz"/>')
# => {"foo"=>{"@bar"=>"baz"}}
consistent_empty_tags
With consistent_empty_tags, every empty tag (with or without attributes) becomes the empty_tag_value.
Nori.new(:consistent_empty_tags => true).parse('<foo bar="baz"/>')
# => {"foo"=>nil}
A string empty_tag_value keeps the attributes accessible on the value,
and an explicit xsi:nil="true" always becomes nil.
parser = Nori.new(:consistent_empty_tags => true, :empty_tag_value => "")
result = parser.parse('<foo bar="baz"/>')
# => {"foo"=>""}
result["foo"].attributes
# => {"bar"=>"baz"}
parser.parse('<foo xsi:nil="true" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>')
# => {"foo"=>nil}
standards
standards is a profile that turns on Nori's spec-correct parsing as a group,
rather than one flag at a time. It is opt-in on the 2.x line and becomes the
default in Nori 3.0.
Nori.new(:standards => true)
Members of the profile:
-
xml:space honoring (XML 1.0 §2.10).
Whitespace-only text underxml:space="preserve"is kept instead of stripped.
The nearest ancestor that setsxml:spacewins, andxml:space="default"
resets to the stripping behavior.Nori.new(:standards => true).parse('<name xml:space="preserve"> </name>') # => {"name"=>" "} -
the XML string-value model for empty elements. The profile implies
consistent_empty_tags: truewithempty_tag_value: "". Both remain
overridable, so passing either option explicitly wins over the profile.Nori.new(:standards => true).parse('<foo bar="baz"/>') # => {"foo"=>""} -
no schema-less typing. Without a schema, character data is just text, so
the profile impliesadvanced_typecasting: false(overridable) and ignores
the baretype=andnil=attribute conventions that Nori inherited from
Rails'Hash.from_xml. Atype="integer"no longer casts, atype="array"
no longer folds children into an Array, and both stay visible as ordinary
attributes. Only the prefixedxsi:nil="true"still marks an element nil,
because that convention comes from XML Schema Instance itself.Nori.new(:standards => true).parse('<id type="integer">123</id>') # => {"id"=>"123"} (with "type" accessible via #attributes)
serializable
serializable is a profile that makes Nori return plain, directly-serializable
data with no custom value classes. It is opt-in on the 2.x line and will
probably become the default in 3.0.
Nori.new(:serializable => true)
Members of the profile:
-
text nodes with attributes become a Hash. A tag with both text content
and attributes maps to the XML JSON convention ({"#text" => content}merged
with the@-prefixed attributes) instead of aNori::StringWithAttributes.
This is the same@-keyed shape element nodes already use, so the attributes
surviveto_json,to_yaml, andMarshal. A text node without attributes
stays a plainString. Typecast values keep their attributes the same way
({"#text" => true, "@source" => "ldap"}) – attributes are never silently
dropped under the profile. The#textkey goes throughconvert_tags_to
like every other key, so a key-converting formula can reshape it (or drop
the#entirely).Nori.new(:serializable => true).parse('<foo bar="baz">Content</foo>') # => {"foo"=>{"#text"=>"Content", "@bar"=>"baz"}} Nori.new(:serializable => true).parse('<foo>Content</foo>') # => {"foo"=>"Content"} -
type="file"nodes are not decoded. Without the profile, a node carrying
type="file"is base64-decoded into aNori::StringIOFilewith its filename
and content type. The profile skips that. The node folds into text and
attributes like any other, leaving the base64 content as a plainStringfor
the caller to decode. Thistype=decoding is a Rails/ActiveSupport
Hash.from_xmlconvention Nori inherited through crack and merb, not part of
any XML specification, so the plain-data profile leaves it behind.Nori.new(:serializable => true).parse('<doc type="file" name="x.pdf">aGVsbG8=</doc>') # => {"doc"=>{"#text"=>"aGVsbG8=", "@type"=>"file", "@name"=>"x.pdf"}}
Owner metadata
- Name: savonrb
- Login: savonrb
- Email:
- Kind: organization
- Description:
- Website: https://www.savonrb.com/
- Location:
- Twitter: savonrb
- Company:
- Icon url: https://avatars.githubusercontent.com/u/2353495?v=4
- Repositories: 12
- Last ynced at: 2024-03-25T19:56:36.386Z
- Profile URL: https://github.com/savonrb
GitHub Events
Total
- Delete event: 2
- Pull request event: 1
- Fork event: 1
- Issues event: 2
- Watch event: 3
- Issue comment event: 3
- Push event: 6
- Create event: 5
Last Year
- Delete event: 2
- Issues event: 1
- Watch event: 1
- Issue comment event: 1
- Push event: 6
- Create event: 5
Committers metadata
Last synced: 2 days ago
Total Commits: 255
Total Committers: 38
Avg Commits per committer: 6.711
Development Distribution Score (DDS): 0.49
Commits in past year: 43
Committers in past year: 3
Avg Commits per committer in past year: 14.333
Development Distribution Score (DDS) in past year: 0.349
| Name | Commits | |
|---|---|---|
| rubiii | me@r****m | 130 |
| John Nunemaker | n****r@g****m | 30 |
| dependabot[bot] | 4****] | 14 |
| Tim Jarratt | t****t@g****m | 14 |
| Wynn Netherland | w****d@g****m | 11 |
| Peter Cai | 2****i | 9 |
| Olle Jonsson | o****n@g****m | 8 |
| weidenfreak | m****n@b****e | 4 |
| Korny Sietsma | k****y@s****m | 3 |
| robuye | r****k@g****m | 3 |
| Gene Drabkin | g****n@g****m | 2 |
| Tim Jarratt | p****t@g****m | 1 |
| Sergey Baev | s****v@a****u | 1 |
| Jussi Koljonen | j****n@m****m | 1 |
| Henry Hsu | h****u@z****m | 1 |
| Alethea Rose | a****a@a****m | 1 |
| Andrzej Kajetanowicz | a****z@g****m | 1 |
| Douglas Eichelberger | d****g | 1 |
| Felix Wang | m****x@g****m | 1 |
| sanemat | o****n@g****m | 1 |
| gaaady | g****y@g****m | 1 |
| edmz | e****z@g****m | 1 |
| deadprogrammer | r****s@g****m | 1 |
| barberj | b****n@g****m | 1 |
| Yuri Zubov | y****u@g****m | 1 |
| Tim Riley | t****m@o****m | 1 |
| Thomas Jachmann | s****f@t****m | 1 |
| Tamal White | t****e@a****m | 1 |
| Sandro Turriate | s****e@g****m | 1 |
| Michael Chu | 1****u | 1 |
| and 8 more... | ||
Committer domains:
- florian-duetsch.de: 1
- autonomousmachine.com: 1
- geekdaily.org: 1
- technicalpickles.com: 1
- dataart.com: 1
- lackac.hu: 1
- apple.com: 1
- thomasjachmann.com: 1
- openmonkey.com: 1
- alethearose.com: 1
- zendesk.com: 1
- maventa.com: 1
- at-consulting.ru: 1
- sietsma.com: 1
- blau.de: 1
- rubiii.com: 1
Issue and Pull Request metadata
Last synced: 1 day ago
Total issues: 55
Total pull requests: 70
Average time to close issues: over 1 year
Average time to close pull requests: 6 months
Total issue authors: 52
Total pull request authors: 42
Average comments per issue: 3.56
Average comments per pull request: 1.57
Merged pull request: 47
Bot issues: 0
Bot pull requests: 14
Past year issues: 0
Past year pull requests: 17
Past year average time to close issues: N/A
Past year average time to close pull requests: about 9 hours
Past year issue authors: 0
Past year pull request authors: 3
Past year average comments per issue: 0
Past year average comments per pull request: 0.88
Past year merged pull request: 16
Past year bot issues: 0
Past year bot pull requests: 14
Top Issue Authors
- pokonski (2)
- inossidabile (2)
- rubiii (2)
- arkes (1)
- ArnoldMEDLINQ (1)
- toobulkeh (1)
- barberj (1)
- mrnovalles (1)
- arjunmenon (1)
- jedbeard (1)
- munshkr (1)
- burlesona (1)
- james-em (1)
- pcai (1)
- sathish316 (1)
Top Pull Request Authors
- dependabot[bot] (14)
- olleolleolle (9)
- robuye (4)
- ekzobrain (2)
- Pepan (2)
- mchu (2)
- rubiii (2)
- thomasjachmann (1)
- anandagrawal84 (1)
- HarlemSquirrel (1)
- alethea (1)
- barberj (1)
- hsume2 (1)
- weidenfreak (1)
- yuri-zubov (1)
Top Issue Labels
- bug (4)
- support (4)
- improvement (2)
- release (1)
- feature (1)
- roadmap (1)
- Help wanted (1)
Top Pull Request Labels
- github_actions (14)
- dependencies (14)
- bug (1)
Package metadata
- Total packages: 15
-
Total downloads:
- rubygems: 266,186,496 total
- Total docker downloads: 1,175,885,386
- Total dependent packages: 173 (may contain duplicates)
- Total dependent repositories: 7,179 (may contain duplicates)
- Total versions: 107
- Total maintainers: 4
- Total advisories: 2
gem.coop: nori
XML to Hash translator
- Homepage: https://github.com/savonrb/nori
- Documentation: http://www.rubydoc.info/gems/nori/
- Licenses: MIT
- Latest release: 2.9.1 (published 3 months ago)
- Last Synced: 2026-09-23T16:04:50.674Z (1 day ago)
- Versions: 28
- Dependent Packages: 0
- Dependent Repositories: 0
- Downloads: 133,037,858 Total
- Docker Downloads: 587,942,693
-
Rankings:
- Dependent repos count: 0.0%
- Dependent packages count: 0.0%
- Average: 0.092%
- Docker downloads count: 0.157%
- Downloads: 0.211%
- Maintainers (4)
- Advisories:
pkgsrc-netbsd-x86_64-10.1-all: textproc/ruby-nori
XML to Hash translator
- Homepage: https://github.com/savonrb/nori
- Documentation: https://pkgsrc.se/textproc/ruby-nori
- Licenses: mit
- Latest release: 2.7.1 (published 6 months ago)
- Last Synced: 2026-05-27T10:25:17.903Z (4 months ago)
- Versions: 1
- Dependent Packages: 0
- Dependent Repositories: 0
-
Rankings:
- Dependent repos count: 0.0%
- Dependent packages count: 0.0%
- Average: 0.634%
- Forks count: 1.05%
- Stargazers count: 1.487%
rubygems.org: nori
XML to Hash translator
- Homepage: https://github.com/savonrb/nori
- Documentation: http://www.rubydoc.info/gems/nori/
- Licenses: MIT
- Latest release: 2.9.1 (published 3 months ago)
- Last Synced: 2026-09-24T16:25:41.915Z (about 10 hours ago)
- Versions: 28
- Dependent Packages: 173
- Dependent Repositories: 7,179
- Downloads: 133,148,638 Total
- Docker Downloads: 587,942,693
-
Rankings:
- Downloads: 0.189%
- Docker downloads count: 0.189%
- Dependent packages count: 0.205%
- Dependent repos count: 0.38%
- Average: 1.282%
- Forks count: 3.065%
- Stargazers count: 3.666%
- Maintainers (4)
- Advisories:
proxy.golang.org: github.com/savonrb/nori
- Homepage:
- Documentation: https://pkg.go.dev/github.com/savonrb/nori#section-documentation
- Licenses: mit
- Latest release: v2.9.1+incompatible (published 3 months ago)
- Last Synced: 2026-09-24T15:47:39.208Z (about 10 hours ago)
- Versions: 39
- Dependent Packages: 0
- Dependent Repositories: 0
-
Rankings:
- Dependent packages count: 4.783%
- Average: 4.944%
- Dependent repos count: 5.105%
ubuntu-20.04: ruby-nori
- Homepage: https://github.com/savonrb/nori
- Licenses: mit
- Latest release: 2.6.0-1 (published 7 months ago)
- Last Synced: 2026-03-13T20:22:16.832Z (7 months ago)
- Versions: 1
- Dependent Packages: 0
- Dependent Repositories: 0
-
Rankings:
- Dependent repos count: 0.0%
- Dependent packages count: 0.0%
- Average: 100%
ubuntu-22.04: ruby-nori
- Homepage: https://github.com/savonrb/nori
- Licenses: mit
- Latest release: 2.6.0-1.1 (published 7 months ago)
- Last Synced: 2026-09-22T22:28:42.186Z (2 days ago)
- Versions: 1
- Dependent Packages: 0
- Dependent Repositories: 0
-
Rankings:
- Dependent repos count: 0.0%
- Dependent packages count: 0.0%
- Average: 100%
debian-13: ruby-nori
- Homepage: https://github.com/savonrb/nori
- Documentation: https://packages.debian.org/trixie/ruby-nori
- Licenses: mit
- Latest release: 2.6.0-1.1 (published 7 months ago)
- Last Synced: 2026-03-14T18:10:00.746Z (6 months ago)
- Versions: 1
- Dependent Packages: 0
- Dependent Repositories: 0
-
Rankings:
- Dependent repos count: 0.0%
- Dependent packages count: 0.0%
- Average: 100%
ubuntu-24.04: ruby-nori
- Homepage: https://github.com/savonrb/nori
- Licenses: mit
- Latest release: 2.6.0-1.1 (published 8 months ago)
- Last Synced: 2026-03-06T16:50:04.311Z (7 months ago)
- Versions: 1
- Dependent Packages: 0
- Dependent Repositories: 0
-
Rankings:
- Dependent repos count: 0.0%
- Dependent packages count: 0.0%
- Average: 100%
ubuntu-23.04: ruby-nori
- Homepage: https://github.com/savonrb/nori
- Licenses: mit
- Latest release: 2.6.0-1.1 (published 8 months ago)
- Last Synced: 2026-03-11T15:29:38.266Z (7 months ago)
- Versions: 1
- Dependent Packages: 0
- Dependent Repositories: 0
-
Rankings:
- Dependent repos count: 0.0%
- Dependent packages count: 0.0%
- Average: 100%
guix: ruby-nori
XML to Hash translator
- Homepage: https://github.com/savonrb/nori
- Documentation: https://git.savannah.gnu.org/cgit/guix.git/tree/gnu/packages/ruby-xyz.scm#n15956
- Licenses: expat
- Latest release: 2.6.0 (published 7 months ago)
- Last Synced: 2026-08-22T04:27:39.831Z (about 1 month ago)
- Versions: 1
- Dependent Packages: 0
- Dependent Repositories: 0
-
Rankings:
- Dependent repos count: 0.0%
- Dependent packages count: 0.0%
- Average: 100%
debian-10: ruby-nori
- Homepage: https://github.com/savonrb/nori
- Documentation: https://packages.debian.org/buster/ruby-nori
- Licenses: mit
- Latest release: 2.6.0-1 (published 8 months ago)
- Last Synced: 2026-03-13T19:04:52.780Z (7 months ago)
- Versions: 1
- Dependent Packages: 0
- Dependent Repositories: 0
-
Rankings:
- Dependent repos count: 0.0%
- Dependent packages count: 0.0%
- Average: 100%
ubuntu-23.10: ruby-nori
- Homepage: https://github.com/savonrb/nori
- Licenses: mit
- Latest release: 2.6.0-1.1 (published 7 months ago)
- Last Synced: 2026-09-04T23:29:43.618Z (20 days ago)
- Versions: 1
- Dependent Packages: 0
- Dependent Repositories: 0
-
Rankings:
- Dependent repos count: 0.0%
- Dependent packages count: 0.0%
- Average: 100%
debian-11: ruby-nori
- Homepage: https://github.com/savonrb/nori
- Documentation: https://packages.debian.org/bullseye/ruby-nori
- Licenses: mit
- Latest release: 2.6.0-1.1 (published 8 months ago)
- Last Synced: 2026-07-25T15:02:39.541Z (2 months ago)
- Versions: 1
- Dependent Packages: 0
- Dependent Repositories: 0
-
Rankings:
- Dependent repos count: 0.0%
- Dependent packages count: 0.0%
- Average: 100%
ubuntu-24.10: ruby-nori
- Homepage: https://github.com/savonrb/nori
- Licenses: mit
- Latest release: 2.6.0-1.1 (published 7 months ago)
- Last Synced: 2026-03-13T12:15:49.167Z (7 months ago)
- Versions: 1
- Dependent Packages: 0
- Dependent Repositories: 0
-
Rankings:
- Dependent repos count: 0.0%
- Dependent packages count: 0.0%
- Average: 100%
debian-12: ruby-nori
- Homepage: https://github.com/savonrb/nori
- Documentation: https://packages.debian.org/bookworm/ruby-nori
- Licenses: mit
- Latest release: 2.6.0-1.1 (published 7 months ago)
- Last Synced: 2026-03-13T23:43:32.798Z (7 months ago)
- Versions: 1
- Dependent Packages: 0
- Dependent Repositories: 0
-
Rankings:
- Dependent repos count: 0.0%
- Dependent packages count: 0.0%
- Average: 100%
Dependencies
- rexml ~> 3.2
- nokogiri >= 1.4.0 development
- rake ~> 12.3.3 development
- rspec ~> 3.11.0 development
- actions/checkout 3d3c42e5aac5ba805825da76410c181273ba90b1 composite
- coverallsapp/github-action 8d6379e14d29928660c4ba802d8e85393440b329 composite
- ruby/setup-ruby 95ef2b042f9d7a56d8268cba8559e2842e2ad01b composite
- zizmorcore/zizmor-action 3dc1ecc9bcb9e94e9b2c709687979e1298497054 composite
- actions/checkout 3d3c42e5aac5ba805825da76410c181273ba90b1 composite
- ruby/setup-ruby 95ef2b042f9d7a56d8268cba8559e2842e2ad01b composite
- rubygems/release-gem 7f9650160c1a4e7989fdc9855807bdbd421d8b6b composite
Score: 30.35815025132667