xmp 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/.rvmrc ADDED
@@ -0,0 +1,34 @@
1
+ #!/usr/bin/env bash
2
+
3
+ # http://rvm.beginrescueend.com/workflow/rvmrc/
4
+
5
+ ruby_string="ruby-1.9.2"
6
+ gemset_name="xmp"
7
+
8
+ if rvm list strings | grep -q "${ruby_string}" ; then
9
+
10
+ # Load or create the specified environment
11
+ if [[ -d "${rvm_path:-$HOME/.rvm}/environments" \
12
+ && -s "${rvm_path:-$HOME/.rvm}/environments/${ruby_string}@${gemset_name}" ]] ; then
13
+ \. "${rvm_path:-$HOME/.rvm}/environments/${ruby_string}@${gemset_name}"
14
+ else
15
+ rvm --create "${ruby_string}@${gemset_name}"
16
+ fi
17
+
18
+ # (
19
+ # Ensure that Bundler is installed, install it if it is not.
20
+ if ! command -v bundle &> /dev/null; then
21
+ echo "Installing bundler and creating bundle"
22
+ gem install bundler
23
+ bundle
24
+ fi
25
+ # )&
26
+
27
+ else
28
+
29
+ # Notify the user to install the desired interpreter before proceeding.
30
+ echo "${ruby_string} was not found, please run 'rvm install ${ruby_string}' and then cd back into the project directory."
31
+
32
+ fi
33
+
34
+
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec
data/README.rdoc ADDED
@@ -0,0 +1,51 @@
1
+ = xmp - Extensible Metadata Platform (XMP) parser
2
+
3
+ XMP provides object oriented interface to XMP data (http://en.wikipedia.org/wiki/Extensible_Metadata_Platform). XMP data can be found in PDF, JPEG, GIF, PNG, and many other formats.
4
+
5
+ == Supported formats
6
+
7
+ Currently only JPEG is supported through exifr gem.
8
+
9
+ == JPEG example
10
+
11
+ # gem install xmp exifr
12
+ require 'xmp'
13
+ require 'exifr'
14
+ require 'open-uri'
15
+
16
+ img = EXIFR::JPEG.new('spec/fixtures/multiple-app1.jpg')
17
+ xmp = XMP.parse(img)
18
+ xmp.dc.subject #=> ["something interesting"]
19
+
20
+ # explore XMP data
21
+ xmp.namespaces.each do |namespace_name|
22
+ namespace = xmp.send(namespace_name)
23
+ namespace.attributes.each do |attr|
24
+ puts "#{namespace_name}.#{attr}: " + namespace.send(attr).inspect
25
+ end
26
+ end
27
+
28
+ == Installation
29
+
30
+ gem install xmp
31
+ # for JPEG support
32
+ gem install exifr -v ">=1.0.4"
33
+
34
+ == Requirements
35
+
36
+ * Ruby 1.8.7, 1.9.2
37
+ * Nokogiri 1.4
38
+ * EXIFR >= 1.0.4
39
+
40
+ == Development
41
+
42
+ # install development dependencies
43
+ bundle install
44
+ # run specs
45
+ rake spec
46
+
47
+ == License
48
+
49
+ Ruby's license.
50
+
51
+ Copyright (c) 2011 Wojciech Piekutowski, AmberBit (http://amberbit.com)
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+ require 'rspec/core/rake_task'
4
+
5
+ task :default => :spec
6
+
7
+ desc "Run all specs"
8
+ RSpec::Core::RakeTask.new do |t|
9
+ t.ruby_opts = "-w"
10
+ t.verbose = true
11
+ t.skip_bundler = true
12
+ end
data/lib/xmp.rb ADDED
@@ -0,0 +1,70 @@
1
+ require 'xmp/silencer'
2
+ XMP::Silencer.silently { require 'nokogiri' }
3
+ require 'xmp/namespace'
4
+
5
+ # = XMP XML parser
6
+ #
7
+ # == Example
8
+ # xmp = XMP.new(File.read('xmp.xml'))
9
+ # xmp.dc.title # => "Amazing Photo"
10
+ # xmp.photoshop.Category # => "summer"
11
+ # xmp.photoshop.SupplementalCategories # => ["morning", "sea"]
12
+ class XMP
13
+ # underlying XML content
14
+ attr_reader :xml
15
+ # available namespace names
16
+ attr_reader :namespaces
17
+
18
+ # accepts valid XMP XML
19
+ def initialize(xml)
20
+ doc = Nokogiri::XML(xml)
21
+ @xml = doc.root
22
+
23
+ available_namespaces = doc.collect_namespaces
24
+ # let nokogiri know about all namespaces
25
+ available_namespaces.each do |ns, url|
26
+ @xml.add_namespace_definition ns, url
27
+ end
28
+
29
+ # collect namespace names
30
+ @namespaces = available_namespaces.collect do |ns, _|
31
+ ns =~ /^xmlns:(.+)/
32
+ $1
33
+ end
34
+ end
35
+
36
+ def inspect
37
+ "#<XMP:@namespaces=#{@namespaces.inspect}>"
38
+ end
39
+
40
+ # returns Namespace object if namespace exists, otherwise tries to call a method
41
+ def method_missing(namespace, *args)
42
+ if has_namespace?(namespace)
43
+ Namespace.new(self, namespace)
44
+ else
45
+ super
46
+ end
47
+ end
48
+
49
+ def respond_to?(method)
50
+ has_namespace?(method) or super
51
+ end
52
+
53
+ def self.parse(doc)
54
+ case doc.class.to_s
55
+ when 'EXIFR::JPEG'
56
+ if xmp_chunk = doc.app1s.find { |a| a =~ %r|\Ahttp://ns.adobe.com/xap/1.0/| }
57
+ xmp_data = xmp_chunk.split("\000")[1]
58
+ XMP.new(xmp_data)
59
+ end
60
+ else
61
+ raise "Document not supported:\n#{doc.inspect}"
62
+ end
63
+ end
64
+
65
+ private
66
+
67
+ def has_namespace?(namespace)
68
+ namespaces.include?(namespace.to_s)
69
+ end
70
+ end
@@ -0,0 +1,69 @@
1
+ class XMP
2
+ class Namespace
3
+ # available attributes
4
+ attr_reader :attributes
5
+
6
+ def initialize(xmp, namespace) # :nodoc
7
+ @xmp = xmp
8
+ @namespace = namespace.to_s
9
+
10
+ @attributes = []
11
+ embedded_attributes =
12
+ xml.xpath("//rdf:Description").map { |d|
13
+ d.attributes.values.
14
+ select { |attr| attr.namespace.prefix.to_s == @namespace }.
15
+ map(&:name)
16
+ }.flatten
17
+ @attributes.concat embedded_attributes
18
+ standalone_attributes = xml.xpath("//rdf:Description/#{@namespace}:*").
19
+ map(&:name)
20
+ @attributes.concat standalone_attributes
21
+ end
22
+
23
+ def inspect
24
+ "#<XMP::Namespace:#{@namespace}>"
25
+ end
26
+
27
+ def method_missing(method, *args)
28
+ if has_attribute?(method)
29
+ embedded_attribute(method) || standalone_attribute(method)
30
+ else
31
+ super
32
+ end
33
+ end
34
+
35
+ def respond_to?(method)
36
+ has_attribute?(method) or super
37
+ end
38
+
39
+ private
40
+
41
+ def embedded_attribute(name)
42
+ element = xml.at("//rdf:Description[@#{@namespace}:#{name}]")
43
+ return unless element
44
+ element.attribute(name.to_s).text
45
+ end
46
+
47
+ def has_attribute?(name)
48
+ attributes.include?(name.to_s)
49
+ end
50
+
51
+ def standalone_attribute(name)
52
+ attribute_xpath = "//#{@namespace}:#{name}"
53
+ attribute = xml.xpath(attribute_xpath).first
54
+ return unless attribute
55
+
56
+ array_value = attribute.xpath("./rdf:Bag | ./rdf:Seq | ./rdf:Alt").first
57
+ if array_value
58
+ items = array_value.xpath("./rdf:li")
59
+ items.map { |i| i.text }
60
+ else
61
+ raise "Don't know how to handle: \n" + attribute.to_s
62
+ end
63
+ end
64
+
65
+ def xml
66
+ @xmp.xml
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,11 @@
1
+ class XMP
2
+ module Silencer
3
+ def self.silently
4
+ verbosity = $VERBOSE
5
+ $VERBOSE = nil
6
+ result = yield
7
+ $VERBOSE = verbosity
8
+ result
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,3 @@
1
+ class XMP
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,13 @@
1
+ require './spec/spec_helper.rb'
2
+
3
+ describe "XMP with EXIFR::JPEG" do
4
+ before do
5
+ XMP::Silencer.silently { @img = EXIFR::JPEG.new('spec/fixtures/multiple-app1.jpg') }
6
+ end
7
+
8
+ it "should parse image" do
9
+ xmp = XMP.parse(@img)
10
+ xmp.should be_instance_of(XMP)
11
+ xmp.namespaces.should =~ %w{dc iX pdf photoshop rdf tiff x xap xapRights}
12
+ end
13
+ end
Binary file
@@ -0,0 +1,239 @@
1
+ <?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?>
2
+ <x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 4.2-c020 1.124078, Tue Sep 11 2007 23:21:40 ">
3
+ <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
4
+ <rdf:Description rdf:about=""
5
+ xmlns:tiff="http://ns.adobe.com/tiff/1.0/"
6
+ xmlns:exif="http://ns.adobe.com/exif/1.0/"
7
+ xmlns:xap="http://ns.adobe.com/xap/1.0/"
8
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
9
+ xmlns:aux="http://ns.adobe.com/exif/1.0/aux/"
10
+ xmlns:Iptc4xmpCore="http://iptc.org/std/Iptc4xmpCore/1.0/xmlns/"
11
+ xmlns:photoshop="http://ns.adobe.com/photoshop/1.0/"
12
+ xmlns:crs="http://ns.adobe.com/camera-raw-settings/1.0/"
13
+ tiff:Make="Canon"
14
+ tiff:Model="Canon EOS-1D Mark III"
15
+ tiff:ImageWidth="800"
16
+ tiff:ImageLength="533"
17
+ tiff:XResolution="72/1"
18
+ tiff:YResolution="72/1"
19
+ tiff:ResolutionUnit="2"
20
+ exif:ExifVersion="0221"
21
+ exif:ExposureTime="1/320"
22
+ exif:ShutterSpeedValue="8321928/1000000"
23
+ exif:FNumber="35/10"
24
+ exif:ApertureValue="361471/100000"
25
+ exif:ExposureProgram="1"
26
+ exif:DateTimeOriginal="2011-01-18T15:48:52.00+01:00"
27
+ exif:DateTimeDigitized="2011-01-18T15:48:52.00+01:00"
28
+ exif:ExposureBiasValue="0/1"
29
+ exif:MaxApertureValue="175/100"
30
+ exif:SubjectDistance="727/100"
31
+ exif:MeteringMode="5"
32
+ exif:FocalLength="85/1"
33
+ exif:CustomRendered="0"
34
+ exif:ExposureMode="1"
35
+ exif:WhiteBalance="0"
36
+ exif:SceneCaptureType="0"
37
+ exif:FocalPlaneXResolution="3888000/1107"
38
+ exif:FocalPlaneYResolution="2592000/736"
39
+ exif:FocalPlaneResolutionUnit="2"
40
+ exif:PixelXDimension="800"
41
+ exif:PixelYDimension="533"
42
+ xap:ModifyDate="2011-02-04T11:12:00+01:00"
43
+ xap:CreateDate="2011-01-18T15:48:52.00+01:00"
44
+ xap:CreatorTool="Adobe Photoshop Lightroom"
45
+ aux:SerialNumber="562133"
46
+ aux:LensInfo="85/1 85/1 0/0 0/0"
47
+ aux:Lens="EF85mm f/1.8 USM"
48
+ aux:LensID="155"
49
+ aux:ImageNumber="0"
50
+ aux:FlashCompensation="0/1"
51
+ aux:OwnerName="John Doe"
52
+ aux:Firmware="1.2.3"
53
+ Iptc4xmpCore:Location="Miejsce"
54
+ photoshop:Category="Kategoria"
55
+ photoshop:LegacyIPTCDigest="7220E75D669D5F417F2D6C9ADA130467"
56
+ crs:Version="6.1"
57
+ crs:ProcessVersion="5.7"
58
+ crs:WhiteBalance="As Shot"
59
+ crs:Temperature="4950"
60
+ crs:Tint="-6"
61
+ crs:Exposure="-0.75"
62
+ crs:Shadows="15"
63
+ crs:Brightness="+92"
64
+ crs:Contrast="+27"
65
+ crs:Saturation="+5"
66
+ crs:Sharpness="25"
67
+ crs:LuminanceSmoothing="0"
68
+ crs:ColorNoiseReduction="25"
69
+ crs:ChromaticAberrationR="0"
70
+ crs:ChromaticAberrationB="0"
71
+ crs:VignetteAmount="-61"
72
+ crs:VignetteMidpoint="50"
73
+ crs:ShadowTint="0"
74
+ crs:RedHue="+14"
75
+ crs:RedSaturation="+18"
76
+ crs:GreenHue="0"
77
+ crs:GreenSaturation="0"
78
+ crs:BlueHue="-7"
79
+ crs:BlueSaturation="-7"
80
+ crs:FillLight="31"
81
+ crs:Vibrance="0"
82
+ crs:HighlightRecovery="30"
83
+ crs:Clarity="+100"
84
+ crs:Defringe="0"
85
+ crs:HueAdjustmentRed="0"
86
+ crs:HueAdjustmentOrange="+33"
87
+ crs:HueAdjustmentYellow="0"
88
+ crs:HueAdjustmentGreen="0"
89
+ crs:HueAdjustmentAqua="0"
90
+ crs:HueAdjustmentBlue="0"
91
+ crs:HueAdjustmentPurple="0"
92
+ crs:HueAdjustmentMagenta="0"
93
+ crs:SaturationAdjustmentRed="-2"
94
+ crs:SaturationAdjustmentOrange="-30"
95
+ crs:SaturationAdjustmentYellow="0"
96
+ crs:SaturationAdjustmentGreen="0"
97
+ crs:SaturationAdjustmentAqua="0"
98
+ crs:SaturationAdjustmentBlue="0"
99
+ crs:SaturationAdjustmentPurple="0"
100
+ crs:SaturationAdjustmentMagenta="0"
101
+ crs:LuminanceAdjustmentRed="0"
102
+ crs:LuminanceAdjustmentOrange="0"
103
+ crs:LuminanceAdjustmentYellow="0"
104
+ crs:LuminanceAdjustmentGreen="0"
105
+ crs:LuminanceAdjustmentAqua="0"
106
+ crs:LuminanceAdjustmentBlue="0"
107
+ crs:LuminanceAdjustmentPurple="0"
108
+ crs:LuminanceAdjustmentMagenta="0"
109
+ crs:SplitToningShadowHue="0"
110
+ crs:SplitToningShadowSaturation="0"
111
+ crs:SplitToningHighlightHue="0"
112
+ crs:SplitToningHighlightSaturation="0"
113
+ crs:SplitToningBalance="+64"
114
+ crs:ParametricShadows="+60"
115
+ crs:ParametricDarks="-11"
116
+ crs:ParametricLights="+15"
117
+ crs:ParametricHighlights="+70"
118
+ crs:ParametricShadowSplit="25"
119
+ crs:ParametricMidtoneSplit="50"
120
+ crs:ParametricHighlightSplit="80"
121
+ crs:SharpenRadius="+1.0"
122
+ crs:SharpenDetail="25"
123
+ crs:SharpenEdgeMasking="0"
124
+ crs:PostCropVignetteAmount="0"
125
+ crs:GrainAmount="0"
126
+ crs:ColorNoiseReductionDetail="50"
127
+ crs:LensProfileEnable="0"
128
+ crs:LensManualDistortionAmount="0"
129
+ crs:PerspectiveVertical="0"
130
+ crs:PerspectiveHorizontal="0"
131
+ crs:PerspectiveRotate="0.0"
132
+ crs:PerspectiveScale="100"
133
+ crs:ConvertToGrayscale="False"
134
+ crs:ToneCurveName="Medium Contrast"
135
+ crs:CameraProfile="Adobe Standard"
136
+ crs:CameraProfileDigest="631F0C9CC003981496182C3DD10EF165"
137
+ crs:LensProfileSetup="LensDefaults"
138
+ crs:HasSettings="True"
139
+ crs:CropTop="0.024828"
140
+ crs:CropLeft="0.012414"
141
+ crs:CropBottom="1"
142
+ crs:CropRight="0.987586"
143
+ crs:CropAngle="0"
144
+ crs:CropConstrainToWarp="0"
145
+ crs:CropWidth="800"
146
+ crs:CropHeight="533"
147
+ crs:CropUnit="0"
148
+ crs:HasCrop="True"
149
+ crs:AlreadyApplied="True">
150
+ <exif:ISOSpeedRatings>
151
+ <rdf:Seq>
152
+ <rdf:li>100</rdf:li>
153
+ </rdf:Seq>
154
+ </exif:ISOSpeedRatings>
155
+ <dc:creator>
156
+ <rdf:Seq>
157
+ <rdf:li>John Doe</rdf:li>
158
+ </rdf:Seq>
159
+ </dc:creator>
160
+ <dc:title>
161
+ <rdf:Alt>
162
+ <rdf:li xml:lang="x-default">Tytuł zdjęcia</rdf:li>
163
+ </rdf:Alt>
164
+ </dc:title>
165
+ <dc:rights>
166
+ <rdf:Alt>
167
+ <rdf:li xml:lang="x-default">Autor</rdf:li>
168
+ </rdf:Alt>
169
+ </dc:rights>
170
+ <dc:subject>
171
+ <rdf:Bag>
172
+ <rdf:li>Słowa kluczowe i numery startowe.</rdf:li>
173
+ </rdf:Bag>
174
+ </dc:subject>
175
+ <dc:description>
176
+ <rdf:Alt>
177
+ <rdf:li xml:lang="x-default">Opis zdjęcia</rdf:li>
178
+ </rdf:Alt>
179
+ </dc:description>
180
+ <photoshop:SupplementalCategories>
181
+ <rdf:Bag>
182
+ <rdf:li>Nazwa imprezy</rdf:li>
183
+ </rdf:Bag>
184
+ </photoshop:SupplementalCategories>
185
+ <crs:ToneCurve>
186
+ <rdf:Seq>
187
+ <rdf:li>0, 0</rdf:li>
188
+ <rdf:li>32, 22</rdf:li>
189
+ <rdf:li>64, 56</rdf:li>
190
+ <rdf:li>128, 128</rdf:li>
191
+ <rdf:li>192, 196</rdf:li>
192
+ <rdf:li>255, 255</rdf:li>
193
+ </rdf:Seq>
194
+ </crs:ToneCurve>
195
+ </rdf:Description>
196
+ </rdf:RDF>
197
+ </x:xmpmeta>
198
+
199
+
200
+
201
+
202
+
203
+
204
+
205
+
206
+
207
+
208
+
209
+
210
+
211
+
212
+
213
+
214
+
215
+
216
+
217
+
218
+
219
+
220
+
221
+
222
+
223
+
224
+
225
+
226
+
227
+
228
+
229
+
230
+
231
+
232
+
233
+
234
+
235
+
236
+
237
+
238
+
239
+ <?xpacket end="w"?>
@@ -0,0 +1,57 @@
1
+ <?xpacket begin='' id='W5M0MpCehiHzreSzNTczkc9d'?>
2
+ <?adobe-xap-filters esc="CR"?>
3
+ <x:xmpmeta xmlns:x='adobe:ns:meta/' x:xmptk='XMP toolkit 2.9-9, framework 1.6'>
4
+ <rdf:RDF xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#' xmlns:iX='http://ns.adobe.com/iX/1.0/'>
5
+ <rdf:Description rdf:about='' xmlns:pdf='http://ns.adobe.com/pdf/1.3/'></rdf:Description>
6
+ <rdf:Description rdf:about='' xmlns:photoshop='http://ns.adobe.com/photoshop/1.0/' photoshop:Headline='DeniseTestImage' photoshop:Credit='Remco'></rdf:Description>
7
+ <rdf:Description rdf:about='' xmlns:tiff='http://ns.adobe.com/tiff/1.0/'></rdf:Description>
8
+ <rdf:Description rdf:about='' xmlns:xap='http://ns.adobe.com/xap/1.0/'></rdf:Description>
9
+ <rdf:Description rdf:about='' xmlns:xapRights='http://ns.adobe.com/xap/1.0/rights/'></rdf:Description>
10
+ <rdf:Description rdf:about='' xmlns:dc='http://purl.org/dc/elements/1.1/'>
11
+ <dc:subject><rdf:Bag><rdf:li>SAMPLEkeyworddataFromIview</rdf:li></rdf:Bag></dc:subject>
12
+ <dc:creator><rdf:Seq><rdf:li>BenjaminStorrier</rdf:li></rdf:Seq></dc:creator>
13
+ <dc:rights><rdf:Alt> <rdf:li>PublicDomain</rdf:li></rdf:Alt></dc:rights>
14
+ </rdf:Description>
15
+ </rdf:RDF>
16
+ </x:xmpmeta>
17
+
18
+
19
+
20
+
21
+
22
+
23
+
24
+
25
+
26
+
27
+
28
+
29
+
30
+
31
+
32
+
33
+
34
+
35
+
36
+
37
+
38
+
39
+
40
+
41
+
42
+
43
+
44
+
45
+
46
+
47
+
48
+
49
+
50
+
51
+
52
+
53
+
54
+
55
+
56
+
57
+ <?xpacket end='r'?>
@@ -0,0 +1,12 @@
1
+ $LOAD_PATH.unshift 'lib'
2
+ require 'xmp/silencer'
3
+
4
+ XMP::Silencer.silently {
5
+ require 'bundler/setup'
6
+ Bundler.require(:development)
7
+ }
8
+
9
+ # load whole montgomery after bundler loads required gems
10
+ require 'xmp'
11
+
12
+ require 'pp'
data/spec/xmp_spec.rb ADDED
@@ -0,0 +1,61 @@
1
+ # encoding: UTF-8
2
+ require './spec/spec_helper.rb'
3
+
4
+ describe XMP do
5
+ describe "with xmp.xml" do
6
+ before { @xmp = XMP.new(File.read('spec/fixtures/xmp.xml')) }
7
+
8
+ it "should return all namespace names" do
9
+ @xmp.namespaces.should =~ %w{rdf x tiff exif xap aux Iptc4xmpCore photoshop crs dc}
10
+ end
11
+
12
+ it "should return standalone attribute" do
13
+ @xmp.dc.title.should eq(['Tytuł zdjęcia'])
14
+ @xmp.dc.subject.should eq(['Słowa kluczowe i numery startowe.'])
15
+ @xmp.photoshop.SupplementalCategories.should eq(['Nazwa imprezy'])
16
+ end
17
+
18
+ it "should return embedded attribute" do
19
+ @xmp.Iptc4xmpCore.Location.should eq('Miejsce')
20
+ @xmp.photoshop.Category.should eq('Kategoria')
21
+ end
22
+
23
+ it "should raise NoMethodError on unknown attribute" do
24
+ lambda { @xmp.photoshop.UnknownAttribute }.should raise_error(NoMethodError)
25
+ end
26
+
27
+ describe "namespace 'tiff'" do
28
+ before { @namespace = @xmp.tiff }
29
+
30
+ it "should return all attribute names" do
31
+ @namespace.attributes.should =~ %w{Make Model ImageWidth ImageLength XResolution YResolution ResolutionUnit}
32
+ end
33
+ end
34
+
35
+ describe "namespace 'photoshop'" do
36
+ before { @namespace = @xmp.photoshop }
37
+
38
+ it "should return all attribute names" do
39
+ @namespace.attributes.should =~ %w{LegacyIPTCDigest Category SupplementalCategories}
40
+ end
41
+ end
42
+ end
43
+
44
+ describe "with xmp2.xml" do
45
+ before { @xmp = XMP.new(File.read('spec/fixtures/xmp2.xml')) }
46
+
47
+ it "should return all namespace names" do
48
+ @xmp.namespaces.should =~ %w{dc iX pdf photoshop rdf tiff x xap xapRights}
49
+ end
50
+
51
+ it "should return standalone attribute" do
52
+ @xmp.dc.creator.should eq(['BenjaminStorrier'])
53
+ @xmp.dc.subject.should eq(['SAMPLEkeyworddataFromIview'])
54
+ end
55
+
56
+ it "should return embedded attribute" do
57
+ @xmp.photoshop.Headline.should eq('DeniseTestImage')
58
+ @xmp.photoshop.Credit.should eq('Remco')
59
+ end
60
+ end
61
+ end
data/xmp.gemspec ADDED
@@ -0,0 +1,28 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "xmp/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "xmp"
7
+ s.version = XMP::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Wojciech Piekutowski"]
10
+ s.email = ["wojciech.piekutowski@amberbit.com"]
11
+ s.homepage = ""
12
+ s.summary = %q{Extensible Metadata Platform (XMP) parser}
13
+ s.description = %q{Extensible Metadata Platform (XMP) parser}
14
+
15
+ s.rubyforge_project = "xmp"
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
+ s.require_paths = ["lib"]
21
+
22
+ s.extra_rdoc_files = %w(README.rdoc)
23
+
24
+ s.add_dependency 'nokogiri', '~>1.4.0'
25
+
26
+ s.add_development_dependency 'exifr', '>=1.0.4'
27
+ s.add_development_dependency 'rspec', '~>2.0'
28
+ end
metadata ADDED
@@ -0,0 +1,98 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: xmp
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Wojciech Piekutowski
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-02-26 00:00:00.000000000 +01:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: nokogiri
17
+ requirement: &8132500 !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ~>
21
+ - !ruby/object:Gem::Version
22
+ version: 1.4.0
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: *8132500
26
+ - !ruby/object:Gem::Dependency
27
+ name: exifr
28
+ requirement: &8132000 !ruby/object:Gem::Requirement
29
+ none: false
30
+ requirements:
31
+ - - ! '>='
32
+ - !ruby/object:Gem::Version
33
+ version: 1.0.4
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: *8132000
37
+ - !ruby/object:Gem::Dependency
38
+ name: rspec
39
+ requirement: &8131540 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ~>
43
+ - !ruby/object:Gem::Version
44
+ version: '2.0'
45
+ type: :development
46
+ prerelease: false
47
+ version_requirements: *8131540
48
+ description: Extensible Metadata Platform (XMP) parser
49
+ email:
50
+ - wojciech.piekutowski@amberbit.com
51
+ executables: []
52
+ extensions: []
53
+ extra_rdoc_files:
54
+ - README.rdoc
55
+ files:
56
+ - .gitignore
57
+ - .rspec
58
+ - .rvmrc
59
+ - Gemfile
60
+ - README.rdoc
61
+ - Rakefile
62
+ - lib/xmp.rb
63
+ - lib/xmp/namespace.rb
64
+ - lib/xmp/silencer.rb
65
+ - lib/xmp/version.rb
66
+ - spec/exifr_jpeg_spec.rb
67
+ - spec/fixtures/multiple-app1.jpg
68
+ - spec/fixtures/xmp.xml
69
+ - spec/fixtures/xmp2.xml
70
+ - spec/spec_helper.rb
71
+ - spec/xmp_spec.rb
72
+ - xmp.gemspec
73
+ has_rdoc: true
74
+ homepage: ''
75
+ licenses: []
76
+ post_install_message:
77
+ rdoc_options: []
78
+ require_paths:
79
+ - lib
80
+ required_ruby_version: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ required_rubygems_version: !ruby/object:Gem::Requirement
87
+ none: false
88
+ requirements:
89
+ - - ! '>='
90
+ - !ruby/object:Gem::Version
91
+ version: '0'
92
+ requirements: []
93
+ rubyforge_project: xmp
94
+ rubygems_version: 1.5.2
95
+ signing_key:
96
+ specification_version: 3
97
+ summary: Extensible Metadata Platform (XMP) parser
98
+ test_files: []