xmpr 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 08d0e048e64b4d40f19b961396560ca82665e267
4
+ data.tar.gz: 47aa31c23b2373edda9845062c9fde289c069903
5
+ SHA512:
6
+ metadata.gz: f282f52a180f4afca03cde9afb64c6f560d9d4e403c99ff5f27bfd306bf2296f534f06f91d5a4fa64734346f0b09be7d6bb3a861f19666232ef57c18896b3393
7
+ data.tar.gz: 06f0587b77eb1a758295e57aac7b7ece5abb5aa80eff6abefed1d01ddcb339bda15405c7d644d601f5e3b7ead72c7769e27a7f3e16dc7adc88c771fe08db4de0
@@ -0,0 +1,2 @@
1
+ �e�px����G���zX,�Y� �?E���>rE�[��;,���iZr�j2f&�F�x]~�G����#��V�0��?���
2
+ ��Ew�ʼnuϏ��!i�"i�GK��~w̎HM%G"sC�:�N��|�zk� ވ�_�+3�Sm
@@ -0,0 +1,4 @@
1
+ �{��_�:�Ah���a��,�A������-�үr��1���/_�;S33D�9ϫ������-_E���/=��[��)�.ҹ+iڙ�7�Pn��ϭ���cHO�{�F9�O�?&wޕ3X �J� �E�q�^=^1R5O
2
+ ���ZL-07�`$�:�.���b�Y�
3
+ ��R>����G�G(��^L%�~���(�G�  ��7��@��M�@�}�f�"���N�����ME .(�h�
4
+ :"��zR��p�£U��~
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 Samuel Cochran
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,16 @@
1
+ # XMP Reader
2
+
3
+ [![Build Status](https://travis-ci.org/sj26/xmpr?branch=master)](https://travis-ci.org/sj26/xmpr)
4
+
5
+ XMP Reader in Ruby. Parse XMP data extracted from an image into rich data types.
6
+
7
+ ## Thanks
8
+
9
+ Refactored from [XMP][xmp-gem]. Inspired by [ExifTool][exiftool].
10
+
11
+ [xmp-gem]: https://github.com/amberbit/xmp
12
+ [exiftool]: http://www.sno.phy.queensu.ca/~phil/exiftool/
13
+
14
+ ## License
15
+
16
+ MIT license, see [LICENSE](LICENSE).
@@ -0,0 +1,122 @@
1
+ # XMPR
2
+ #
3
+ # XMP reader
4
+ #
5
+ # XMPR has some known namespaces, like "dc" for dublin core. See the NAMESPACES
6
+ # constants for a complete list.
7
+ #
8
+ # ## Example
9
+ #
10
+ # xmp = XMPR.parse(File.read('xmp.xml'))
11
+ # xmp["dc", "title"] # => "Amazing Photo"
12
+ # xmp["photoshop", "Category"] # => "summer"
13
+ # xmp["photoshop", "SupplementalCategories"] # => ["morning", "sea"]
14
+ #
15
+ # ## References
16
+ #
17
+ # * https://www.aiim.org/documents/standards/xmpspecification.pdf
18
+ #
19
+ module XMPR
20
+ # Namespace shortcuts, and fallbacks for undeclared namespaces.
21
+ NAMESPACES = {
22
+ "aux" => "http://ns.adobe.com/exif/1.0/aux/",
23
+ "crs" => "http://ns.adobe.com/camera-raw-settings/1.0/",
24
+ "dc" => "http://purl.org/dc/elements/1.1/",
25
+ "exif" => "http://ns.adobe.com/exif/1.0/",
26
+ "Iptc4xmpCore" => "http://iptc.org/std/Iptc4xmpCore/1.0/xmlns/",
27
+ "pdf" => "http://ns.adobe.com/pdf/1.3/",
28
+ "photoshop" => "http://ns.adobe.com/photoshop/1.0/",
29
+ "rdf" => "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
30
+ "tiff" => "http://ns.adobe.com/tiff/1.0/",
31
+ "x" => "adobe:ns:meta/",
32
+ "xap" => "http://ns.adobe.com/xap/1.0/",
33
+ "xmp" => "http://ns.adobe.com/xap/1.0/",
34
+ "xmpidq" => "http://ns.adobe.com/xmp/Identifier/qual/1.0/",
35
+ "xmpBJ" => "http://ns.adobe.com/xap/1.0/bj/",
36
+ "xmpRights" => "http://ns.adobe.com/xap/1.0/rights/",
37
+ "xmpMM" => "http://ns.adobe.com/xap/1.0/mm/",
38
+ "xmpTPg" => "http://ns.adobe.com/xap/1.0/t/pg/",
39
+ }
40
+
41
+ DEFAULT_NAMESPACE = "http://ns.adobe.com/xap/1.0/"
42
+
43
+ def self.parse(value)
44
+ XMP.new(value)
45
+ end
46
+
47
+ class XMP
48
+ # Nokogiri document of parsed xml
49
+ attr_reader :xml
50
+
51
+ def initialize(source)
52
+ require "nokogiri"
53
+ @xml = Nokogiri::XML(source)
54
+ end
55
+
56
+ def [](namespace_or_name, name=nil, **options)
57
+ if name
58
+ namespace = namespace_or_name
59
+ else
60
+ namespace, name = DEFAULT_NAMESPACE, namespace_or_name
61
+ end
62
+
63
+ if NAMESPACES.has_key? namespace
64
+ namespace = NAMESPACES[namespace]
65
+ end
66
+
67
+ embedded_attribute(namespace, name) ||
68
+ standalone_attribute(namespace, name, **options)
69
+ end
70
+
71
+ def to_hash
72
+ {}.tap do |hash|
73
+ xml.at("//rdf:Description", NAMESPACES).attributes.each do |(_, attribute)|
74
+ hash[attribute.namespace.href] ||= {}
75
+ hash[attribute.namespace.href][attribute.name] = attribute.value
76
+ end
77
+ xml.xpath("//rdf:Description/*", NAMESPACES).each do |element|
78
+ hash[element.namespace.href] ||= {}
79
+ hash[element.namespace.href][element.name] = standalone_value(element, lang: nil)
80
+ end
81
+ end
82
+ end
83
+
84
+ private
85
+
86
+ def embedded_attribute(namespace, name)
87
+ if element = xml.at("//rdf:Description[@ns:#{name}]", "rdf" => NAMESPACES["rdf"], "ns" => namespace)
88
+ element.attribute_with_ns(name, namespace).text
89
+ end
90
+ end
91
+
92
+ def standalone_attribute(namespace, name, lang: nil)
93
+ if element = xml.xpath("//ns:#{name}", "ns" => namespace).first
94
+ standalone_value(element, lang: lang)
95
+ end
96
+ end
97
+
98
+ def standalone_value(element, lang:)
99
+ if alt_element = element.xpath("./rdf:Alt", NAMESPACES).first
100
+ alt_value(alt_element, lang: lang)
101
+ elsif array_element = element.xpath("./rdf:Bag | ./rdf:Seq", NAMESPACES).first
102
+ array_value(array_element)
103
+ else
104
+ raise "Don't know how to handle:\n#{element}"
105
+ end
106
+ end
107
+
108
+ def alt_value(element, lang:)
109
+ if lang && item = element.xpath("./rdf:li[@xml:lang=#{lang.inspect}]", NAMESPACES).first
110
+ item.text
111
+ elsif item = element.xpath(%{./rdf:li[@xml:lang="x-default"]}, NAMESPACES).first
112
+ item.text
113
+ elsif item = element.xpath("./rdf:li", NAMESPACES).first
114
+ item.text
115
+ end
116
+ end
117
+
118
+ def array_value(element)
119
+ element.xpath("./rdf:li", NAMESPACES).map(&:text)
120
+ end
121
+ end
122
+ end
@@ -0,0 +1,3 @@
1
+ module XMPR
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,72 @@
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:dc="http://purl.org/dc/elements/1.1/"
6
+ xmlns:Iptc4xmpCore="http://iptc.org/std/Iptc4xmpCore/1.0/xmlns/"
7
+ xmlns:photoshop="http://ns.adobe.com/photoshop/1.0/"
8
+ Iptc4xmpCore:Location="Miejsce"
9
+ photoshop:Category="Kategoria">
10
+ <dc:title>
11
+ <rdf:Alt>
12
+ <rdf:li xml:lang="x-default">Tytuł zdjęcia</rdf:li>
13
+ <rdf:li xml:lang="en-US">Something else</rdf:li>
14
+ </rdf:Alt>
15
+ </dc:title>
16
+ <dc:subject>
17
+ <rdf:Bag>
18
+ <rdf:li>Słowa kluczowe</rdf:li>
19
+ <rdf:li>Opis zdjęcia</rdf:li>
20
+ </rdf:Bag>
21
+ </dc:subject>
22
+ <dc:creator>
23
+ <rdf:Seq>
24
+ <rdf:li>John Doe</rdf:li>
25
+ <rdf:li>Jane Smith</rdf:li>
26
+ </rdf:Seq>
27
+ </dc:creator>
28
+ </rdf:Description>
29
+ </rdf:RDF>
30
+ </x:xmpmeta>
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
+
58
+
59
+
60
+
61
+
62
+
63
+
64
+
65
+
66
+
67
+
68
+
69
+
70
+
71
+
72
+ <?xpacket end="w"?>
@@ -0,0 +1,4 @@
1
+ $LOAD_PATH.unshift File.expand_path("../../lib", __FILE__)
2
+ require "xmpr"
3
+
4
+ require "minitest/autorun"
@@ -0,0 +1,37 @@
1
+ # encoding: UTF-8
2
+
3
+ require "test_helper"
4
+
5
+ class XMPRTest < MiniTest::Test
6
+ def xmp
7
+ XMPR.parse(File.read("test/fixtures/xmp.xml"))
8
+ end
9
+
10
+ def test_embedded_attribute
11
+ assert_equal "Kategoria", xmp["photoshop", "Category"]
12
+ end
13
+
14
+ def test_explicit_namespace
15
+ assert_equal "Miejsce", xmp["http://iptc.org/std/Iptc4xmpCore/1.0/xmlns/", "Location"]
16
+ end
17
+
18
+ def test_standalone_alt_attribute
19
+ assert_equal "Tytuł zdjęcia", xmp["dc", "title"]
20
+ end
21
+
22
+ def test_standalone_alt_attribute_with_lang
23
+ assert_equal "Something else", xmp["dc", "title", lang: "en-US"]
24
+ end
25
+
26
+ def test_standalone_bag_attribute
27
+ assert_equal ["Słowa kluczowe", "Opis zdjęcia"], xmp["dc", "subject"]
28
+ end
29
+
30
+ def test_standalone_seq_attribute
31
+ assert_equal ["John Doe", "Jane Smith"], xmp["dc", "creator"]
32
+ end
33
+
34
+ def test_to_hash
35
+ assert_equal({"http://www.w3.org/1999/02/22-rdf-syntax-ns#"=>{"about"=>""}, "http://iptc.org/std/Iptc4xmpCore/1.0/xmlns/"=>{"Location"=>"Miejsce"}, "http://ns.adobe.com/photoshop/1.0/"=>{"Category"=>"Kategoria"}, "http://purl.org/dc/elements/1.1/"=>{"title"=>"Tytuł zdjęcia", "subject"=>["Słowa kluczowe", "Opis zdjęcia"], "creator"=>["John Doe", "Jane Smith"]}}, xmp.to_hash)
36
+ end
37
+ end
metadata ADDED
@@ -0,0 +1,130 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: xmpr
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Samuel Cochran
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain:
11
+ - |
12
+ -----BEGIN CERTIFICATE-----
13
+ MIIDKDCCAhCgAwIBAgIBAzANBgkqhkiG9w0BAQUFADA6MQ0wCwYDVQQDDARzajI2
14
+ MRQwEgYKCZImiZPyLGQBGRYEc2oyNjETMBEGCgmSJomT8ixkARkWA2NvbTAeFw0x
15
+ NTAzMTcyMjUwMjZaFw0xNjAzMTYyMjUwMjZaMDoxDTALBgNVBAMMBHNqMjYxFDAS
16
+ BgoJkiaJk/IsZAEZFgRzajI2MRMwEQYKCZImiZPyLGQBGRYDY29tMIIBIjANBgkq
17
+ hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsr60Eo/ttCk8GMTMFiPr3GoYMIMFvLak
18
+ xSmTk9YGCB6UiEePB4THSSA5w6IPyeaCF/nWkDp3/BAam0eZMWG1IzYQB23TqIM0
19
+ 1xzcNRvFsn0aQoQ00k+sj+G83j3T5OOV5OZIlu8xAChMkQmiPd1NXc6uFv+Iacz7
20
+ kj+CMsI9YUFdNoU09QY0b+u+Rb6wDYdpyvN60YC30h0h1MeYbvYZJx/iZK4XY5zu
21
+ 4O/FL2ChjL2CPCpLZW55ShYyrzphWJwLOJe+FJ/ZBl6YXwrzQM9HKnt4titSNvyU
22
+ KzE3L63A3PZvExzLrN9u09kuWLLJfXB2sGOlw3n9t72rJiuBr3/OQQIDAQABozkw
23
+ NzAJBgNVHRMEAjAAMAsGA1UdDwQEAwIEsDAdBgNVHQ4EFgQU99dfRjEKFyczTeIz
24
+ m3ZsDWrNC80wDQYJKoZIhvcNAQEFBQADggEBAFxKLjiLkMLkUmdpsAzJad/t7Jo/
25
+ CGby/3n0WSXPBeZJfsnSdJ2qtG7iy/xqYDc1RjpKgX0RlMgeQRSE3ZDL/HZzBKDF
26
+ azaTgG9Zk1Quu59/79Z0Sltq07Z/IeccFl5j9M+1YS8VY2mOPi9g03OoOSRmhsMS
27
+ wpEF+zvJ0ESS5OPjtp6Sk4q1QYc0aVIthEznuVNMW6CPpTNhMAOFMaTC5AXCzJ3Q
28
+ 52G9HuhbVSTgE/I10H9qZBOE3qdP8ka/Fk0PUrux/DuUanNZgSKJokrQvRA4H9Au
29
+ WpPA7HJYV6msWQiukoBEhfQ2l6Fl2HUwntvX3MCcFNHeJJ5ETERp9alo88E=
30
+ -----END CERTIFICATE-----
31
+ date: 2015-12-18 00:00:00.000000000 Z
32
+ dependencies:
33
+ - !ruby/object:Gem::Dependency
34
+ name: nokogiri
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '1.6'
40
+ type: :runtime
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '1.6'
47
+ - !ruby/object:Gem::Dependency
48
+ name: bundler
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '1.10'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '1.10'
61
+ - !ruby/object:Gem::Dependency
62
+ name: rake
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: '10.0'
68
+ type: :development
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: '10.0'
75
+ - !ruby/object:Gem::Dependency
76
+ name: minitest
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ type: :development
83
+ prerelease: false
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ description: Parse XMP data extracted from an image into rich data types
90
+ email: sj26@sj26.com
91
+ executables: []
92
+ extensions: []
93
+ extra_rdoc_files: []
94
+ files:
95
+ - LICENSE
96
+ - README.md
97
+ - lib/xmpr.rb
98
+ - lib/xmpr/version.rb
99
+ - test/fixtures/xmp.xml
100
+ - test/test_helper.rb
101
+ - test/xmpr_test.rb
102
+ homepage: https://github.com/sj26/xmpr
103
+ licenses:
104
+ - MIT
105
+ metadata: {}
106
+ post_install_message:
107
+ rdoc_options: []
108
+ require_paths:
109
+ - lib
110
+ required_ruby_version: !ruby/object:Gem::Requirement
111
+ requirements:
112
+ - - "~>"
113
+ - !ruby/object:Gem::Version
114
+ version: '2.1'
115
+ required_rubygems_version: !ruby/object:Gem::Requirement
116
+ requirements:
117
+ - - ">="
118
+ - !ruby/object:Gem::Version
119
+ version: '0'
120
+ requirements: []
121
+ rubyforge_project:
122
+ rubygems_version: 2.4.5.1
123
+ signing_key:
124
+ specification_version: 4
125
+ summary: Parse XMP data
126
+ test_files:
127
+ - test/fixtures/xmp.xml
128
+ - test/test_helper.rb
129
+ - test/xmpr_test.rb
130
+ has_rdoc:
Binary file