# coding: utf-8
=begin
# post_xml.rb
# 2009-05-18.
# BloggerAPI POST Request で必要な XML の生成
<entry xmlns='http://www.w3.org/2005/Atom'>
<published>2009-06-01T00:00:00+09:00</published>
<app:control xmlns:app='http://www.w3.org/2007/app'>
<app:draft>yes</app:draft></app:control>
<title type='text'>test_title</title>
<category scheme='http://www.blogger.com/atom/ns#' term='Blogger'/>
<category scheme='http://www.blogger.com/atom/ns#' term='test'/>
<content type='xhtml'><div xmlns='http://www.w3.org/1999/xhtml'>
<p>xxx<a href='http://www.google.com'>google</a><br/><img src='ddd.png'/></p>
<pre><code>
def aaa
end
</code></pre>
<p>end.</p></div></content></entry>
# 実際は code element 以外,改行なし
=end
# You can redistribute it and/or modify it under the same terms as Ruby.
require "rexml/document"
require 'time'
module BloggerContentDiv
def setup_div
ary = @entry.content.strip.lines.to_a
return nil if ary.empty?
ary.each_with_index{|x,i|
to_tag(x)
tag_p if ary.size == i + 1
}
return @div
end
def to_tag(x)
on = {"<pre>"=>"pre","<blockquote>"=>"blockquote"}
off = {"</pre>"=>true,"</blockquote>"=>true}
if on[x.strip]
tag_p unless @str_plain.empty?
@tag = on[x.chop]
elsif off[x.strip]
my_tag
@tag = nil
else
@str_plain << x unless @tag
@str_tag << x if @tag
end
end
private
def tag_p
str = @str_plain.strip
return nil if str.empty?
@e_p = @div.add_element("p")
str.each_line{|w|
@m = /<(a)|<(img)|<(del)/.match(w)
@m ? sub_tag_p(w) : @e_p.add_text(w.strip)
@e_p.add_element("br") if /\n/.match(w)
}
@str_plain = ""
return @div
end
def sub_tag_p(line)
pre_str unless @m.pre_match.empty?
if @m[1] then tag_a(line)
elsif @m[2] then tag_img(line)
elsif @m[3] then tag_del(line)
end
s = /<.*?\/>/.match(line)
post_str(s) if s
end
def tag_del(line)
del = /<del>(.*?)<\/del>/.match(line)
@e_p.add_element("del").add_text(del[1])
end
def tag_img(line)
href = /<img\ssrc=["'](.*?)["']/.match(line)
alt = /alt=["'](.*?)["']/.match(line)
return nil unless href
img = @e_p.add_element("img",{'src'=>href[1]})
img.add_attribute({'alt'=>alt[1]}) if alt
end
def tag_a(line)
all = /<a\shref=["'](.*?)["']>(.*?)<\/a>/.match(line)
@e_p.add_element("a",{'href'=>all[1]}).add_text(all[2])
end
def pre_str
@e_p.add_text(@m.pre_match.chop)
end
def post_str(s)
@e_p.add_text(s.post_match.chop)
end
def my_tag
case @tag
when "pre" then tag_pre
when "blockquote" then tag_block
end
@str_tag = ""
end
def tag_pre
@div.add_text("\n")
str = @str_tag
e1 = @div.add_element("pre")
e2 = e1.add_element("code").add_text("\n")
e2.add_text(str)
@div.add_text("\n")
end
def tag_block
e1 = @div.add_element("blockquote")
e2 = e1.add_element("p")
@str_tag.strip.each_line{|w|
e2.add_text(w.strip)
e2.add_element("br") if /\n/.match(w)
}
end
end
class BloggerEntry
attr_reader :title, :content, :published, :category, :control
attr_accessor :editid, :updated
def initialize
@published = nil
@control = nil
@title = nil
@content = nil
@category = nil
# these value, after post request
@editid = nil
@updated = nil
end
def setup(h)
h.each{|k, v|
i = "@#{k}".downcase.to_sym
set_ins(i, v) if i_defined?(i)
}
return self
end
def to_xml_post
return BloggerXML.new(self).post_data
end
private
def set_ins(i,v)
self.instance_variable_set(i, v)
end
def i_defined?(i)
self.instance_variable_defined?(i)
end
end
class BloggerXML
include BloggerContentDiv
def initialize(entry)
@entry = entry
@str_plain = ""
@str_tag = ""
@tag = nil
end
def post_data
doc = REXML::Document.new()
doc << REXML::XMLDecl.new(version="1.0", encoding="utf-8" )
# entry
@e = doc.add_element("entry", {'xmlns'=>'http://www.w3.org/2005/Atom'})
# published
set_published
# App control element
set_control
# Title
@e.add_element("title", {'type'=>'text'}).add_text(@entry.title.strip)
# Category
set_category
# Content
content = @e.add_element("content", {'type'=>'xhtml'})
@div = content.add_element("div", {'xmlns'=>'http://www.w3.org/1999/xhtml'})
setup_div
return @e
end
private
def set_published
unless @entry.published
n = Time.now.iso8601.to_s
else
n = Time.parse(@entry.published).iso8601.to_s
end
@e.add_element("published").add_text(n.to_s)
end
def set_control
if @entry.control
ac = @e.add_element("app:control",
{'xmlns:app'=>'http://www.w3.org/2007/app'})
ac.add_element("app:draft").add_text("#{@entry.control}")
end
end
def set_category
@entry.category.split(",").to_a.each{|c|
@e.add_element("category",{"scheme"=>'http://www.blogger.com/atom/ns#', "term"=>"#{c}"})
}
end
end
#--- test
title = 'test_title'
content =<<EOF
xxxx<a href='http://www.google.com'>google</a>
<img src='ddd.png' alt='fff'>
<pre>
def aaa
end
</pre>
end.
EOF
category = "Blogger,test"
control = "yes"
h = {:title=>title, :content=>content, :category=>category, :control=>control, :published=>'2009-06-01'}
entry = BloggerEntry.new().setup(h)
puts data = entry.to_xml_post
#--- Start Post
# require 'gdata'
#begin
# blogID = 'xxxxxxxxxxxx'
# url = "http://www.blogger.com/feeds/#{blogID}/posts/default"
# client = GData::Client::Blogger.new
# client.source = sourcename
# clientlogin('username', 'password')
# client.post(url, data.to_s)
#rescue GData::Client::AuthorizationError => e
# print "gData error\n"
# print e.message
#end
content =<<EOF
中の pre は本当は小文字 < >で囲まれてる
修正
100 行目あたり
def pre_str
@e_p.add_text(@m.pre_match.chop)
@e_p.add_text(@m.pre_match)
end
def post_str(s)
@e_p.add_text(s.post_match.chop)
@e_p.add_text(s.post_match)
end