<img src=“https://secure.travis-ci.org/sshaw/ddex.svg”/>
DDEX metadata serialization for Ruby
require "ddex" message = DDEX.read("path/to/metadata.xml") # ERN puts message.update_indicator message.resource_list.sound_recordings.each do |sr| title = sr.reference_title.title_text puts title.value puts title.language_and_script_code puts sr.remastered? end puts "Supported!" if DDEX.supports?("ern/341") message = DDEX.read(string) message = DDEX.read(io) p message.to_hash include DDEX::ERN::V341 # v3.4.1 message = NewReleaseMessage.new(:resource_list => ResourceList.new) record = SoundRecording.new(:language_and_script_code => "en-US") # ... message.resource_list.sound_recordings = [record] xml = DDEX.write(message) File.open("bloat.xml", "w") { |io| io.puts(xml) }
Rubygems:
gem install ddex
Bundler:
gem "ddex"
Currently just ERN 3.3 - 3.7, DSR soon!
Every DDEX version handled by this module is fully supported, but there are some things you’ll need to know.
DDEX elements and attributes use the CamelCase naming convention, this module uses Ruby naming conversions: CamelCase for classes, and snake_case for class attributes. For example, this DDEX XML:
<PartyName> <FullName>sshaw</FullName> </PartyName>
Would be manipulated via:
party = PartyName.new(:full_name => "sshaw") puts party.full_name party.full_name = "gwozdzie"
See also Boolean elements and attributes
Elements that can occur more than once will be placed in an Array
and their parent classes’ accessor methods will use the plural form of the element/attribute’s name. For example:
<Release> <!-- More data --> <PLine> <Year>1994</Year> <PLineText>Track Copyright</PLineText> </PLine> <PLine> <Year>2001</Year> <PLineText>Another Track Copyright</PLineText> </PLine> </Release>
Would be manipulated via:
release.p_lines.each { |line| puts line.p_line_text } release.p_lines << PLine.new(:year => 1999)
The following are applied to accessors derived from DDEX elements and attributes with an XML schema type of boolean
:
-
"Is"
is removed from the beginning of the name -
The reader method is turned into a predicate accessor, i.e., has a
"?"
appended to it
For example, SoundRecording/IsArtistRelated
:
recording = SoundRecording.new(:artist_related => true) p recording.artist_related? # true recording.artist_related = false
These changes only affect the object model, the resulting XML will conform to the appropriate DDEX schema.
PriceInformation/@PriceType
has been renamed to PriceInformation#type
to avoid conflicting with the element of the same name (PriceInformation/PriceType
).
The specification version is determined by the MessageSchemaVersionId
, which can be:
-
Detected based on the root element’s value i.e.,
/node()/@MessageSchemaVersionId
(the root element varies by specification) -
Explicitly given to DDEX.read via the
:version
option
By default the MessageSchemaVersionId
is assumed to be in SPEC/VERSION
or VERSION
format (any leading, trailing, or duplicate slashes will be stripped), as this seems to be the convention used by most instance docs -though the DDEX specifications are not strict about this. If you’re dealing with MessageSchemaVersionId
s that vary from this format, and explicitly setting the version is not practical, you can set the global default(s):
DDEX::ERN.config["V35"][:message_schema_version_id] = "ern tray_fever!" DDEX::ERN.config["V351"][:message_schema_version_id] = "ern/35-punto-1" # ...
Note that the version key must match the version’s module name.
Feel free to open an issue if you feel this arrangement is problematic or should be modified to accommodate something else.
Not yet!
If you want to parse DDEX metadata but don’t want to use Ruby to process the results you can setup a parsing service using Rack::DDEX
. Rack::DDEX
is a Rack endpoint that parses a DDEX file and returns JSON.
For example, from the repository’s root:
~/code/ruby/ddex >cat etc/config.ru require "rack/ddex" run Rack::DDEX.new ~/code/ruby/ddex >rackup -I lib etc/config.ru # Note that -D has problems with autoloading [2014-12-15 20:35:40] INFO WEBrick 1.3.1 [2014-12-15 20:35:40] INFO ruby 2.1.2 (2014-05-08) [x86_64-darwin13.0] [2014-12-15 20:35:40] INFO WEBrick::HTTPServer#start: pid=76385 port=9292
Then, from another terminal
~/code/ruby/ddex >curl -d @spec/fixtures/ern/36/instance1.xml http://localhost:9292 {"message_header":{"message_thread_id":"Bu._UcZLsNbTVitjYnci","message_id":"DbVn-iuUB-SiHl05B2IqW3_","message_file_name":"wz9RHX_Eu1d" ... ~/code/ruby/ddex >curl http://localhost:9292 # HTTP 400 {"error":"XML parsing error: Start tag expected, '<' not found"}
See CONTRIBUTING.md
-
jaxb2ruby (Generate Ruby objects from an XML schema)
-
ROXML.from_xml
does not check the root element’s name. Need to add something like:raise "unknown element #{xml.name}" unless xml.name == tag_name
-
When an ROXML accessor expects an ROXML class, and one is not provided,
to_xml
will result in aNoMethodError
:# in SomeClass xml_accessor :x, :as => AnotherClass # Then x = SomeClass.new(:x => "123") x.to_xml # undefined method `to_xml' for "123":String
Raised here: github.com/Empact/roxml/blob/v2.5.1/lib/roxml/xml/references.rb#L262
Skye Shaw [skye.shaw {AT} gmail.com]
Copyright © 2013 Skye Shaw. Released under the MIT License.