FormatterHQ

XML to Ruby Class Generator

Generate typed Ruby models from XML with dry-struct: attributes and child elements become struct attributes, repeated elements become arrays.

Input XML
Output RUBY
Ready.

How to use the XML to Ruby

  1. Paste your XML document into the Input editor, or use Sample, Upload file or Load URL, or press Sample to see an example.
  2. Leave Top-level class name empty to name the root type after the root element, or type your own name.
  3. Leave Types only (no helpers) off for from_dynamic! helpers that build the structs from a hash; tick it for the definitions only.
  4. Press Generate (it also updates as you edit), then use Copy or Download.

XML to Ruby: typed models with dry-struct

Ruby makes it easy to parse XML, with Nokogiri or the bundled REXML, but the result is either a node tree or an untyped hash. This XML to Ruby generator writes Dry::Struct classes from a sample document, so your application works with typed, validated objects. Attributes and child elements both become struct attributes, and repeated elements become Types.Array attributes.

Example: gem metadata

<gem name="rails" version="7.2.0">
  <dependency name="activesupport" requirement="= 7.2.0"/>
  <dependency name="actionpack" requirement="= 7.2.0"/>
  <licenses><license>MIT</license></licenses>
</gem>
class Dependency < Dry::Struct
  attribute :dependency_name, Types::String
  attribute :requirement,     Types::String
end

class Licenses < Dry::Struct
  attribute :license, Types::String
end

class Gem < Dry::Struct
  attribute :dependency, Types.Array(Dependency)
  attribute :licenses,   Licenses
  attribute :gem_name,   Types::String
  attribute :version,    Types::String
end

The name attributes were renamed dependency_name and gem_name to avoid clashing with methods that already exist on the struct classes. Also note the version 7.2.0 stays a string, while <licenses> with a single <license> became an object rather than an array. Add a second license to the sample if a gem can have several.

Getting the XML into the structs

The generated from_dynamic! methods expect a hash with attributes as plain keys. Rails' ActiveSupport produces a close match:

hash = Hash.from_xml(xml_text)["gem"]      # attributes become keys
gem = Gem.from_dynamic!(hash)
puts gem.dependency.map(&:requirement)

Hash.from_xml merges attributes and child elements into one hash and turns repeated elements into arrays, much like this tool's mapping. With Nokogiri, build the hash yourself: node["name"] reads an attribute and node.at("license").text reads child text. Remember that all XML values are strings; strict dry-types reject a string where an integer is expected, so convert values or use Types::Coercible variants.

Nokogiri or REXML?

REXML is pure Ruby and became a bundled gem in Ruby 3.0, so it may need a Gemfile entry on newer Rubies; it is fine for small documents. Nokogiri wraps libxml2, is much faster, and supports XPath and CSS selectors, which makes it the usual choice for large files or scraping.

Notes

  • Namespace prefixes are removed from attribute names.
  • Add dry-struct and dry-types to your Gemfile.
  • For untrusted XML, Nokogiri's default parse options do not load external entities, which is the safe choice.

Format the output with the Ruby Formatter. For JSON data, use JSON to Ruby. Check the XML with the XML Formatter. Generation runs in your browser.

Frequently asked questions

Why was name renamed to gem_name?
name would clash with a method Dry::Struct classes already have, so the attribute is prefixed with the class name. The helpers still read the original name key.
Can I use Hash.from_xml with the generated structs?
Yes, it produces a similar shape: attributes and child elements as keys and repeated elements as arrays. Pass the hash for the root element to from_dynamic!.
Why does my integer attribute fail validation?
XML values are strings, and strict types do not coerce. Convert values before building the struct or switch to coercible types.
Why is licenses not an array?
The sample contained only one license element. Include two so the generator sees that it repeats.
Can I use the models without Rails?
Yes. dry-struct and dry-types do not depend on Rails. If you want Hash.from_xml without the rest of the framework, add the activesupport gem and require "active_support/core_ext/hash/conversions". Otherwise build the hash with Nokogiri yourself.
How do I handle elements that are sometimes missing?
In dry-struct, declare the attribute with attribute? so the key may be absent, and use an optional type such as Types::String.optional when the value may be nil. The generator only knows your sample, so adjust these by hand for fields that real documents omit.

Last updated September 26, 2026

Related tools

JSON to Ruby Generate Ruby Dry::Struct classes from a JSON sample instantly, with nested types detected automatically. XML to Rust Generate Rust structs with Serde derives from a XML sample instantly, with nested types detected automatically. XML to Scala Generate Scala case classes from a XML sample instantly, with nested types detected automatically. XML to Swift Generate Swift Codable structs from a XML sample instantly, with nested types detected automatically. XML to TypeScript Generate TypeScript interfaces from a XML sample instantly, with nested types detected automatically. GraphQL to TypeScript Generate TypeScript interfaces, enums and union types from a GraphQL schema (SDL), with nullability and argument types. JSON Schema to TypeScript Turn JSON Schema into TypeScript interfaces and types with optional properties, enums, $ref definitions and JSDoc comments. JSON to C++ Generate C++ classes with nlohmann::json helpers from a JSON sample instantly, with nested types detected automatically. JSON to Crystal Generate Crystal classes with JSON mapping from a JSON sample instantly, with nested types detected automatically. JSON to C# Generate C# classes with JsonProperty attributes from a JSON sample instantly, with nested types detected automatically. JSON to Dart Generate Dart classes with fromJson and toJson from a JSON sample instantly, with nested types detected automatically. JSON to Elm Generate Elm type aliases with decoders from a JSON sample instantly, with nested types detected automatically.