{"id":13484113,"url":"https://github.com/mvz/happymapper","last_synced_at":"2025-10-07T06:30:38.436Z","repository":{"id":648275,"uuid":"290589","full_name":"mvz/happymapper","owner":"mvz","description":"Object to XML mapping library, using Nokogiri (Fork from John Nunemaker's Happymapper)","archived":false,"fork":true,"pushed_at":"2025-01-02T19:30:36.000Z","size":904,"stargazers_count":152,"open_issues_count":24,"forks_count":44,"subscribers_count":11,"default_branch":"master","last_synced_at":"2025-01-19T02:53:04.031Z","etag":null,"topics":["hacktoberfest","ruby"],"latest_commit_sha":null,"homepage":"http://github.com/mvz/happymapper/","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"jnunemaker/happymapper","license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mvz.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"License","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2009-08-28T04:49:45.000Z","updated_at":"2025-01-02T19:30:38.000Z","dependencies_parsed_at":"2023-07-05T21:32:37.765Z","dependency_job_id":null,"html_url":"https://github.com/mvz/happymapper","commit_stats":{"total_commits":592,"total_committers":42,"mean_commits":"14.095238095238095","dds":0.5945945945945945,"last_synced_commit":"a650cecc262c0afcd8012cd5da1665e076abd4da"},"previous_names":["dam5s/happymapper"],"tags_count":9,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mvz%2Fhappymapper","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mvz%2Fhappymapper/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mvz%2Fhappymapper/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mvz%2Fhappymapper/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mvz","download_url":"https://codeload.github.com/mvz/happymapper/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":235599596,"owners_count":19016190,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["hacktoberfest","ruby"],"created_at":"2024-07-31T17:01:19.562Z","updated_at":"2025-10-07T06:30:33.063Z","avatar_url":"https://github.com/mvz.png","language":"Ruby","readme":"# HappyMapper\n\nHappymapper allows you to parse XML data and convert it quickly and easily into\nruby data structures.\n\nThis project is a fork of the great work done first by\n[jnunemaker](https://github.com/jnunemaker/happymapper).\n\n[![Gem Version](https://badge.fury.io/rb/nokogiri-happymapper.svg)](https://badge.fury.io/rb/nokogiri-happymapper)\n[![Maintainability](https://api.codeclimate.com/v1/badges/491015f82bd2a45fd9d3/maintainability)](https://codeclimate.com/github/mvz/happymapper/maintainability)\n\n## Major Differences\n\n  * [Nokogiri](http://nokogiri.org/) support\n  * Text nodes parsing\n  * Raw XML content parsing\n  * `#to_xml` support utilizing the same HappyMapper tags\n  * Numerous fixes for namespaces when using composition of classes\n  * Fixes for instances of XML where a namespace is defined but no elements\n    with that namespace are found\n\n## Installation\n\nInstall via rubygems:\n\n    $ gem install nokogiri-happymapper\n\nOr add the `nokogiri-happymapper` gem to your project's `Gemfile`.\n\n    gem 'nokogiri-happymapper', require: 'happymapper'\n\nYou can now also require `nokogiri-happymapper` directly.\n\n    gem 'nokogiri-happymapper'\n\nRun Bundler to install the gem:\n\n    $ bundle install\n\n## Examples\n\nLet's start with a simple example to get our feet wet. Here we have a simple\nexample of XML that defines some address information:\n\n```xml\n\u003caddress\u003e\n  \u003cstreet\u003eMilchstrasse\u003c/street\u003e\n  \u003chousenumber\u003e23\u003c/housenumber\u003e\n  \u003cpostcode\u003e26131\u003c/postcode\u003e\n  \u003ccity\u003eOldenburg\u003c/city\u003e\n  \u003ccountry code=\"de\"\u003eGermany\u003c/country\u003e\n\u003c/address\u003e\n```\n\nHappymapper provides support for simple, zero configuration parsing as well as\nthe ability to model the XML content in classes.\n\n### HappyMapper.parse(XML)\n\nWith no classes or configuration you can parse the example XML with little\neffort:\n\n```ruby\naddress = HappyMapper.parse(ADDRESS_XML_DATA)\naddress.street # =\u003e Milchstrasse\naddress.housenumber # =\u003e 23\naddress.postcode # =\u003e 26131\naddress.city # =\u003e Oldenburg\naddress.country.code # =\u003e de\naddress.country.content # =\u003e Germany\n```\n\nIt is important to be aware that this no configuration parsing is limited in capacity:\n\n* All element names are converted to accessor methods with\n  [underscorized](http://rubydoc.info/gems/activesupport/ActiveSupport/Inflector:underscore)\n  names\n* All value fields are left as String types\n* Determining if there is just one or multiple child elements is hard, so it\n  assumes it is one until it finds another with the same name.\n\n### Address.parse(XML)\n\nHappymapper will let you easily model this information as a class:\n\n```ruby\nrequire 'happymapper'\n\nclass Address\n  include HappyMapper\n\n  tag 'address'\n  element :street, String, tag: 'street'\n  element :postcode, String, tag: 'postcode'\n  element :housenumber, Integer, tag: 'housenumber'\n  element :city, String, tag: 'city'\n  element :country, String, tag: 'country'\nend\n```\n\nTo make a class HappyMapper compatible you simply `include HappyMapper` within\nthe class definition. This takes care of all the work of defining all the\nspeciality methods and magic you need to get running. As you can see we\nimmediately start using these methods.\n\n* `tag` matches the name of the XML tag name 'address'.\n\n* `element` defines accessor methods for the specified symbol\n  (e.g. `:street`,`:housenumber`) that will return the class type\n  (e.g. `String`,`Integer`) of the XML tag specified\n  (e.g. `tag: 'street'`, `tag: 'housenumber'`).\n\nWhen you define an element with an accessor with the same name as the tag, this\nis the case for all the examples above, you can omit the `:tag`. These two\nelement declaration are equivalent to each other:\n\n```ruby\nelement :street, String, tag: 'street'\nelement :street, String\n```\n\nIncluding the additional tag element is not going to hurt anything and in some\ncases will make it absolutely clear how these elements map to the XML. However,\nonce you know this rule, it is hard not to want to save yourself the\nkeystrokes.\n\nInstead of `element` you may also use `has_one`:\n\n```ruby\nelement :street, String, tag: 'street'\nelement :street, String\nhas_one :street, String\n```\n\nThese three statements are equivalent to each other.\n\n### Parsing\n\nWith the mapping of the address XML articulated in our Address class it is time\nto parse the data:\n\n```ruby\naddress = Address.parse(ADDRESS_XML_DATA, single: true)\nputs address.street\n```\n\nAssuming that the constant `ADDRESS_XML_DATA` contains a string representation\nof the address XML data this is fairly straight-forward save for the `parse`\nmethod.\n\nThe `parse` method, like `tag` and `element` are all added when you included\nHappyMapper in the class. Parse is a wonderful, magical place that converts all\nthese declarations that you have made into the data structure you are about to\nknow and love.\n\nBut what about the `single: true`? Right, that is because by default when\nyour object is all done parsing it will be an array. In this case an array with\none element, but an array none the less. So the following are equivalent to\neach other:\n\n```ruby\naddress = Address.parse(ADDRESS_XML_DATA).first\naddress = Address.parse(ADDRESS_XML_DATA, single: true)\n```\n\nThe first one returns an array and we return the first instance, the second\nwill do that work for us inside of parse.\n\n### Multiple Elements Mapping\n\nWhat if our address XML was a little different, perhaps we allowed multiple\nstreets:\n\n```xml\n\u003caddress\u003e\n  \u003cstreet\u003eMilchstrasse\u003c/street\u003e\n  \u003cstreet\u003eAnother Street\u003c/street\u003e\n  \u003chousenumber\u003e23\u003c/housenumber\u003e\n  \u003cpostcode\u003e26131\u003c/postcode\u003e\n  \u003ccity\u003eOldenburg\u003c/city\u003e\n  \u003ccountry code=\"de\"\u003eGermany\u003c/country\u003e\n\u003c/address\u003e\n```\n\nSimilar to `element` or `has_one`, the declaration for when you have multiple\nelements you simply use:\n\n```ruby\nhas_many :streets, String, tag: 'street'\n```\n\nYour resulting `streets` method will now return an array.\n\n```ruby\naddress = Address.parse(ADDRESS_XML_DATA, single: true)\nputs address.streets.join('\\n')\n```\n\nImagine that you have to write `streets.join('\\n')` for the rest of eternity\nthroughout your code. It would be a nightmare and one that you could avoid by\ncreating your own convenience method.\n\n```ruby\nrequire 'happymapper'\n\nclass Address\n  include HappyMapper\n\n  tag 'address'\n\n  has_many :streets, String\n\n  def streets\n    @streets.join('\\n')\n  end\n\n  element :postcode, String, tag: 'postcode'\n  element :housenumber, String, tag: 'housenumber'\n  element :city, String, tag: 'city'\n  element :country, String, tag: 'country'\nend\n```\n\nNow when we call the method `streets` we get a single value, but we still have\nthe instance variable `@streets` if we ever need to the values as an array.\n\n\n### Attribute Mapping\n\n```xml\n\u003caddress location='home'\u003e\n  \u003cstreet\u003eMilchstrasse\u003c/street\u003e\n  \u003cstreet\u003eAnother Street\u003c/street\u003e\n  \u003chousenumber\u003e23\u003c/housenumber\u003e\n  \u003cpostcode\u003e26131\u003c/postcode\u003e\n  \u003ccity\u003eOldenburg\u003c/city\u003e\n  \u003ccountry code=\"de\"\u003eGermany\u003c/country\u003e\n\u003c/address\u003e\n```\n\nAttributes are absolutely the same as `element` or `has_many`\n\n```ruby\nattribute :location, String, tag: 'location'\n```\n\nAgain, you can omit the tag if the attribute accessor symbol matches the name\nof the attribute.\n\n#### Attributes On Empty Child Elements\n\n```xml\n\u003cfeed xml:lang=\"en-US\" xmlns=\"http://www.w3.org/2005/Atom\"\u003e\n  \u003cid\u003etag:all-the-episodes.heroku.com,2005:/tv_shows\u003c/id\u003e\n  \u003clink rel=\"alternate\" type=\"text/html\" href=\"http://all-the-episodes.heroku.com\"/\u003e\n  \u003clink rel=\"self\" type=\"application/atom+xml\"\n        href=\"http://all-the-episodes.heroku.com/tv_shows.atom\"/\u003e\n  \u003ctitle\u003eTV Shows\u003c/title\u003e\n  \u003cupdated\u003e2011-07-10T06:52:27Z\u003c/updated\u003e\n\u003c/feed\u003e\n```\n\nIn this case you would need to map an element to a new `Link` class just to\naccess `\u003clink\u003e`s attributes, except that there is an alternate syntax. Instead\nof\n\n```ruby\nclass Feed\n  # ....\n  has_many :links, Link, tag: 'link', xpath: '.'\nend\n\nclass Link\n  include HappyMapper\n\n  attribute :rel, String\n  attribute :type, String\n  attribute :href, String\nend\n```\n\nYou can drop the `Link` class and simply replace the `has_many` on `Feed` with\n\n```ruby\nelement :link, String, single: false, attributes: { rel: String, type: String, href: String }\n```\n\nAs there is no content, the type given for `:link` (`String` above) is\nirrelevant, but `nil` won't work and other types may try to perform typecasting\nand fail. You can omit the single: false for elements that only occur once\nwithin their parent.\n\nThis syntax is most appropriate for elements that (a) have attributes but no\ncontent and (b) only occur at only one level of the heirarchy. If `\u003cfeed\u003e`\ncontained another element that also contained a `\u003clink\u003e` (as atom feeds\ngenerally do) it would be DRY-er to use the first syntax, i.e. with a separate\n`Link` class.\n\n\n### Class composition (and Text Node)\n\nOur address has a country and that country element has a code. Up until this\npoint we neglected it as we declared a `country` as being a `String`.\n\n    \u003caddress location='home'\u003e\n      \u003cstreet\u003eMilchstrasse\u003c/street\u003e\n      \u003cstreet\u003eAnother Street\u003c/street\u003e\n      \u003chousenumber\u003e23\u003c/housenumber\u003e\n      \u003cpostcode\u003e26131\u003c/postcode\u003e\n      \u003ccity\u003eOldenburg\u003c/city\u003e\n      \u003ccountry code=\"de\"\u003eGermany\u003c/country\u003e\n    \u003c/address\u003e\n\nWell if we only going to parse country, on it's own, we would likely create a\nclass mapping for it.\n\n```ruby\nclass Country\n  include HappyMapper\n\n  tag 'country'\n\n  attribute :code, String\n  content :name, String\nend\n```\n\nWe are utilizing an `attribute` declaration and a new declaration called `content`.\n\n* `content` is used when you want the text contained within the element\n\nAwesome, now if we were to redeclare our `Address` class we would use our new\n`Country` class.\n\n```ruby\nclass Address\n  include HappyMapper\n\n  tag 'address'\n\n  has_many :streets, String, tag: 'street'\n\n  def streets\n    @streets.join('\\n')\n  end\n\n  element :postcode, String, tag: 'postcode'\n  element :housenumber, String, tag: 'housenumber'\n  element :city, String, tag: 'city'\n  element :country, Country, tag: 'country'\nend\n```\n\nInstead of `String`, `Boolean`, or `Integer` we say that it is a `Country` and\nHappyMapper takes care of the details of continuing the XML mapping through the\ncountry element.\n\n```ruby\naddress = Address.parse(ADDRESS_XML_DATA, single: true)\nputs address.country.code\n```\n\nA quick note, in the above example we used the constant `Country`. We could\nhave used `'Country'`. The nice part of using the latter declaration, enclosed\nin quotes, is that you do not have to define your class before this class. So\nCountry and Address can live in separate files and as long as both constants\nare available when it comes time to parse you are golden.\n\n### Custom XPATH\n\n#### Has One, Has Many\n\nGetting to elements deep down within your XML can be a little more work if you\ndid not have xpath support. Consider the following example:\n\n```xml\n\u003cmedia\u003e\n  \u003cgallery\u003e\n    \u003ctitle href=\"htttp://fishlovers.org/friends\"\u003eFriends Who Like Fish\u003c/title\u003e\n    \u003cpicture\u003e\n      \u003cname\u003eBurtie Sanchez\u003c/name\u003e\n      \u003cimg\u003eburtie01.png\u003c/img\u003e\n    \u003c/picture\u003e\n  \u003c/gallery\u003e\n  \u003cpicture\u003e\n    \u003cname\u003eUnsorted Photo\u003c/name\u003e\n    \u003cimg\u003ebestfriends.png\u003c/img\u003e\n  \u003c/picture\u003e\n\u003c/media\u003e\n```\n\nYou may want to map the sub-elements contained buried in the 'gallery' as top\nlevel items in the media. Traditionally you could use class composition to\naccomplish this task, however, using the xpath attribute you have the ability\nto shortcut some of that work.\n\n```ruby\nclass Media\n  include HappyMapper\n\n  has_one :title, String, xpath: 'gallery/title'\n  has_one :link, String, xpath: 'gallery/title/@href'\nend\n```\n\n### Shared Functionality\n\n#### Inheritance Approach\n\nWhile mapping XML to objects you may arrive at a point where you have two or\nmore very similar structures.\n\n```ruby\nclass Article\n  include HappyMapper\n\n  has_one :title, String\n  has_one :author, String\n  has_one :published, Time\n\n  has_one :entry, String\n\nend\n\nclass Gallery\n  include HappyMapper\n\n  has_one :title, String\n  has_one :author, String\n  has_one :published, Time\n\n  has_many :photos, String\n\nend\n```\n\nIn this example there are definitely two similarities between our two pieces of\ncontent. So much so that you might be included to create an inheritance\nstructure to save yourself some keystrokes.\n\n```ruby\nclass Content\n  include HappyMapper\n\n  has_one :title, String\n  has_one :author, String\n  has_one :published, Time\nend\n\nclass Article \u003c Content\n  include HappyMapper\n\n  has_one :entry, String\nend\n\nclass Gallery \u003c Content\n  include HappyMapper\n\n  has_many :photos, String\nend\n```\n\n#### Module Mixins Approach\n\nYou can also solve the above problem through mixins.\n\n```ruby\nmodule Content\n  def self.included(content)\n    content.has_one :title, String\n    content.has_one :author, String\n    content.has_one :published, Time\n  end\n\n  def published_time\n    @published.strftime(\"%H:%M:%S\")\n  end\nend\n\nclass Article\n  include HappyMapper\n\n  include Content\n  has_one :entry, String\nend\n\nclass Gallery\n  include HappyMapper\n\n  include Content\n  has_many :photos, String\nend\n```\n\nHere, when we include `Content` in both of these classes the module method\n`#included` is called and our class is given as a parameter. So we take that\nopportunity to do some surgery and define our happymapper elements as well as\nany other methods that may rely on those instance variables that come along in\nthe package.\n\n### Filtering with XPATH (non-greedy)\n\nI ran into a case where I wanted to capture all the pictures that were directly\nunder media, but not the ones contained within a gallery.\n\n```xml\n\u003cmedia\u003e\n  \u003cgallery\u003e\n    \u003cpicture\u003e\n      \u003cname\u003eBurtie Sanchez\u003c/name\u003e\n      \u003cimg\u003eburtie01.png\u003c/img\u003e\n    \u003c/picture\u003e\n  \u003c/gallery\u003e\n  \u003cpicture\u003e\n    \u003cname\u003eUnsorted Photo\u003c/name\u003e\n    \u003cimg\u003ebestfriends.png\u003c/img\u003e\n  \u003c/picture\u003e\n\u003c/media\u003e\n```\n\nThe following `Media` class is where I started:\n\n```ruby\nrequire 'happymapper'\n\nclass Media\n  include HappyMapper\n\n  has_many :galleries, Gallery, tag: 'gallery'\n  has_many :pictures, Picture, tag: 'picture'\nend\n```\n\nHowever when I parsed the media xml the number of pictures returned to me was 2, not 1.\n\n```ruby\npictures = Media.parse(MEDIA_XML,single: true).pictures\npictures.length.should == 1   # =\u003e Failed Expectation\n```\n\nThe reason that 2 elements are returned and not 1 is because the default\nmappings are assigned XPATH './/' which makes them greedy. Essentially by\ndefault it will find all elements with the tag 'pictures' at the current\nlevel of the document and anywhere else within the document.\n\nTo limit an element from being greedy and only finding elements at the\nlevel of the current node you can specify an XPATH.\n\n```ruby\nhas_many :pictures, Picture, tag: 'picture', xpath: '.'\n```\n\n`.` states that we are only interested in pictures that can be found directly\nunder the current node. So when we parse again we will have only our one element.\n\n### Namespaces\n\nObviously your XML and these trivial examples are easy to map and parse because\nthey lack the treacherous namespaces that befall most XML files.\n\nPerhaps our `address` XML is really swarming with namespaces:\n\n    \u003cprefix:address location='home' xmlns:prefix=\"http://www.unicornland.com/prefix\"\u003e\n      \u003cprefix:street\u003eMilchstrasse\u003c/prefix:street\u003e\n      \u003cprefix:street\u003eAnother Street\u003c/prefix:street\u003e\n      \u003cprefix:housenumber\u003e23\u003c/prefix:housenumber\u003e\n      \u003cprefix:postcode\u003e26131\u003c/prefix:postcode\u003e\n      \u003cprefix:city\u003eOldenburg\u003c/prefix:city\u003e\n      \u003cprefix:country code=\"de\"\u003eGermany\u003c/prefix:country\u003e\n    \u003c/prefix:address\u003e\n\nHere again is our address example with a made up namespace called `prefix` that\ncomes direct to use from unicornland, a very magical place indeed. Well we are\ngoing to have to do some work on our class definition and that simply adding\nthis one liner to the `Address` class:\n\n```ruby\nclass Address\n  include HappyMapper\n\n  tag 'address'\n  namespace 'prefix'\n  # ... rest of the code ...\nend\n```\n\nOf course, if that is too easy for you, you can append a `namespace: 'prefix`\nto every one of the elements that you defined.\n\n```ruby\nhas_many :street, String, tag: 'street', namespace: 'prefix'\nelement :postcode, String, tag: 'postcode', namespace: 'prefix'\nelement :housenumber, String, tag: 'housenumber', namespace: 'prefix'\nelement :city, String, tag: 'city', namespace: 'prefix'\nelement :country, Country, tag: 'country', namespace: 'prefix'\n```\n\nI definitely recommend the former, as it saves you a whole hell of lot of\ntyping. However, there are times when appending a namespace to an element\ndeclaration is important and that is when it has a different namespace than\n`namespace 'prefix'`.\n\nImagine that our `country` actually belonged to a completely different namespace.\n\n```xml\n\u003cprefix:address location='home'\n                xmlns:prefix=\"http://www.unicornland.com/prefix\"\n                xmlns:different=\"http://www.trollcountry.com/different\"\u003e\n  \u003cprefix:street\u003eMilchstrasse\u003c/prefix:street\u003e\n  \u003cprefix:street\u003eAnother Street\u003c/prefix:street\u003e\n  \u003cprefix:housenumber\u003e23\u003c/prefix:housenumber\u003e\n  \u003cprefix:postcode\u003e26131\u003c/prefix:postcode\u003e\n  \u003cprefix:city\u003eOldenburg\u003c/prefix:city\u003e\n  \u003cdifferent:country code=\"de\"\u003eGermany\u003c/different:country\u003e\n\u003c/prefix:address\u003e\n```\n\nWell we would need to specify that namespace:\n\n```ruby\nelement :country, Country, tag: 'country', namespace: 'different'\n```\n\nWith that we should be able to parse as we once did.\n\n### Large Datasets (`:in_groups_of`)\n\nWhen dealing with large sets of XML that simply cannot or should not be placed\ninto memory the objects can be handled in groups through the `:in_groups_of`\nparameter.\n\n```ruby\nAddress.parse(LARGE_ADDRESS_XML_DATA,in_groups_of: 5) do |group|\n  puts address.streets\nend\n```\n\nThis trivial block will parse the large set of XML data and in groups of 5\naddresses at a time display the streets.\n\n### Saving to XML\n\nSaving a class to XML is as easy as calling `#to_xml`.  The end result will be\nthe current state of your object represented as xml. Let's cover some details\nthat are sometimes necessary and features present to make your life easier.\n\n\n#### :on_save\n\nWhen you are saving data to xml it is often important to change or manipulate\ndata to a particular format. For example, a time object:\n\n```ruby\nhas_one :published_time, Time, on_save: lambda {|time| time.strftime(\"%H:%M:%S\") if time }\n```\n\nHere we add the options `:on_save` and specify a lambda which will be executed\non the method call to `:published_time`.\n\n#### :state_when_nil\n\nWhen an element contains a nil value, or perhaps the result of the :on_save\nlambda correctly results in a nil value you will be happy that the element will\nnot appear in the resulting XML. However, there are time when you will want to\nsee that element and that's when `:state_when_nil` is there for you.\n\n```ruby\nhas_one :favorite_color, String, state_when_nil: true\n```\n\nThe resulting XML will include the 'favorite_color' element even if the\nfavorite color has not been specified.\n\n#### :read_only\n\nWhen an element, attribute, or text node is a value that you have no interest in\nsaving to XML, you can ensure that takes place by stating that it is `read only`.\n\n```ruby\nhas_one :modified, Boolean, read_only: true\nattribute :temporary, Boolean, read_only: true\n```\n\nThis is useful if perhaps the incoming XML is different than the out-going XML.\n\n#### namespaces\n\nParsing the XML to objects only required you to simply specify the prefix of\nthe namespace you wanted to parse, when you persist to xml you will need to\ndefine your namespaces so that they are correctly captured.\n\n```ruby\nclass Address\n  include HappyMapper\n\n  register_namespace 'prefix', 'http://www.unicornland.com/prefix'\n  register_namespace 'different', 'http://www.trollcountry.com/different'\n\n  tag 'address'\n  namespace 'prefix'\n\n  has_many :street, String\n  element :postcode, String\n  element :housenumber, String\n  element :city, String\n  element :country, Country, tag: 'country', namespace: 'different'\n\nend\n```\n","funding_links":[],"categories":["HTML/XML Parsing"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmvz%2Fhappymapper","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmvz%2Fhappymapper","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmvz%2Fhappymapper/lists"}