Code Monkey home page Code Monkey logo

ddex's Introduction

DDEX

<img src=“https://github.com/sshaw/ddex/workflows/CI/badge.svg”/>

DDEX metadata serialization for Ruby

Overview

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) }

Installation

Rubygems:

gem install ddex

Bundler:

gem "ddex"

Supported Versions

See: github.com/sshaw/ddex/tree/master/lib/ddex

How This Differs From the Spec

Every DDEX version handled by this module is fully supported, but there are some things you’ll need to know.

Naming Conventions

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

Cardinally

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)

Boolean Elements and Attributes

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

Version Specific Changes

These changes only affect the object model, the resulting XML will conform to the appropriate DDEX schema.

ERN >= v3.6 < v4.0

PriceInformation/@PriceType has been renamed to PriceInformation#type to avoid conflicting with the element of the same name (PriceInformation/PriceType).

Specification Version Detection

An attempt is made to detect the version. How this is done varies by spec and version. See below for details.

The version can always be explicitly given to DDEX.read via the :version option.

ERN >= 4

Version is determined by the DDEX XML namespace associated with the doc.

For example, given a namespace of: http://ddex.net/xml/ern/41 we’ll try to match the end, either "ern/41" or "ern/41/". The values used to match the come from DDEX::ERN.config[V][:message_schema_version_id] where V is a version string, e.g., "V41".

ERN < 4

The version is detected based on the root element’s value i.e., /node()/@MessageSchemaVersionId.

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 MessageSchemaVersionIds 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.

Validation

Not yet!

DDEX Parsing Service (Rack Endpoint)

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"}

Contributing

See CONTRIBUTING.md

More Info

TODO/Known Problems

  • 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 a NoMethodError:

    # 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

See Also

Author

Skye Shaw [skye.shaw {AT} gmail.com]

License

Copyright © 2013-2020 Skye Shaw. Released under the MIT License.


Made by ScreenStaring

ddex's People

Contributors

ancorcruz avatar benalavi avatar cromonms avatar millar avatar parndt avatar sshaw avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ddex's Issues

Can't Open xml document

Hi,

I'm working on parsing through DDEX files and found your gem. It doesn't appear to work as the README.md states, but there is a ton of code and the majority of the tests pass. I would love to contribute to this if I could, but I can't seem to get going with the gem. Is there something I need to do to make it work? Thanks for you assistance, I hope I can help you progress this gem forward.

ERN v312

Hi @sshaw,

We have to read the following XML:

<ern:NewReleaseMessage xmlns:ern="http://ddex.net/xml/2010/ern-main/312"
                       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                       xsi:schemaLocation="http://ddex.net/xml/2010/ern-main/312 http://ddex.net/xml/2010/ern-main/312/ern-main.xsd"
                       MessageSchemaVersionId="2010/ern-main/312">

As you can see, the MessageSchemaVersionId is 2010/ern-main/312.

How much work do you think it'd be for us to write support for this version, and which steps should we follow in doing so?

Thanks!
Phil

Invalid XML generation (wrong elements order) [ERN V3.2]

ERN v3.2 XSD defines XML sequences for some elements (enforcing order of elements), I bet later versions of the standard do it as well.

DDEX.write generates XML with the elements in the wrong order, for example:

<DisplayArtist>
  <ArtistRole>MainArtist</ArtistRole>
  <PartyName>
    <FullName>Bruno Mars</FullName>
  </PartyName>
</DisplayArtist>

however, the valid XML is:

<DisplayArtist>
  <PartyName>
    <FullName>Bruno Mars</FullName>
  </PartyName>
  <ArtistRole>MainArtist</ArtistRole>
</DisplayArtist>

or

<ImageDetailsByTerritory>
  <TechnicalImageDetails>
    <TechnicalResourceDetailsReference>T12345</TechnicalResourceDetailsReference>
    <ImageCodecType>JPEG</ImageCodecType>
    <ImageHeight>800</ImageHeight>
    <ImageWidth>800</ImageWidth>
    <File>
      <FileName>ABCDEF_T12345.jpg</FileName>
      <FilePath>resources/</FilePath>
      <HashSum>
        <HashSum>aBcDeFgH12345XyZ</HashSum>
        <HashSumAlgorithmType>SHA1</HashSumAlgorithmType>
      </HashSum>
    </File>
  </TechnicalImageDetails>
  <TerritoryCode>Worldwide</TerritoryCode>
</ImageDetailsByTerritory>

while the valid XML is:

<ImageDetailsByTerritory>
  <TerritoryCode>Worldwide</TerritoryCode>
  <TechnicalImageDetails>
    <TechnicalResourceDetailsReference>T12345</TechnicalResourceDetailsReference>
    <ImageCodecType>JPEG</ImageCodecType>
    <ImageHeight>800</ImageHeight>
    <ImageWidth>800</ImageWidth>
    <File>
      <FileName>ABCDEF_T12345.jpg</FileName>
      <FilePath>resources/</FilePath>
      <HashSum>
        <HashSum>aBcDeFgH12345XyZ</HashSum>
        <HashSumAlgorithmType>SHA1</HashSumAlgorithmType>
      </HashSum>
    </File>
  </TechnicalImageDetails>
</ImageDetailsByTerritory>

The root of the issue is in classes that inherit from other classes that define xml_accessors like:

# file: "lib/ddex/v20100712/ddexc/display_artist.rb"
class DDEX::V20100712::DDEXC::DisplayArtist < DDEX::V20100712::DDEXC::PartyDescriptor
  ...
  xml_accessor :artist_roles, :as => [DDEX::V20100712::DDEXC::ArtistRole], :from => "ArtistRole", :required => false
  ...
end

# file: " lib/ddex/v20100712/ddexc/party_descriptor.rb"
class DDEX::V20100712::DDEXC::PartyDescriptor < Element
  ...
  xml_accessor :party_names, :as => [DDEX::V20100712::DDEXC::PartyName], :from => "PartyName", :required => false
  ...
end


# file: "lib/ddex/ern/v32/image_details_by_territory.rb"
class DDEX::ERN::V32::ImageDetailsByTerritory < DDEX::V20100712::DDEXC::ImageDetailsByTerritory
  ...
  xml_accessor :technical_image_details, :as => [DDEX::ERN::V32::TechnicalImageDetails], :from => "TechnicalImageDetails", :required => false
  ...
end

# file: "lib/ddex/v20100712/ddexc/image_details_by_territory.rb"
class DDEX::V20100712::DDEXC::ImageDetailsByTerritory < Element
  ...
  xml_accessor :excluded_territory_codes, :as => [], :from => "ExcludedTerritoryCode", :required => false
  xml_accessor :territory_codes, :as => [], :from => "TerritoryCode", :required => false
  ...
end

XML elements defined in the parent classes are written in the XML output after the elements defined in the child class, however this is not what the XSD defines.

I'm not quite sure how to fix this issue. The only idea I have right now is define each XML element in a single class without inheritance from other XML elements. Not an small change.

Implementing DSR

Hi @sshaw - Any idea of when DSR will be implemented? I could help with it, if you give me the path

Support Rails 7

Hi,

Getting this error when trying to update to Rails 7

  In Gemfile:
    ddex (~> 0.0.8) was resolved to 0.0.8, which depends on
      activesupport (>= 3.0, < 7)

    rails (~> 7.0.2.3) was resolved to 7.0.2.3, which depends on
      activesupport (= 7.0.2.3)

Are there any tasks that need doing before you can bump activesupport version on the gem?

Thanks.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.