sitemap_generator 4.1.1 → 4.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +1 -1
- data/Gemfile.lock +3 -3
- data/README.md +6 -0
- data/VERSION +1 -1
- data/lib/sitemap_generator.rb +9 -1
- data/lib/sitemap_generator/builder/sitemap_file.rb +6 -6
- data/lib/sitemap_generator/builder/sitemap_url.rb +38 -29
- data/lib/sitemap_generator/link_set.rb +7 -5
- data/lib/sitemap_generator/sitemap_location.rb +1 -1
- data/lib/sitemap_generator/utilities.rb +11 -0
- data/spec/sitemap_generator/geo_sitemap_spec.rb +2 -2
- data/spec/sitemap_generator/link_set_spec.rb +25 -7
- data/spec/sitemap_generator/mobile_sitemap_spec.rb +2 -2
- data/spec/sitemap_generator/news_sitemap_spec.rb +2 -2
- data/spec/sitemap_generator/pagemap_sitemap_spec.rb +27 -20
- data/spec/sitemap_generator/sitemap_location_spec.rb +31 -0
- data/spec/sitemap_generator/utilities_spec.rb +10 -0
- data/spec/sitemap_generator/video_sitemap_spec.rb +11 -3
- data/spec/support/schemas/sitemap-video.xsd +245 -11
- data/spec/support/xml_macros.rb +17 -5
- metadata +4 -4
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: ./
|
3
3
|
specs:
|
4
|
-
sitemap_generator (4.
|
4
|
+
sitemap_generator (4.2)
|
5
5
|
builder
|
6
6
|
|
7
7
|
GEM
|
@@ -12,7 +12,7 @@ GEM
|
|
12
12
|
metaclass (0.0.1)
|
13
13
|
mocha (0.10.0)
|
14
14
|
metaclass (~> 0.0.1)
|
15
|
-
nokogiri (1.5.
|
15
|
+
nokogiri (1.5.10)
|
16
16
|
rake (10.0.4)
|
17
17
|
rspec (2.8.0)
|
18
18
|
rspec-core (~> 2.8.0)
|
@@ -29,7 +29,7 @@ PLATFORMS
|
|
29
29
|
DEPENDENCIES
|
30
30
|
builder
|
31
31
|
mocha
|
32
|
-
nokogiri
|
32
|
+
nokogiri (= 1.5.10)
|
33
33
|
rake
|
34
34
|
rspec
|
35
35
|
sitemap_generator!
|
data/README.md
CHANGED
@@ -105,6 +105,7 @@ That's it! Welcome to the future!
|
|
105
105
|
|
106
106
|
## Changelog
|
107
107
|
|
108
|
+
* v4.2: Update Google ping URL. Quote the ping URL in the output. Support Video `video:price` element ([#117][https://github.com/kjvarga/sitemap_generator/issues/117]). Support symbols as well as strings for most arguments to `add()` ([#113][https://github.com/kjvarga/sitemap_generator/issues/113]). Ensure that `public_path` and `sitemaps_path` end with a slash (`/`) ([#113][https://github.com/kjvarga/sitemap_generator/issues/118]).
|
108
109
|
* v4.1.1: Support setting the S3 region. Fixed bug where incorrect URL was being used in the ping to search engines - only affected sites with a single sitemap file and no index file. Output the URL being pinged in the verbose output. Test in Rails 4.
|
109
110
|
* v4.1.0: [PageMap sitemap][using_pagemaps] support. Tested with Rails 4 pre-release.
|
110
111
|
* v4.0.1: Add a post install message regarding the naming convention change.
|
@@ -912,6 +913,10 @@ end
|
|
912
913
|
* `:gallery_title` - Title attribute of the gallery location element
|
913
914
|
* `:uploader`
|
914
915
|
* `:uploader_info` - Info attribute of uploader element
|
916
|
+
* `:price` - Only one price supported at this time
|
917
|
+
* `:price_currency` - Required. In [ISO_4217][iso_4217] format.
|
918
|
+
* `:price_type` - Optional. `rent` or `own`
|
919
|
+
* `:price_resolution` - Optional. `HD` or `SD`
|
915
920
|
|
916
921
|
### Geo Sitemaps
|
917
922
|
|
@@ -1078,3 +1083,4 @@ Copyright (c) 2009 Karl Varga released under the MIT license
|
|
1078
1083
|
[ehoch]:https://github.com/ehoch
|
1079
1084
|
[alternate_links]:http://support.google.com/webmasters/bin/answer.py?hl=en&answer=2620865
|
1080
1085
|
[using_pagemaps]:https://developers.google.com/custom-search/docs/structured_data#pagemaps
|
1086
|
+
[iso_4217]:http://en.wikipedia.org/wiki/ISO_4217
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
4.
|
1
|
+
4.2.0
|
data/lib/sitemap_generator.rb
CHANGED
@@ -26,7 +26,15 @@ module SitemapGenerator
|
|
26
26
|
MAX_SITEMAP_IMAGES = 1_000 # max images per url
|
27
27
|
MAX_SITEMAP_NEWS = 1_000 # max news sitemap per index_file
|
28
28
|
MAX_SITEMAP_FILESIZE = SitemapGenerator::Numeric.new(10).megabytes # bytes
|
29
|
-
|
29
|
+
SCHEMAS = {
|
30
|
+
'geo' => 'http://www.google.com/geo/schemas/sitemap/1.0',
|
31
|
+
'image' => 'http://www.google.com/schemas/sitemap-image/1.1',
|
32
|
+
'mobile' => 'http://www.google.com/schemas/sitemap-mobile/1.0',
|
33
|
+
'news' => 'http://www.google.com/schemas/sitemap-news/0.9',
|
34
|
+
'pagemap' => 'http://www.google.com/schemas/sitemap-pagemap/1.0',
|
35
|
+
'video' => 'http://www.google.com/schemas/sitemap-video/1.1'
|
36
|
+
}
|
37
|
+
|
30
38
|
# Lazy-initialize the LinkSet instance
|
31
39
|
Sitemap = (Class.new do
|
32
40
|
def method_missing(*args, &block)
|
@@ -28,15 +28,15 @@ module SitemapGenerator
|
|
28
28
|
<?xml version="1.0" encoding="UTF-8"?>
|
29
29
|
<urlset
|
30
30
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
31
|
-
xmlns:image="http://www.google.com/schemas/sitemap-image/1.1"
|
32
31
|
xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9
|
33
32
|
http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd"
|
34
33
|
xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
|
35
|
-
xmlns:
|
36
|
-
xmlns:
|
37
|
-
xmlns:
|
38
|
-
xmlns:
|
39
|
-
xmlns:
|
34
|
+
xmlns:image="#{SitemapGenerator::SCHEMAS['image']}"
|
35
|
+
xmlns:video="#{SitemapGenerator::SCHEMAS['video']}"
|
36
|
+
xmlns:geo="#{SitemapGenerator::SCHEMAS['geo']}"
|
37
|
+
xmlns:news="#{SitemapGenerator::SCHEMAS['news']}"
|
38
|
+
xmlns:mobile="#{SitemapGenerator::SCHEMAS['mobile']}"
|
39
|
+
xmlns:pagemap="#{SitemapGenerator::SCHEMAS['pagemap']}"
|
40
40
|
xmlns:xhtml="http://www.w3.org/1999/xhtml"
|
41
41
|
>
|
42
42
|
HTML
|
@@ -72,72 +72,73 @@ module SitemapGenerator
|
|
72
72
|
builder.url do
|
73
73
|
builder.loc self[:loc]
|
74
74
|
builder.lastmod w3c_date(self[:lastmod]) if self[:lastmod]
|
75
|
-
builder.changefreq self[:changefreq]
|
75
|
+
builder.changefreq self[:changefreq].to_s if self[:changefreq]
|
76
76
|
builder.priority format_float(self[:priority]) if self[:priority]
|
77
77
|
|
78
78
|
unless SitemapGenerator::Utilities.blank?(self[:news])
|
79
79
|
news_data = self[:news]
|
80
80
|
builder.news:news do
|
81
81
|
builder.news:publication do
|
82
|
-
builder.news :name, news_data[:publication_name] if news_data[:publication_name]
|
83
|
-
builder.news :language, news_data[:publication_language] if news_data[:publication_language]
|
82
|
+
builder.news :name, news_data[:publication_name].to_s if news_data[:publication_name]
|
83
|
+
builder.news :language, news_data[:publication_language].to_s if news_data[:publication_language]
|
84
84
|
end
|
85
85
|
|
86
|
-
builder.news :access, news_data[:access] if news_data[:access]
|
87
|
-
builder.news :genres, news_data[:genres] if news_data[:genres]
|
86
|
+
builder.news :access, news_data[:access].to_s if news_data[:access]
|
87
|
+
builder.news :genres, news_data[:genres].to_s if news_data[:genres]
|
88
88
|
builder.news :publication_date, w3c_date(news_data[:publication_date]) if news_data[:publication_date]
|
89
|
-
builder.news :title, news_data[:title] if news_data[:title]
|
90
|
-
builder.news :keywords, news_data[:keywords] if news_data[:keywords]
|
91
|
-
builder.news :stock_tickers, news_data[:stock_tickers] if news_data[:stock_tickers]
|
89
|
+
builder.news :title, news_data[:title].to_s if news_data[:title]
|
90
|
+
builder.news :keywords, news_data[:keywords].to_s if news_data[:keywords]
|
91
|
+
builder.news :stock_tickers, news_data[:stock_tickers].to_s if news_data[:stock_tickers]
|
92
92
|
end
|
93
93
|
end
|
94
94
|
|
95
95
|
self[:images].each do |image|
|
96
96
|
builder.image:image do
|
97
97
|
builder.image :loc, image[:loc]
|
98
|
-
builder.image :caption, image[:caption] if image[:caption]
|
99
|
-
builder.image :geo_location, image[:geo_location] if image[:geo_location]
|
100
|
-
builder.image :title, image[:title] if image[:title]
|
101
|
-
builder.image :license, image[:license] if image[:license]
|
98
|
+
builder.image :caption, image[:caption].to_s if image[:caption]
|
99
|
+
builder.image :geo_location, image[:geo_location].to_s if image[:geo_location]
|
100
|
+
builder.image :title, image[:title].to_s if image[:title]
|
101
|
+
builder.image :license, image[:license].to_s if image[:license]
|
102
102
|
end
|
103
103
|
end
|
104
104
|
|
105
105
|
self[:videos].each do |video|
|
106
106
|
builder.video :video do
|
107
|
-
builder.video :thumbnail_loc, video[:thumbnail_loc]
|
108
|
-
builder.video :title, video[:title]
|
109
|
-
builder.video :description, video[:description]
|
110
|
-
builder.video :content_loc, video[:content_loc] if video[:content_loc]
|
107
|
+
builder.video :thumbnail_loc, video[:thumbnail_loc].to_s
|
108
|
+
builder.video :title, video[:title].to_s
|
109
|
+
builder.video :description, video[:description].to_s
|
110
|
+
builder.video :content_loc, video[:content_loc].to_s if video[:content_loc]
|
111
111
|
if video[:player_loc]
|
112
112
|
loc_attributes = { :allow_embed => yes_or_no_with_default(video[:allow_embed], true) }
|
113
|
-
loc_attributes[:autoplay] = video[:autoplay] if SitemapGenerator::Utilities.present?(video[:autoplay])
|
114
|
-
builder.video :player_loc, video[:player_loc], loc_attributes
|
113
|
+
loc_attributes[:autoplay] = video[:autoplay].to_s if SitemapGenerator::Utilities.present?(video[:autoplay])
|
114
|
+
builder.video :player_loc, video[:player_loc].to_s, loc_attributes
|
115
115
|
end
|
116
|
-
builder.video :duration, video[:duration] if video[:duration]
|
116
|
+
builder.video :duration, video[:duration].to_s if video[:duration]
|
117
117
|
builder.video :expiration_date, w3c_date(video[:expiration_date]) if video[:expiration_date]
|
118
118
|
builder.video :rating, format_float(video[:rating]) if video[:rating]
|
119
|
-
builder.video :view_count, video[:view_count] if video[:view_count]
|
119
|
+
builder.video :view_count, video[:view_count].to_s if video[:view_count]
|
120
120
|
builder.video :publication_date, w3c_date(video[:publication_date]) if video[:publication_date]
|
121
|
-
video[:tags].each {|tag| builder.video :tag, tag } if video[:tags]
|
122
|
-
builder.video :tag, video[:tag] if video[:tag]
|
123
|
-
builder.video :category, video[:category] if video[:category]
|
121
|
+
video[:tags].each {|tag| builder.video :tag, tag.to_s } if video[:tags]
|
122
|
+
builder.video :tag, video[:tag].to_s if video[:tag]
|
123
|
+
builder.video :category, video[:category].to_s if video[:category]
|
124
124
|
builder.video :family_friendly, yes_or_no_with_default(video[:family_friendly], true) if video.has_key?(:family_friendly)
|
125
|
-
builder.video :gallery_loc, video[:gallery_loc], :title => video[:gallery_title] if video[:gallery_loc]
|
125
|
+
builder.video :gallery_loc, video[:gallery_loc].to_s, :title => video[:gallery_title].to_s if video[:gallery_loc]
|
126
|
+
builder.video :price, video[:price].to_s, prepare_video_price_attribs(video) if SitemapGenerator::Utilities.present?(video[:price])
|
126
127
|
if video[:uploader]
|
127
|
-
builder.video :uploader, video[:uploader], video[:uploader_info] ? { :info => video[:uploader_info] } : {}
|
128
|
+
builder.video :uploader, video[:uploader].to_s, video[:uploader_info] ? { :info => video[:uploader_info].to_s } : {}
|
128
129
|
end
|
129
130
|
end
|
130
131
|
end
|
131
132
|
|
132
133
|
self[:alternates].each do |alternate|
|
133
134
|
rel = alternate[:nofollow] ? 'alternate nofollow' : 'alternate'
|
134
|
-
builder.xhtml :link, :rel => rel, :hreflang => alternate[:lang], :href => alternate[:href]
|
135
|
+
builder.xhtml :link, :rel => rel, :hreflang => alternate[:lang].to_s, :href => alternate[:href].to_s
|
135
136
|
end
|
136
137
|
|
137
138
|
unless SitemapGenerator::Utilities.blank?(self[:geo])
|
138
139
|
geo = self[:geo]
|
139
140
|
builder.geo :geo do
|
140
|
-
builder.geo :format, geo[:format] if geo[:format]
|
141
|
+
builder.geo :format, geo[:format].to_s if geo[:format]
|
141
142
|
end
|
142
143
|
end
|
143
144
|
|
@@ -148,9 +149,9 @@ module SitemapGenerator
|
|
148
149
|
unless SitemapGenerator::Utilities.blank?(self[:pagemap])
|
149
150
|
builder.pagemap :PageMap do
|
150
151
|
SitemapGenerator::Utilities.as_array(self[:pagemap][:dataobjects]).each do |dataobject|
|
151
|
-
builder.pagemap :DataObject, :type => dataobject[:type], :id => dataobject[:id] do
|
152
|
+
builder.pagemap :DataObject, :type => dataobject[:type].to_s, :id => dataobject[:id].to_s do
|
152
153
|
SitemapGenerator::Utilities.as_array(dataobject[:attributes]).each do |attribute|
|
153
|
-
builder.pagemap :Attribute, attribute[:value], :name => attribute[:name]
|
154
|
+
builder.pagemap :Attribute, attribute[:value].to_s, :name => attribute[:name].to_s
|
154
155
|
end
|
155
156
|
end
|
156
157
|
end
|
@@ -166,6 +167,14 @@ module SitemapGenerator
|
|
166
167
|
|
167
168
|
protected
|
168
169
|
|
170
|
+
def prepare_video_price_attribs(video)
|
171
|
+
attribs = {}
|
172
|
+
attribs[:currency] = video[:price_currency].to_s # required
|
173
|
+
attribs[:type] = video[:price_type] if SitemapGenerator::Utilities.present?(video[:price_type])
|
174
|
+
attribs[:resolution] = video[:price_resolution] if SitemapGenerator::Utilities.present?(video[:price_resolution])
|
175
|
+
attribs
|
176
|
+
end
|
177
|
+
|
169
178
|
def prepare_news(news)
|
170
179
|
SitemapGenerator::Utilities.assert_valid_keys(news, :publication_name, :publication_language, :publication_date, :genres, :access, :title, :keywords, :stock_tickers) unless news.empty?
|
171
180
|
news
|
@@ -34,7 +34,7 @@ module SitemapGenerator
|
|
34
34
|
set_options(opts)
|
35
35
|
if verbose
|
36
36
|
start_time = Time.now
|
37
|
-
puts "In #{sitemap_index.location.public_path}"
|
37
|
+
puts "In '#{sitemap_index.location.public_path}':"
|
38
38
|
end
|
39
39
|
interpreter.eval(:yield_sitemap => yield_sitemap?, &block)
|
40
40
|
finalize!
|
@@ -123,7 +123,7 @@ module SitemapGenerator
|
|
123
123
|
:include_index => false,
|
124
124
|
:filename => :sitemap,
|
125
125
|
:search_engines => {
|
126
|
-
:google => "http://www.google.com/webmasters/
|
126
|
+
:google => "http://www.google.com/webmasters/tools/ping?sitemap=%s",
|
127
127
|
:bing => "http://www.bing.com/webmaster/ping.aspx?siteMap=%s",
|
128
128
|
:sitemap_writer => "http://www.sitemapwriter.com/notify.php?crawler=all&url=%s"
|
129
129
|
},
|
@@ -285,7 +285,7 @@ module SitemapGenerator
|
|
285
285
|
index_url = CGI.escape(unescaped_url)
|
286
286
|
|
287
287
|
output("\n")
|
288
|
-
output("Pinging with URL #{unescaped_url}:")
|
288
|
+
output("Pinging with URL '#{unescaped_url}':")
|
289
289
|
search_engines.merge(engines).each do |engine, link|
|
290
290
|
link = link % index_url
|
291
291
|
name = Utilities.titleize(engine.to_s)
|
@@ -506,8 +506,10 @@ module SitemapGenerator
|
|
506
506
|
#
|
507
507
|
# Set to nil to use the current directory.
|
508
508
|
def public_path=(value)
|
509
|
-
@public_path = Pathname.new(value
|
510
|
-
|
509
|
+
@public_path = Pathname.new(SitemapGenerator::Utilities.append_slash(value))
|
510
|
+
if @public_path.relative?
|
511
|
+
@public_path = SitemapGenerator.app.root + @public_path
|
512
|
+
end
|
511
513
|
update_location_info(:public_path, @public_path)
|
512
514
|
@public_path
|
513
515
|
end
|
@@ -151,5 +151,16 @@ module SitemapGenerator
|
|
151
151
|
def falsy?(value)
|
152
152
|
['0', 0, 'f', 'false', false].include?(value)
|
153
153
|
end
|
154
|
+
|
155
|
+
# Append a slash to `path` if it does not already end in a slash.
|
156
|
+
# Returns a string. Expects a string or Pathname object.
|
157
|
+
def append_slash(path)
|
158
|
+
strpath = path.to_s
|
159
|
+
if strpath[-1] != nil && strpath[-1].chr != '/'
|
160
|
+
strpath + '/'
|
161
|
+
else
|
162
|
+
strpath
|
163
|
+
end
|
164
|
+
end
|
154
165
|
end
|
155
166
|
end
|
@@ -14,7 +14,7 @@ describe "SitemapGenerator" do
|
|
14
14
|
).to_xml
|
15
15
|
|
16
16
|
# Check that the options were parsed correctly
|
17
|
-
doc = Nokogiri::XML.parse("<root xmlns:geo='
|
17
|
+
doc = Nokogiri::XML.parse("<root xmlns:geo='#{SitemapGenerator::SCHEMAS['geo']}'>#{geo_xml_fragment}</root>")
|
18
18
|
url = doc.at_xpath("//url")
|
19
19
|
url.should_not be_nil
|
20
20
|
url.at_xpath("loc").text.should == loc
|
@@ -25,6 +25,6 @@ describe "SitemapGenerator" do
|
|
25
25
|
|
26
26
|
# Google's documentation and published schema don't match some valid elements may
|
27
27
|
# not validate.
|
28
|
-
xml_fragment_should_validate_against_schema(geo, '
|
28
|
+
xml_fragment_should_validate_against_schema(geo, 'sitemap-geo', 'xmlns:geo' => SitemapGenerator::SCHEMAS['geo'])
|
29
29
|
end
|
30
30
|
end
|
@@ -72,15 +72,26 @@ describe SitemapGenerator::LinkSet do
|
|
72
72
|
|
73
73
|
describe "sitemaps public_path" do
|
74
74
|
it "should default to public/" do
|
75
|
-
|
76
|
-
ls.
|
77
|
-
ls.
|
75
|
+
path = SitemapGenerator.app.root + 'public/'
|
76
|
+
ls.public_path.should == path
|
77
|
+
ls.sitemap.location.public_path.should == path
|
78
|
+
ls.sitemap_index.location.public_path.should == path
|
78
79
|
end
|
79
80
|
|
80
81
|
it "should change when the public_path is changed" do
|
82
|
+
path = SitemapGenerator.app.root + 'tmp/'
|
83
|
+
ls.public_path = 'tmp/'
|
84
|
+
ls.public_path.should == path
|
85
|
+
ls.sitemap.location.public_path.should == path
|
86
|
+
ls.sitemap_index.location.public_path.should == path
|
87
|
+
end
|
88
|
+
|
89
|
+
it "should append a slash to the path" do
|
90
|
+
path = SitemapGenerator.app.root + 'tmp/'
|
81
91
|
ls.public_path = 'tmp'
|
82
|
-
ls.
|
83
|
-
ls.
|
92
|
+
ls.public_path.should == path
|
93
|
+
ls.sitemap.location.public_path.should == path
|
94
|
+
ls.sitemap_index.location.public_path.should == path
|
84
95
|
end
|
85
96
|
end
|
86
97
|
|
@@ -98,6 +109,13 @@ describe SitemapGenerator::LinkSet do
|
|
98
109
|
ls.sitemap.location.url.should == 'http://one.com/sitemaps/sitemap.xml.gz'
|
99
110
|
ls.sitemap_index.location.url.should == 'http://one.com/sitemaps/sitemap.xml.gz'
|
100
111
|
end
|
112
|
+
|
113
|
+
it "should append a slash to the path" do
|
114
|
+
ls.default_host = 'http://one.com'
|
115
|
+
ls.sitemaps_path = 'sitemaps'
|
116
|
+
ls.sitemap.location.url.should == 'http://one.com/sitemaps/sitemap.xml.gz'
|
117
|
+
ls.sitemap_index.location.url.should == 'http://one.com/sitemaps/sitemap.xml.gz'
|
118
|
+
end
|
101
119
|
end
|
102
120
|
|
103
121
|
describe "sitemap_index_url" do
|
@@ -317,7 +335,7 @@ describe SitemapGenerator::LinkSet do
|
|
317
335
|
path = 'new/path'
|
318
336
|
group = ls.group(:sitemaps_path => path)
|
319
337
|
group.sitemaps_path.should == path
|
320
|
-
group.sitemap.location.sitemaps_path.to_s.should == path
|
338
|
+
group.sitemap.location.sitemaps_path.to_s.should == 'new/path/'
|
321
339
|
end
|
322
340
|
end
|
323
341
|
|
@@ -489,7 +507,7 @@ describe SitemapGenerator::LinkSet do
|
|
489
507
|
path = 'new/path'
|
490
508
|
ls.create(:sitemaps_path => path)
|
491
509
|
ls.sitemaps_path.should == path
|
492
|
-
ls.sitemap.location.sitemaps_path.to_s.should == path
|
510
|
+
ls.sitemap.location.sitemaps_path.to_s.should == 'new/path/'
|
493
511
|
end
|
494
512
|
|
495
513
|
it "should set the default_host" do
|
@@ -12,7 +12,7 @@ describe "SitemapGenerator" do
|
|
12
12
|
).to_xml
|
13
13
|
|
14
14
|
# Check that the options were parsed correctly
|
15
|
-
doc = Nokogiri::XML.parse("<root xmlns:mobile='
|
15
|
+
doc = Nokogiri::XML.parse("<root xmlns:mobile='#{SitemapGenerator::SCHEMAS['mobile']}'>#{mobile_xml_fragment}</root>")
|
16
16
|
url = doc.at_xpath("//url")
|
17
17
|
url.should_not be_nil
|
18
18
|
url.at_xpath("loc").text.should == loc
|
@@ -22,6 +22,6 @@ describe "SitemapGenerator" do
|
|
22
22
|
|
23
23
|
# Google's documentation and published schema don't match some valid elements may
|
24
24
|
# not validate.
|
25
|
-
xml_fragment_should_validate_against_schema(mobile, '
|
25
|
+
xml_fragment_should_validate_against_schema(mobile, 'sitemap-mobile', 'xmlns:mobile' => SitemapGenerator::SCHEMAS['mobile'])
|
26
26
|
end
|
27
27
|
end
|
@@ -20,7 +20,7 @@ describe "SitemapGenerator" do
|
|
20
20
|
}
|
21
21
|
}).to_xml
|
22
22
|
|
23
|
-
doc = Nokogiri::XML.parse("<root xmlns:news='
|
23
|
+
doc = Nokogiri::XML.parse("<root xmlns:news='#{SitemapGenerator::SCHEMAS['news']}'>#{news_xml_fragment}</root>")
|
24
24
|
|
25
25
|
url = doc.at_xpath("//url")
|
26
26
|
loc = url.at_xpath("loc")
|
@@ -37,6 +37,6 @@ describe "SitemapGenerator" do
|
|
37
37
|
news.at_xpath("//news:name").text.should == "Example"
|
38
38
|
news.at_xpath("//news:language").text.should == "en"
|
39
39
|
|
40
|
-
xml_fragment_should_validate_against_schema(news, '
|
40
|
+
xml_fragment_should_validate_against_schema(news, 'sitemap-news', 'xmlns:news' => SitemapGenerator::SCHEMAS['news'])
|
41
41
|
end
|
42
42
|
end
|
@@ -1,7 +1,8 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe "SitemapGenerator" do
|
4
|
-
|
4
|
+
let(:schema) { SitemapGenerator::SCHEMAS['pagemap'] }
|
5
|
+
|
5
6
|
it "should add the pagemap sitemap element" do
|
6
7
|
pagemap_xml_fragment = SitemapGenerator::Builder::SitemapUrl.new('my_page.html', {
|
7
8
|
:host => 'http://www.example.com',
|
@@ -9,42 +10,48 @@ describe "SitemapGenerator" do
|
|
9
10
|
:pagemap => {
|
10
11
|
:dataobjects => [
|
11
12
|
{
|
12
|
-
type
|
13
|
-
id
|
14
|
-
attributes
|
15
|
-
{name
|
16
|
-
{name
|
13
|
+
:type => 'document',
|
14
|
+
:id => 'hibachi',
|
15
|
+
:attributes => [
|
16
|
+
{:name => 'name', :value => 'Dragon'},
|
17
|
+
{:name => 'review', :value => 3.5},
|
17
18
|
]
|
18
19
|
},
|
19
20
|
{
|
20
|
-
type
|
21
|
-
attributes
|
22
|
-
{name
|
23
|
-
{name
|
21
|
+
:type => 'stats',
|
22
|
+
:attributes => [
|
23
|
+
{:name => 'installs', :value => 2000},
|
24
|
+
{:name => 'comments', :value => 200},
|
24
25
|
]
|
25
26
|
}
|
26
27
|
]
|
27
28
|
}
|
28
29
|
}).to_xml
|
29
30
|
|
31
|
+
# Nokogiri is a fickle beast. We have to add the namespace and define
|
32
|
+
# the prefix in order for XPath queries to work. And then we have to
|
33
|
+
# reingest because otherwise Nokogiri doesn't use it.
|
30
34
|
doc = Nokogiri::XML.parse(pagemap_xml_fragment)
|
31
|
-
|
35
|
+
doc.root.add_namespace_definition('pagemap', schema)
|
36
|
+
doc = Nokogiri::XML.parse(doc.to_xml)
|
37
|
+
|
32
38
|
url = doc.at_xpath("//url")
|
33
39
|
loc = url.at_xpath("loc")
|
34
40
|
loc.text.should == 'http://www.example.com/my_page.html'
|
35
|
-
|
36
|
-
pagemap =
|
37
|
-
pagemap.
|
38
|
-
pagemap.at_xpath('//DataObject')
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
41
|
+
|
42
|
+
pagemap = doc.at_xpath('//pagemap:PageMap', 'pagemap' => schema)
|
43
|
+
pagemap.element_children.count.should == 2
|
44
|
+
dataobject = pagemap.at_xpath('//pagemap:DataObject')
|
45
|
+
dataobject.attributes['type'].value.should == 'document'
|
46
|
+
dataobject.attributes['id'].value.should == 'hibachi'
|
47
|
+
dataobject.element_children.count.should == 2
|
48
|
+
first_attribute = dataobject.element_children.first
|
49
|
+
second_attribute = dataobject.element_children.last
|
43
50
|
first_attribute.text.should == 'Dragon'
|
44
51
|
first_attribute.attributes['name'].value.should == 'name'
|
45
52
|
second_attribute.text.should == '3.5'
|
46
53
|
second_attribute.attributes['name'].value.should == 'review'
|
47
54
|
|
48
|
-
xml_fragment_should_validate_against_schema(pagemap, '
|
55
|
+
xml_fragment_should_validate_against_schema(pagemap, 'sitemap-pagemap', 'xmlns:pagemap' => schema)
|
49
56
|
end
|
50
57
|
end
|
@@ -112,6 +112,37 @@ describe SitemapGenerator::SitemapLocation do
|
|
112
112
|
location.filesize
|
113
113
|
end
|
114
114
|
end
|
115
|
+
|
116
|
+
describe "public_path" do
|
117
|
+
it "should append a trailing slash" do
|
118
|
+
location = SitemapGenerator::SitemapLocation.new(:public_path => 'public/google')
|
119
|
+
location.public_path.to_s.should == 'public/google/'
|
120
|
+
location[:public_path] = 'new/path'
|
121
|
+
location.public_path.to_s.should == 'new/path/'
|
122
|
+
location[:public_path] = 'already/slashed/'
|
123
|
+
location.public_path.to_s.should == 'already/slashed/'
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
describe "sitemaps_path" do
|
128
|
+
it "should append a trailing slash" do
|
129
|
+
location = SitemapGenerator::SitemapLocation.new(:sitemaps_path => 'public/google')
|
130
|
+
location.sitemaps_path.to_s.should == 'public/google/'
|
131
|
+
location[:sitemaps_path] = 'new/path'
|
132
|
+
location.sitemaps_path.to_s.should == 'new/path/'
|
133
|
+
location[:sitemaps_path] = 'already/slashed/'
|
134
|
+
location.sitemaps_path.to_s.should == 'already/slashed/'
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
describe "url" do
|
139
|
+
it "should handle paths not ending in slash" do
|
140
|
+
location = SitemapGenerator::SitemapLocation.new(
|
141
|
+
:public_path => 'public/google', :filename => 'xxx',
|
142
|
+
:host => default_host, :sitemaps_path => 'sub/dir')
|
143
|
+
location.url.should == default_host + '/sub/dir/xxx'
|
144
|
+
end
|
145
|
+
end
|
115
146
|
end
|
116
147
|
|
117
148
|
describe SitemapGenerator::SitemapIndexLocation do
|
@@ -66,4 +66,14 @@ describe SitemapGenerator::Utilities do
|
|
66
66
|
SitemapGenerator::Utilities.as_array({}).should == [{}]
|
67
67
|
end
|
68
68
|
end
|
69
|
+
|
70
|
+
describe "append_slash" do
|
71
|
+
SitemapGenerator::Utilities.append_slash('').should == ''
|
72
|
+
SitemapGenerator::Utilities.append_slash(nil).should == ''
|
73
|
+
SitemapGenerator::Utilities.append_slash(Pathname.new('')).should == ''
|
74
|
+
SitemapGenerator::Utilities.append_slash('tmp').should == 'tmp/'
|
75
|
+
SitemapGenerator::Utilities.append_slash(Pathname.new('tmp')).should == 'tmp/'
|
76
|
+
SitemapGenerator::Utilities.append_slash('tmp/').should == 'tmp/'
|
77
|
+
SitemapGenerator::Utilities.append_slash(Pathname.new('tmp/')).should == 'tmp/'
|
78
|
+
end
|
69
79
|
end
|
@@ -28,7 +28,11 @@ describe "SitemapGenerator" do
|
|
28
28
|
:family_friendly => true,
|
29
29
|
:view_count => 123,
|
30
30
|
:duration => 456,
|
31
|
-
:rating => 0.499999999
|
31
|
+
:rating => 0.499999999,
|
32
|
+
:price => 123.45,
|
33
|
+
:price_currency => 'CAD',
|
34
|
+
:price_resolution => 'HD',
|
35
|
+
:price_type => 'rent'
|
32
36
|
}
|
33
37
|
end
|
34
38
|
|
@@ -42,7 +46,7 @@ describe "SitemapGenerator" do
|
|
42
46
|
|
43
47
|
# Return a Nokogiri document from the XML. The root of the document is the <URL> element.
|
44
48
|
def video_doc(xml)
|
45
|
-
Nokogiri::XML.parse("<root xmlns:video='
|
49
|
+
Nokogiri::XML.parse("<root xmlns:video='#{SitemapGenerator::SCHEMAS['video']}'>#{xml}</root>")
|
46
50
|
end
|
47
51
|
|
48
52
|
# Validate the contents of the video element
|
@@ -65,7 +69,11 @@ describe "SitemapGenerator" do
|
|
65
69
|
video_doc.at_xpath("video:player_loc").attribute('autoplay').text.should == video_options[:autoplay]
|
66
70
|
video_doc.at_xpath("video:uploader").text.should == video_options[:uploader]
|
67
71
|
video_doc.at_xpath("video:uploader").attribute("info").text.should == video_options[:uploader_info]
|
68
|
-
|
72
|
+
video_doc.at_xpath("video:price").text.should == video_options[:price].to_s
|
73
|
+
video_doc.at_xpath("video:price").attribute("resolution").text.should == video_options[:price_resolution].to_s
|
74
|
+
video_doc.at_xpath("video:price").attribute("type").text.should == video_options[:price_type].to_s
|
75
|
+
video_doc.at_xpath("video:price").attribute("currency").text.should == video_options[:price_currency].to_s
|
76
|
+
xml_fragment_should_validate_against_schema(video_doc, 'sitemap-video', 'xmlns:video' => SitemapGenerator::SCHEMAS['video'])
|
69
77
|
end
|
70
78
|
|
71
79
|
it "should add a valid video sitemap element" do
|
@@ -50,9 +50,19 @@
|
|
50
50
|
</xsd:restriction>
|
51
51
|
</xsd:simpleType>
|
52
52
|
|
53
|
-
<xsd:simpleType name="
|
54
|
-
<xsd:
|
55
|
-
<xsd:
|
53
|
+
<xsd:simpleType name="tPlatformList">
|
54
|
+
<xsd:annotation>
|
55
|
+
<xsd:documentation>
|
56
|
+
Space-separated platform names.
|
57
|
+
|
58
|
+
Platform names:
|
59
|
+
web - desktop and laptop browsers.
|
60
|
+
mobile - mobile devices such as phones and tablets.
|
61
|
+
tv - tv platforms such as GoogleTV.
|
62
|
+
</xsd:documentation>
|
63
|
+
</xsd:annotation>
|
64
|
+
<xsd:restriction base="xsd:string">
|
65
|
+
<xsd:pattern value="((web|mobile|tv)( (web|mobile|tv))*)?"/>
|
56
66
|
</xsd:restriction>
|
57
67
|
</xsd:simpleType>
|
58
68
|
|
@@ -63,11 +73,12 @@
|
|
63
73
|
<xsd:annotation>
|
64
74
|
<xsd:documentation>
|
65
75
|
A URL pointing to the URL for the video thumbnail image file. We can
|
66
|
-
accept most image sizes/types but recommend your
|
67
|
-
120x90 pixels in .jpg, .png, or. gif formats.
|
76
|
+
accept most image sizes/types but recommend your thumbnails are at
|
77
|
+
least 120x90 pixels in .jpg, .png, or. gif formats.
|
68
78
|
</xsd:documentation>
|
69
79
|
</xsd:annotation>
|
70
80
|
</xsd:element>
|
81
|
+
|
71
82
|
<xsd:element name="title">
|
72
83
|
<xsd:annotation>
|
73
84
|
<xsd:documentation>
|
@@ -80,6 +91,7 @@
|
|
80
91
|
</xsd:restriction>
|
81
92
|
</xsd:simpleType>
|
82
93
|
</xsd:element>
|
94
|
+
|
83
95
|
<xsd:element name="description">
|
84
96
|
<xsd:annotation>
|
85
97
|
<xsd:documentation>
|
@@ -92,6 +104,7 @@
|
|
92
104
|
</xsd:restriction>
|
93
105
|
</xsd:simpleType>
|
94
106
|
</xsd:element>
|
107
|
+
|
95
108
|
<xsd:element name="content_loc" minOccurs="0" type="xsd:anyURI">
|
96
109
|
<xsd:annotation>
|
97
110
|
<xsd:documentation>
|
@@ -107,6 +120,7 @@
|
|
107
120
|
</xsd:documentation>
|
108
121
|
</xsd:annotation>
|
109
122
|
</xsd:element>
|
123
|
+
|
110
124
|
<xsd:element name="player_loc" minOccurs="0">
|
111
125
|
<xsd:annotation>
|
112
126
|
<xsd:documentation>
|
@@ -148,6 +162,7 @@
|
|
148
162
|
</xsd:simpleContent>
|
149
163
|
</xsd:complexType>
|
150
164
|
</xsd:element>
|
165
|
+
|
151
166
|
<xsd:element name="duration" minOccurs="0">
|
152
167
|
<xsd:annotation>
|
153
168
|
<xsd:documentation>
|
@@ -160,6 +175,7 @@
|
|
160
175
|
</xsd:restriction>
|
161
176
|
</xsd:simpleType>
|
162
177
|
</xsd:element>
|
178
|
+
|
163
179
|
<xsd:element name="expiration_date" minOccurs="0">
|
164
180
|
<xsd:annotation>
|
165
181
|
<xsd:documentation>
|
@@ -181,6 +197,7 @@
|
|
181
197
|
</xsd:union>
|
182
198
|
</xsd:simpleType>
|
183
199
|
</xsd:element>
|
200
|
+
|
184
201
|
<xsd:element name="rating" minOccurs="0">
|
185
202
|
<xsd:annotation>
|
186
203
|
<xsd:documentation>
|
@@ -194,6 +211,7 @@
|
|
194
211
|
</xsd:restriction>
|
195
212
|
</xsd:simpleType>
|
196
213
|
</xsd:element>
|
214
|
+
|
197
215
|
<xsd:element name="content_segment_loc"
|
198
216
|
minOccurs="0"
|
199
217
|
maxOccurs="unbounded">
|
@@ -231,6 +249,7 @@
|
|
231
249
|
</xsd:simpleContent>
|
232
250
|
</xsd:complexType>
|
233
251
|
</xsd:element>
|
252
|
+
|
234
253
|
<xsd:element name="view_count"
|
235
254
|
minOccurs="0"
|
236
255
|
type="xsd:nonNegativeInteger">
|
@@ -240,6 +259,7 @@
|
|
240
259
|
</xsd:documentation>
|
241
260
|
</xsd:annotation>
|
242
261
|
</xsd:element>
|
262
|
+
|
243
263
|
<xsd:element name="publication_date" minOccurs="0">
|
244
264
|
<xsd:annotation>
|
245
265
|
<xsd:documentation>
|
@@ -260,6 +280,7 @@
|
|
260
280
|
</xsd:union>
|
261
281
|
</xsd:simpleType>
|
262
282
|
</xsd:element>
|
283
|
+
|
263
284
|
<xsd:element name="tag" type="xsd:string" minOccurs="0" maxOccurs="32">
|
264
285
|
<xsd:annotation>
|
265
286
|
<xsd:documentation>
|
@@ -273,10 +294,11 @@
|
|
273
294
|
</xsd:documentation>
|
274
295
|
</xsd:annotation>
|
275
296
|
</xsd:element>
|
297
|
+
|
276
298
|
<xsd:element name="category" minOccurs="0">
|
277
299
|
<xsd:annotation>
|
278
300
|
<xsd:documentation>
|
279
|
-
The video's category
|
301
|
+
The video's category - for example, cooking. In general, categories
|
280
302
|
are broad groupings of content by subject. For example, a site about
|
281
303
|
cooking could have categories for Broiling, Baking, and Grilling.
|
282
304
|
</xsd:documentation>
|
@@ -287,6 +309,7 @@
|
|
287
309
|
</xsd:restriction>
|
288
310
|
</xsd:simpleType>
|
289
311
|
</xsd:element>
|
312
|
+
|
290
313
|
<xsd:element name="family_friendly" minOccurs="0" type="tYesNo">
|
291
314
|
<xsd:annotation>
|
292
315
|
<xsd:documentation>
|
@@ -295,6 +318,7 @@
|
|
295
318
|
</xsd:documentation>
|
296
319
|
</xsd:annotation>
|
297
320
|
</xsd:element>
|
321
|
+
|
298
322
|
<xsd:element name="restriction" minOccurs="0">
|
299
323
|
<xsd:annotation>
|
300
324
|
<xsd:documentation>
|
@@ -324,6 +348,7 @@
|
|
324
348
|
</xsd:simpleContent>
|
325
349
|
</xsd:complexType>
|
326
350
|
</xsd:element>
|
351
|
+
|
327
352
|
<xsd:element name="gallery_loc" minOccurs="0">
|
328
353
|
<xsd:annotation>
|
329
354
|
<xsd:documentation>
|
@@ -345,21 +370,27 @@
|
|
345
370
|
</xsd:simpleContent>
|
346
371
|
</xsd:complexType>
|
347
372
|
</xsd:element>
|
373
|
+
|
348
374
|
<xsd:element name="price" minOccurs="0" maxOccurs="unbounded">
|
349
375
|
<xsd:annotation>
|
350
376
|
<xsd:documentation>
|
351
377
|
The price to download or view the video. More than one
|
352
378
|
<video:price> element can be listed (for example, in order to
|
353
|
-
specify various currencies).
|
379
|
+
specify various currencies). The price value must either be a
|
380
|
+
non-negative decimal or be empty. If a price value is specified, the
|
381
|
+
currency attribute is required. If no price value is specified, the
|
382
|
+
type attribute must be valid and present. The resolution attribute
|
383
|
+
is optional.
|
354
384
|
</xsd:documentation>
|
355
385
|
</xsd:annotation>
|
356
386
|
<xsd:complexType>
|
357
387
|
<xsd:simpleContent>
|
358
|
-
<xsd:extension base="
|
359
|
-
<xsd:attribute name="currency"
|
388
|
+
<xsd:extension base="xsd:string">
|
389
|
+
<xsd:attribute name="currency">
|
360
390
|
<xsd:annotation>
|
361
391
|
<xsd:documentation>
|
362
|
-
The currency in ISO 4217 format.
|
392
|
+
The currency in ISO 4217 format. This attribute is required
|
393
|
+
if a value is given for price.
|
363
394
|
</xsd:documentation>
|
364
395
|
</xsd:annotation>
|
365
396
|
<xsd:simpleType>
|
@@ -368,10 +399,42 @@
|
|
368
399
|
</xsd:restriction>
|
369
400
|
</xsd:simpleType>
|
370
401
|
</xsd:attribute>
|
402
|
+
<xsd:attribute name="type">
|
403
|
+
<xsd:annotation>
|
404
|
+
<xsd:documentation>
|
405
|
+
The type (purchase or rent) of price. This value is required
|
406
|
+
if there is no value given for price.
|
407
|
+
</xsd:documentation>
|
408
|
+
</xsd:annotation>
|
409
|
+
<xsd:simpleType>
|
410
|
+
<xsd:restriction base="xsd:string">
|
411
|
+
<xsd:enumeration value="purchase"/>
|
412
|
+
<xsd:enumeration value="PURCHASE"/>
|
413
|
+
<xsd:enumeration value="rent"/>
|
414
|
+
<xsd:enumeration value="RENT"/>
|
415
|
+
</xsd:restriction>
|
416
|
+
</xsd:simpleType>
|
417
|
+
</xsd:attribute>
|
418
|
+
<xsd:attribute name="resolution">
|
419
|
+
<xsd:annotation>
|
420
|
+
<xsd:documentation>
|
421
|
+
The resolution of the video at this price (SD or HD).
|
422
|
+
</xsd:documentation>
|
423
|
+
</xsd:annotation>
|
424
|
+
<xsd:simpleType>
|
425
|
+
<xsd:restriction base="xsd:string">
|
426
|
+
<xsd:enumeration value="sd"/>
|
427
|
+
<xsd:enumeration value="SD"/>
|
428
|
+
<xsd:enumeration value="hd"/>
|
429
|
+
<xsd:enumeration value="HD"/>
|
430
|
+
</xsd:restriction>
|
431
|
+
</xsd:simpleType>
|
432
|
+
</xsd:attribute>
|
371
433
|
</xsd:extension>
|
372
434
|
</xsd:simpleContent>
|
373
435
|
</xsd:complexType>
|
374
436
|
</xsd:element>
|
437
|
+
|
375
438
|
<xsd:element name="requires_subscription" minOccurs="0" type="tYesNo">
|
376
439
|
<xsd:annotation>
|
377
440
|
<xsd:documentation>
|
@@ -380,6 +443,7 @@
|
|
380
443
|
</xsd:documentation>
|
381
444
|
</xsd:annotation>
|
382
445
|
</xsd:element>
|
446
|
+
|
383
447
|
<xsd:element name="uploader" minOccurs="0">
|
384
448
|
<xsd:annotation>
|
385
449
|
<xsd:documentation>
|
@@ -402,8 +466,178 @@
|
|
402
466
|
</xsd:simpleContent>
|
403
467
|
</xsd:complexType>
|
404
468
|
</xsd:element>
|
469
|
+
|
470
|
+
<xsd:element name="tvshow" minOccurs="0">
|
471
|
+
<xsd:annotation>
|
472
|
+
<xsd:documentation>
|
473
|
+
Encloses all information about a single TV video.
|
474
|
+
</xsd:documentation>
|
475
|
+
</xsd:annotation>
|
476
|
+
<xsd:complexType>
|
477
|
+
<xsd:sequence>
|
478
|
+
<xsd:element name="show_title" type="xsd:string">
|
479
|
+
<xsd:annotation>
|
480
|
+
<xsd:documentation>
|
481
|
+
The title of the TV show. This should be the same for all
|
482
|
+
episodes from the same series.
|
483
|
+
</xsd:documentation>
|
484
|
+
</xsd:annotation>
|
485
|
+
</xsd:element>
|
486
|
+
<xsd:element name="video_type">
|
487
|
+
<xsd:annotation>
|
488
|
+
<xsd:documentation>
|
489
|
+
Describes the relationship of the video to the specified
|
490
|
+
TV show/episode.
|
491
|
+
</xsd:documentation>
|
492
|
+
</xsd:annotation>
|
493
|
+
<xsd:simpleType>
|
494
|
+
<xsd:restriction base="xsd:string">
|
495
|
+
<!-- Complete episode -->
|
496
|
+
<xsd:enumeration value="full"/>
|
497
|
+
<!-- Episode promo -->
|
498
|
+
<xsd:enumeration value="preview"/>
|
499
|
+
<!-- Episode clip -->
|
500
|
+
<xsd:enumeration value="clip"/>
|
501
|
+
<!-- Interview -->
|
502
|
+
<xsd:enumeration value="interview"/>
|
503
|
+
<!-- News related to the content -->
|
504
|
+
<xsd:enumeration value="news"/>
|
505
|
+
<!-- If none of the above options accurately describe
|
506
|
+
the relationship -->
|
507
|
+
<xsd:enumeration value="other"/>
|
508
|
+
</xsd:restriction>
|
509
|
+
</xsd:simpleType>
|
510
|
+
</xsd:element>
|
511
|
+
<xsd:element name="episode_title" type="xsd:string" minOccurs="0">
|
512
|
+
<xsd:annotation>
|
513
|
+
<xsd:documentation>
|
514
|
+
The title of the episode—for example, "Flesh and Bone" is the
|
515
|
+
title of the Season 1, Episode 8 episode of Battlestar
|
516
|
+
Galactica. This tag is not necessary if the video is not
|
517
|
+
related to a specific episode (for example, if it's a trailer
|
518
|
+
for an entire series or season).
|
519
|
+
</xsd:documentation>
|
520
|
+
</xsd:annotation>
|
521
|
+
</xsd:element>
|
522
|
+
<xsd:element name="season_number" minOccurs="0">
|
523
|
+
<xsd:annotation>
|
524
|
+
<xsd:documentation>
|
525
|
+
Only for shows with a per-season schedule.
|
526
|
+
</xsd:documentation>
|
527
|
+
</xsd:annotation>
|
528
|
+
<xsd:simpleType>
|
529
|
+
<xsd:restriction base="xsd:integer">
|
530
|
+
<xsd:minInclusive value="1"/>
|
531
|
+
</xsd:restriction>
|
532
|
+
</xsd:simpleType>
|
533
|
+
</xsd:element>
|
534
|
+
<xsd:element name="episode_number" minOccurs="0">
|
535
|
+
<xsd:annotation>
|
536
|
+
<xsd:documentation>
|
537
|
+
The episode number in number format. For TV shoes with a
|
538
|
+
per-season schedule, the first episode of each series should
|
539
|
+
be numbered 1.
|
540
|
+
</xsd:documentation>
|
541
|
+
</xsd:annotation>
|
542
|
+
<xsd:simpleType>
|
543
|
+
<xsd:restriction base="xsd:integer">
|
544
|
+
<xsd:minInclusive value="1"/>
|
545
|
+
</xsd:restriction>
|
546
|
+
</xsd:simpleType>
|
547
|
+
</xsd:element>
|
548
|
+
<xsd:element name="premier_date" minOccurs="0">
|
549
|
+
<xsd:annotation>
|
550
|
+
<xsd:documentation>
|
551
|
+
The date the content of the video was first broadcast, in
|
552
|
+
W3C format (for example, 2010-11-05.)
|
553
|
+
</xsd:documentation>
|
554
|
+
</xsd:annotation>
|
555
|
+
<xsd:simpleType>
|
556
|
+
<xsd:union>
|
557
|
+
<xsd:simpleType>
|
558
|
+
<xsd:restriction base="xsd:date"/>
|
559
|
+
</xsd:simpleType>
|
560
|
+
<xsd:simpleType>
|
561
|
+
<xsd:restriction base="xsd:dateTime"/>
|
562
|
+
</xsd:simpleType>
|
563
|
+
</xsd:union>
|
564
|
+
</xsd:simpleType>
|
565
|
+
</xsd:element>
|
566
|
+
</xsd:sequence>
|
567
|
+
</xsd:complexType>
|
568
|
+
</xsd:element>
|
569
|
+
|
570
|
+
<xsd:element name="platform" minOccurs="0">
|
571
|
+
<xsd:annotation>
|
572
|
+
<xsd:documentation>
|
573
|
+
A list of platforms where the video may or may not be played.
|
574
|
+
If there is no <video:platform> tag, it is assumed that
|
575
|
+
the video can be played on all platforms.
|
576
|
+
</xsd:documentation>
|
577
|
+
</xsd:annotation>
|
578
|
+
<xsd:complexType>
|
579
|
+
<xsd:simpleContent>
|
580
|
+
<xsd:extension base="tPlatformList">
|
581
|
+
<xsd:attribute name="relationship" use="required">
|
582
|
+
<xsd:annotation>
|
583
|
+
<xsd:documentation>
|
584
|
+
Attribute "relationship" specifies whether the video is
|
585
|
+
restricted or permitted for the specified platforms.
|
586
|
+
</xsd:documentation>
|
587
|
+
</xsd:annotation>
|
588
|
+
<xsd:simpleType>
|
589
|
+
<xsd:restriction base="xsd:string">
|
590
|
+
<xsd:enumeration value="allow"/>
|
591
|
+
<xsd:enumeration value="deny"/>
|
592
|
+
</xsd:restriction>
|
593
|
+
</xsd:simpleType>
|
594
|
+
</xsd:attribute>
|
595
|
+
</xsd:extension>
|
596
|
+
</xsd:simpleContent>
|
597
|
+
</xsd:complexType>
|
598
|
+
</xsd:element>
|
599
|
+
|
600
|
+
<xsd:element name="live" minOccurs="0" type="tYesNo">
|
601
|
+
<xsd:annotation>
|
602
|
+
<xsd:documentation>
|
603
|
+
Whether the video is a live internet broadcast.
|
604
|
+
</xsd:documentation>
|
605
|
+
</xsd:annotation>
|
606
|
+
</xsd:element>
|
607
|
+
|
608
|
+
<xsd:element name="id" minOccurs="0" maxOccurs="unbounded">
|
609
|
+
<xsd:annotation>
|
610
|
+
<xsd:documentation>
|
611
|
+
An unambiguous identifier for the video within a given
|
612
|
+
identification context.
|
613
|
+
</xsd:documentation>
|
614
|
+
</xsd:annotation>
|
615
|
+
<xsd:complexType>
|
616
|
+
<xsd:simpleContent>
|
617
|
+
<xsd:extension base="xsd:string">
|
618
|
+
<xsd:attribute name="type" use="required">
|
619
|
+
<xsd:annotation>
|
620
|
+
<xsd:documentation>
|
621
|
+
The identification context.
|
622
|
+
</xsd:documentation>
|
623
|
+
</xsd:annotation>
|
624
|
+
<xsd:simpleType>
|
625
|
+
<xsd:restriction base="xsd:string">
|
626
|
+
<xsd:enumeration value="tms:series"/>
|
627
|
+
<xsd:enumeration value="tms:program"/>
|
628
|
+
<xsd:enumeration value="rovi:series"/>
|
629
|
+
<xsd:enumeration value="rovi:program"/>
|
630
|
+
<xsd:enumeration value="freebase"/>
|
631
|
+
<xsd:enumeration value="url"/>
|
632
|
+
</xsd:restriction>
|
633
|
+
</xsd:simpleType>
|
634
|
+
</xsd:attribute>
|
635
|
+
</xsd:extension>
|
636
|
+
</xsd:simpleContent>
|
637
|
+
</xsd:complexType>
|
638
|
+
</xsd:element>
|
405
639
|
</xsd:sequence>
|
406
640
|
</xsd:complexType>
|
407
641
|
</xsd:element>
|
408
642
|
|
409
|
-
</xsd:schema>
|
643
|
+
</xsd:schema>
|
data/spec/support/xml_macros.rb
CHANGED
@@ -8,6 +8,10 @@ module XmlMacros
|
|
8
8
|
end
|
9
9
|
end
|
10
10
|
|
11
|
+
# Validate XML against a local schema file.
|
12
|
+
#
|
13
|
+
# `schema_name` gives the name of the schema file to validate against. The schema
|
14
|
+
# file is looked for in `spec/support/schemas/<schema_name>.xsd`.
|
11
15
|
def xml_data_should_validate_against_schema(xml, schema_name)
|
12
16
|
xml = xml.is_a?(String) ? xml : xml.to_s
|
13
17
|
doc = Nokogiri::XML(xml)
|
@@ -26,15 +30,23 @@ module XmlMacros
|
|
26
30
|
#
|
27
31
|
# Element 'video': No matching global declaration available for the validation root.
|
28
32
|
#
|
29
|
-
# <tt>
|
30
|
-
# <tt>
|
33
|
+
# <tt>xml</tt> The XML fragment
|
34
|
+
# <tt>schema_name</tt> the name of the schema file to validate against. The schema
|
35
|
+
# file is looked for in `spec/support/schemas/<schema_name>.xsd`.
|
36
|
+
# <tt>xmlns</tt> A hash with only one key which gives the XML namespace and associated
|
37
|
+
# URI. Sometimes one needs to specify a prefix to the namespace, in which case this would
|
38
|
+
# look like: 'xmlns:video' => 'http://www.google.com/schemas/sitemap-video/1.1'
|
31
39
|
#
|
32
40
|
# Example:
|
33
|
-
#
|
34
|
-
|
41
|
+
# xml_fragment_should_validate_against_schema('<video/>', 'sitemap-video', 'xmlns:video' => 'http://www.google.com/schemas/sitemap-video/1.1')
|
42
|
+
#
|
43
|
+
# This validates the given XML using the spec/support/schemas/sitemap-video.xsd`
|
44
|
+
# schema. The XML namespace `xmlns:video='http://www.google.com/schemas/sitemap-video/1.1'` is automatically
|
45
|
+
# added to the root element for you.
|
46
|
+
def xml_fragment_should_validate_against_schema(xml, schema_name, xmlns={})
|
35
47
|
xml = xml.is_a?(String) ? xml : xml.to_s
|
36
48
|
doc = Nokogiri::XML(xml)
|
37
|
-
doc.root[
|
49
|
+
doc.root.send(:[]=, *xmlns.first)
|
38
50
|
xml_data_should_validate_against_schema(doc, schema_name)
|
39
51
|
end
|
40
52
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sitemap_generator
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.
|
4
|
+
version: 4.2.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-08-16 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: mocha
|
@@ -183,7 +183,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
183
183
|
version: '0'
|
184
184
|
segments:
|
185
185
|
- 0
|
186
|
-
hash:
|
186
|
+
hash: 629438297049129393
|
187
187
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
188
188
|
none: false
|
189
189
|
requirements:
|
@@ -192,7 +192,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
192
192
|
version: '0'
|
193
193
|
segments:
|
194
194
|
- 0
|
195
|
-
hash:
|
195
|
+
hash: 629438297049129393
|
196
196
|
requirements: []
|
197
197
|
rubyforge_project:
|
198
198
|
rubygems_version: 1.8.25
|