kwaff 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/COPYING +340 -0
- data/ChangeLog.txt +118 -0
- data/README.txt +96 -0
- data/bin/kwaff +131 -0
- data/doc/docstyle.css +307 -0
- data/doc/examples.html +1283 -0
- data/doc/users-guide.html +395 -0
- data/examples/Makefile +17 -0
- data/examples/ant/Makefile +7 -0
- data/examples/ant/build.kwaff +57 -0
- data/examples/hibernate/AuctionItem.hbm.kwaff +45 -0
- data/examples/hibernate/Bid.hbm.kwaff +42 -0
- data/examples/hibernate/Makefile +9 -0
- data/examples/hibernate/User.hbm.kwaff +65 -0
- data/examples/hibernate/hibernate.cfg.kwaff +17 -0
- data/examples/seasar2/Makefile +9 -0
- data/examples/seasar2/seasar2.kwaff +62 -0
- data/examples/servlet/Makefile +9 -0
- data/examples/servlet/web.kwaff +37 -0
- data/examples/spring/Makefile +9 -0
- data/examples/spring/applicationContext.kwaff +147 -0
- data/examples/xhtml/Makefile +9 -0
- data/examples/xhtml/README.kwaff +84 -0
- data/examples/xi/Makefile +9 -0
- data/examples/xi/bbs.kwaff +58 -0
- data/lib/kwaff.rb +85 -0
- data/lib/kwaff/doctype.rb +124 -0
- data/lib/kwaff/doctypes.yaml +138 -0
- data/lib/kwaff/errors.rb +26 -0
- data/lib/kwaff/node.rb +101 -0
- data/lib/kwaff/optparse.rb +101 -0
- data/lib/kwaff/orderedhash.rb +56 -0
- data/lib/kwaff/parser.rb +342 -0
- data/lib/kwaff/rexml.rb +394 -0
- data/lib/kwaff/translator.rb +275 -0
- data/setup.rb +1331 -0
- data/test/ex101.exp +10 -0
- data/test/ex101.in +8 -0
- data/test/ex102.exp +14 -0
- data/test/ex102.in +16 -0
- data/test/ex103.exp +13 -0
- data/test/ex103.in +13 -0
- data/test/ex104.exp +24 -0
- data/test/ex104.in +24 -0
- data/test/ex105.exp +12 -0
- data/test/ex105.in +18 -0
- data/test/ex106.exp +22 -0
- data/test/ex106.in +21 -0
- data/test/ex107.exp +14 -0
- data/test/ex107.in +14 -0
- data/test/ex111.exp +7 -0
- data/test/ex111.in +13 -0
- data/test/ex112.exp +15 -0
- data/test/ex112.in +16 -0
- data/test/ex113.exp +23 -0
- data/test/ex113.in +22 -0
- data/test/ex114.exp +12 -0
- data/test/ex114.in +17 -0
- data/test/ex115.exp +9 -0
- data/test/ex115.in +12 -0
- data/test/ex121.exp +10 -0
- data/test/ex121.in +8 -0
- data/test/ex122.exp +10 -0
- data/test/ex122.in +8 -0
- data/test/ex301.exp +13 -0
- data/test/ex301.in +14 -0
- data/test/ex302.exp +15 -0
- data/test/ex302.in +18 -0
- data/test/ex303.exp +15 -0
- data/test/ex303.in +16 -0
- data/test/ex304.exp +17 -0
- data/test/ex304.in +15 -0
- data/test/ex311.exp +18 -0
- data/test/ex311.in +32 -0
- data/test/ex312.exp +21 -0
- data/test/ex312.in +18 -0
- data/test/ex313.exp +20 -0
- data/test/ex313.in +33 -0
- data/test/ex314.exp +34 -0
- data/test/ex314.in +24 -0
- data/test/ex801.exp +16 -0
- data/test/ex801.in +15 -0
- data/test/test.rb +273 -0
- data/todo.txt +1 -0
- metadata +132 -0
data/lib/kwaff/rexml.rb
ADDED
@@ -0,0 +1,394 @@
|
|
1
|
+
##
|
2
|
+
## translators for REXML
|
3
|
+
##
|
4
|
+
## $Id: rexml.rb 9 2005-06-09 08:44:11Z kwatch $
|
5
|
+
## $Release: 1.0.0 $
|
6
|
+
## copyright(c) 2005 kuwata-lab.com all rights reserved
|
7
|
+
##
|
8
|
+
|
9
|
+
require 'rexml/document'
|
10
|
+
|
11
|
+
require 'kwaff/errors'
|
12
|
+
require 'kwaff/orderedhash'
|
13
|
+
require 'kwaff/node'
|
14
|
+
require 'kwaff/parser'
|
15
|
+
require 'kwaff/translator'
|
16
|
+
|
17
|
+
module Kwaff
|
18
|
+
|
19
|
+
class Node
|
20
|
+
def to_rexml(toppings={})
|
21
|
+
translator = Kwaff::RexmlTranslator.new(toppings)
|
22
|
+
return translator ? translator.translate(self) : nil
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
## translate Kwaff::Document to REXML::Document
|
28
|
+
##
|
29
|
+
## ex.
|
30
|
+
## kwaff_str = File.open('file.kwaff') { |f| f.read }
|
31
|
+
## kwaff_document = Kwaff.parse_document(kwaff_str)
|
32
|
+
## translator = Kwaff::Rexml::RexmlTranslator.new()
|
33
|
+
## rexml_document = translator.translate(kwaff_document)
|
34
|
+
##
|
35
|
+
class RexmlTranslator < Translator
|
36
|
+
|
37
|
+
def initialize(toppings={})
|
38
|
+
super(toppings)
|
39
|
+
end
|
40
|
+
|
41
|
+
def translate_element(elem, level=0)
|
42
|
+
rexml_elem = REXML::Element.new(elem.tag)
|
43
|
+
elem.attrs.each do |aname, avalue|
|
44
|
+
rexml_elem.add_attribute(aname, avalue)
|
45
|
+
end if elem.attrs
|
46
|
+
elem.children.each do |child|
|
47
|
+
rexml_node = translate(child, level)
|
48
|
+
rexml_elem.add(rexml_node)
|
49
|
+
end if elem.children
|
50
|
+
return rexml_elem
|
51
|
+
end
|
52
|
+
|
53
|
+
def translate_document(document, level=0)
|
54
|
+
headers = document.headers
|
55
|
+
rexml_document = REXML::Document.new
|
56
|
+
rexml_xmldecl = REXML::XMLDecl.new(headers[:xmlversion], headers[:encoding])
|
57
|
+
rexml_document.add(rexml_xmldecl)
|
58
|
+
if headers[:doctype]
|
59
|
+
#$stderr.puts "*** debug: headers[:doctype]=#{headers[:doctype].inspect}"
|
60
|
+
rexml_source = REXML::Source.new(headers[:doctype].to_s)
|
61
|
+
rexml_doctype = REXML::DocType.new(rexml_source)
|
62
|
+
rexml_document.add(rexml_doctype)
|
63
|
+
end
|
64
|
+
rexml_document.add(document.root.to_rexml()) if document.root
|
65
|
+
return rexml_document
|
66
|
+
end
|
67
|
+
|
68
|
+
def translate_comment(comment, level=0)
|
69
|
+
return REXML::Comment.new(comment.str)
|
70
|
+
end
|
71
|
+
|
72
|
+
def translate_text(text, level=0)
|
73
|
+
return REXML::Text.new(text.str)
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
|
78
|
+
|
79
|
+
|
80
|
+
##
|
81
|
+
## * To convert XML string to Kwaff format string,
|
82
|
+
## use Kwaff::Rexml::revert()
|
83
|
+
## * To convert Kwaff format string to REXML::Document tree,
|
84
|
+
## use Kwaff::Rexml::Parser or Kwaff::Rexml::parse_document().
|
85
|
+
## * To convert Kwaff::Document tree to REXML::Document tree,
|
86
|
+
## use Kwaff::RexmlTranslator.
|
87
|
+
## * To convert REXML::Document tree to Kwaff format string,
|
88
|
+
## use Kwaff::Rexml::KwaffTranslator
|
89
|
+
## * To convert REXML::Document tree to Kwaff::Document tree,
|
90
|
+
## use Kwaff::Rexml::ReverseTranslator.
|
91
|
+
##
|
92
|
+
module Rexml
|
93
|
+
|
94
|
+
## Parse Kwaff string and return REXML::Document
|
95
|
+
##
|
96
|
+
## ex.
|
97
|
+
## kwaff_str = File.open('file.kwaff') { |f| f.read }
|
98
|
+
## parser = Kwaff::Rexml::Parser.new(kwaff_str)
|
99
|
+
## rexml_document = parser.parse_document()
|
100
|
+
##
|
101
|
+
class Parser < Kwaff::Parser
|
102
|
+
|
103
|
+
def create_document(headers, root)
|
104
|
+
Kwaff::assert() unless root.is_a?(REXML::Element)
|
105
|
+
## XML Declaration and Document Type
|
106
|
+
#rexml_xmldecl = REXML::XMLDecl.new((headers[:xmlversion] || '1.0'), headers[:encoding])
|
107
|
+
#rexml_source = REXML::Source.new(headers[:doctype])
|
108
|
+
#rexml_doctype = REXML::DocType.new(rexml_source)
|
109
|
+
s = ''
|
110
|
+
s << '<?xml version="' << (headers[:xmlversion] || '1.0')
|
111
|
+
if headers[:encoding]
|
112
|
+
s << ' encoding="' << headers[:encoding] << '"'
|
113
|
+
end
|
114
|
+
s << "?>\n"
|
115
|
+
s << headers[:doctype].to_s if headers[:doctype]
|
116
|
+
|
117
|
+
## create XML Document
|
118
|
+
#rexml_document = REXML::Document.new()
|
119
|
+
#rexml_document.add(rexml_xmldecl)
|
120
|
+
#rexml_document.add(rexml_doctype)
|
121
|
+
rexml_document = REXML::Document.new(s)
|
122
|
+
rexml_document.add(root)
|
123
|
+
return rexml_document
|
124
|
+
end
|
125
|
+
|
126
|
+
def create_element(tag, children, attrs)
|
127
|
+
rexml_element = REXML::Element.new
|
128
|
+
rexml_element.name = tag
|
129
|
+
attrs.each do |aname, avalue|
|
130
|
+
rexml_element.add_attribute(aname, avalue)
|
131
|
+
end if attrs
|
132
|
+
children.each do |child|
|
133
|
+
rexml_element.add(child)
|
134
|
+
end if children
|
135
|
+
return rexml_element
|
136
|
+
end
|
137
|
+
|
138
|
+
def create_comment(str)
|
139
|
+
return REXML::Comment.new(str)
|
140
|
+
end
|
141
|
+
|
142
|
+
def create_text(str, flag_escape=true)
|
143
|
+
return flag_escape ? REXML::Text.new(str) : REXML::CData.new(str)
|
144
|
+
end
|
145
|
+
|
146
|
+
def set_node_option(node, name, value)
|
147
|
+
# nothing
|
148
|
+
end
|
149
|
+
|
150
|
+
end
|
151
|
+
|
152
|
+
|
153
|
+
|
154
|
+
##
|
155
|
+
## Kwaff::Rexml::Translator
|
156
|
+
##
|
157
|
+
class Translator
|
158
|
+
def initialize(toppings={})
|
159
|
+
@toppings = toppings
|
160
|
+
@newline = toppings[:newline] || "\n"
|
161
|
+
@space = ' ' * (toppings[:output_indent_width] || 2)
|
162
|
+
@output = ''
|
163
|
+
end
|
164
|
+
|
165
|
+
## don't override!
|
166
|
+
def translate(rexml_node, level=0)
|
167
|
+
## cannot use visitor-pattern
|
168
|
+
case rexml_node
|
169
|
+
when REXML::Document
|
170
|
+
return translate_document(rexml_node, level)
|
171
|
+
when REXML::Element
|
172
|
+
return translate_element(rexml_node, level)
|
173
|
+
when REXML::Comment
|
174
|
+
return translate_comment(rexml_node, level)
|
175
|
+
when REXML::Text
|
176
|
+
return translate_text(rexml_node, level)
|
177
|
+
else
|
178
|
+
errmsg = "translation error (rexml_node.class.name=#{rexml_node.class.name})."
|
179
|
+
raise Kwaff::TranslationError.new(errmsg)
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
## abstract method
|
184
|
+
def translate_document(rexml_node, level=0)
|
185
|
+
raise NotImplementedError.new("#{self.class.name}#translate_document() is not implemented.")
|
186
|
+
end
|
187
|
+
|
188
|
+
## abstract method
|
189
|
+
def translate_element(rexml_node, level=0)
|
190
|
+
raise NotImplementedError.new("#{self.class.name}#translate_element() is not implemented.")
|
191
|
+
end
|
192
|
+
|
193
|
+
## abstract method
|
194
|
+
def translate_comment(rexml_node, level=0)
|
195
|
+
raise NotImplementedError.new("#{self.class.name}#translate_comment() is not implemented.")
|
196
|
+
end
|
197
|
+
|
198
|
+
## abstract method
|
199
|
+
def translate_text(rexml_node, level=0)
|
200
|
+
raise NotImplementedError.new("#{self.class.name}#translate_text() is not implemented.")
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
|
205
|
+
## Translate REXML::Document to Kwaff string
|
206
|
+
##
|
207
|
+
## ex.
|
208
|
+
## xml_str = File.open('file.xml') { |f| f.read }
|
209
|
+
## rexml_document = REXML::Document.new(xml_str)
|
210
|
+
## translator = Kwaff::Rexml::KwaffTranslator.new()
|
211
|
+
## kwaff_str = translator.translate(rexml_document)
|
212
|
+
##
|
213
|
+
class KwaffTranslator < Translator
|
214
|
+
def initialize(toppings={})
|
215
|
+
@toppings = toppings
|
216
|
+
@newline = toppings[:newline] || "\n"
|
217
|
+
@space = ' ' * (toppings[:output_indent_width] || 2)
|
218
|
+
@output = ''
|
219
|
+
end
|
220
|
+
|
221
|
+
def translate_element(rexml_elem, level=0)
|
222
|
+
Kwaff::assert() unless rexml_elem.is_a?(REXML::Element)
|
223
|
+
|
224
|
+
children = []
|
225
|
+
rexml_elem.children.each do |child|
|
226
|
+
children << child if !child.is_a?(REXML::Text) || child.to_s =~ /\S/
|
227
|
+
end if rexml_elem.children
|
228
|
+
|
229
|
+
tag = rexml_elem.expanded_name ## namespace + tagname
|
230
|
+
@output << (@space * level) if level > 0
|
231
|
+
@output << "* #{tag}" ## *pattern*
|
232
|
+
|
233
|
+
text = nil
|
234
|
+
if children.length == 1 && children[0].is_a?(REXML::Text)
|
235
|
+
text = children[0].to_s.strip
|
236
|
+
if text.index(?\n) == nil
|
237
|
+
@output << " = #{text}"
|
238
|
+
else
|
239
|
+
text = nil
|
240
|
+
end
|
241
|
+
end
|
242
|
+
@output << @newline
|
243
|
+
|
244
|
+
rexml_elem.attributes.each do |name, value|
|
245
|
+
@output << (@space * (level + 1))
|
246
|
+
@output << "- #{name} = #{value}#{@newline}" ## *pattern*
|
247
|
+
end
|
248
|
+
|
249
|
+
if text == nil
|
250
|
+
children.each do |child|
|
251
|
+
#translate_element(child, level+1)
|
252
|
+
translate(child, level+1)
|
253
|
+
end if rexml_elem.children
|
254
|
+
end
|
255
|
+
|
256
|
+
return @output
|
257
|
+
end
|
258
|
+
|
259
|
+
def _rexml_doctype_to_kwaff_doctype(rexml_doctype)
|
260
|
+
tag = rexml_doctype.name
|
261
|
+
public_id = rexml_doctype.instance_eval("@long_name")
|
262
|
+
public_id = public_id.gsub(/\A"/, '').gsub(/"\z/, '') if public_id
|
263
|
+
system_id = rexml_doctype.instance_eval("@uri")
|
264
|
+
system_id = system_id.gsub(/\A"/, '').gsub(/"\z/, '') if system_id
|
265
|
+
if system_id || public_id
|
266
|
+
doctype = Kwaff::DocType.new(tag, public_id, system_id)
|
267
|
+
else
|
268
|
+
doctype = Kwaff::DocType.new()
|
269
|
+
doctype.doctype = rexml_doctype.to_s
|
270
|
+
end
|
271
|
+
return doctype
|
272
|
+
end
|
273
|
+
|
274
|
+
def translate_document(rexml_document, level=0)
|
275
|
+
Kwaff::assert() unless rexml_document.class == REXML::Document
|
276
|
+
@output << "?xmlversion = #{rexml_document.version.sub(/\s+encoding=/,'')}#{@newline}"
|
277
|
+
@output << "?encoding = #{rexml_document.encoding.to_s}#{@newline}"
|
278
|
+
rexml_doctype = rexml_document.doctype
|
279
|
+
if rexml_doctype
|
280
|
+
doctype = _rexml_doctype_to_kwaff_doctype(rexml_doctype)
|
281
|
+
nickname = nil
|
282
|
+
if doctype.system_id
|
283
|
+
dtype = DocType.find { |dt| doctype.system_id == dt.system_id }
|
284
|
+
nickname = DocType.nickname(dtype) if dtype
|
285
|
+
end
|
286
|
+
doctype_str = nickname || rexml_doctype.to_s
|
287
|
+
@output << "?doctype = #{doctype_str}#{@newline}" if doctype_str
|
288
|
+
end
|
289
|
+
translate_element(rexml_document.root, level)
|
290
|
+
return @output
|
291
|
+
end
|
292
|
+
|
293
|
+
def translate_comment(rexml_comment, level=0)
|
294
|
+
prefix = (@space * level) + "# " ## *pattern*
|
295
|
+
rexml_comment.string.split(/\r?\n/).each do |line|
|
296
|
+
@output << prefix << line << @newline
|
297
|
+
end
|
298
|
+
return @output
|
299
|
+
end
|
300
|
+
|
301
|
+
def translate_text(rexml_text, level=0)
|
302
|
+
str = rexml_text.value
|
303
|
+
return @output if str =~ /\A\s*\z/
|
304
|
+
prefix = (@space * level) + ". " ## *pattern*
|
305
|
+
str.split(/\r?\n/).each do |line|
|
306
|
+
@output << prefix << line << @newline
|
307
|
+
end
|
308
|
+
return @output
|
309
|
+
end
|
310
|
+
|
311
|
+
end
|
312
|
+
|
313
|
+
|
314
|
+
##
|
315
|
+
## translate REXML::Document to Kwaff::Document
|
316
|
+
##
|
317
|
+
class ReverseTranslator < Translator
|
318
|
+
|
319
|
+
def translate_document(rexml_document, level=0)
|
320
|
+
headers = OrderedHash.new
|
321
|
+
headers[:xmlversion] = rexml_document.version().to_s
|
322
|
+
headers[:encoding] = rexml_document.encoding().to_s
|
323
|
+
if doctype = rexml_document.doctype
|
324
|
+
doctype = doctype.to_s
|
325
|
+
doctype << "\n" if doctype[-1] != ?\n
|
326
|
+
headers[:doctype] = doctype.to_s
|
327
|
+
end
|
328
|
+
root = translate_element(rexml_document.root)
|
329
|
+
return Document.new(headers, root)
|
330
|
+
end
|
331
|
+
|
332
|
+
def translate_element(rexml_element, level=0)
|
333
|
+
tag = rexml_element.name
|
334
|
+
children = []
|
335
|
+
attrs = OrderedHash.new
|
336
|
+
rexml_element.attributes.each do |aname, avalue|
|
337
|
+
attrs[aname] = avalue
|
338
|
+
end if rexml_element.attributes
|
339
|
+
rexml_element.children.each do |child|
|
340
|
+
node = translate(child)
|
341
|
+
children << node if node
|
342
|
+
end if rexml_element.children
|
343
|
+
return Element.new(tag, children, attrs)
|
344
|
+
end
|
345
|
+
|
346
|
+
def translate_comment(rexml_comment, level=0)
|
347
|
+
str = rexml_comment.to_s
|
348
|
+
return Comment.new(str)
|
349
|
+
end
|
350
|
+
|
351
|
+
def translate_text(rexml_text, level=0)
|
352
|
+
str = rexml_text.value
|
353
|
+
return nil if str =~ /\A\s*\z/
|
354
|
+
flag_escape = !rexml_text.is_a?(REXML::CData)
|
355
|
+
return Text.new(str, flag_escape)
|
356
|
+
end
|
357
|
+
|
358
|
+
end
|
359
|
+
|
360
|
+
|
361
|
+
## return an intance of REXML::Document
|
362
|
+
##
|
363
|
+
## ex.
|
364
|
+
## kwaff_str = File.open('file.kwaff') { |f| f.read }
|
365
|
+
## rexml_document = Kwaff::parse_document(kwaff_str)
|
366
|
+
##
|
367
|
+
def self.parse_document(kwaff_str, toppings={})
|
368
|
+
parser = Kwaff::Rexml::Parser.new(kwaff_str, toppings)
|
369
|
+
rexml_document = parser.parse_document()
|
370
|
+
return rexml_document
|
371
|
+
end
|
372
|
+
|
373
|
+
|
374
|
+
## convert XML string to Kwaff string.
|
375
|
+
##
|
376
|
+
## ex.
|
377
|
+
## xml_str = File.open('file.xml') { |f| f.read }
|
378
|
+
## kwaff_str = Kwaff::Rexml::revert(xml_str)
|
379
|
+
##
|
380
|
+
def self.revert(xml_str, toppings={})
|
381
|
+
rexml_document = REXML::Document.new(xml_str)
|
382
|
+
if !toppings[:newline]
|
383
|
+
pos = xml_str.index(?\n)
|
384
|
+
toppings[:newline] = "\r\n" if xml_str[pos-1] == ?\r
|
385
|
+
end
|
386
|
+
translator = Kwaff::Rexml::KwaffTranslator.new(toppings)
|
387
|
+
kwaff_str = translator.translate(rexml_document)
|
388
|
+
return kwaff_str
|
389
|
+
end
|
390
|
+
|
391
|
+
|
392
|
+
end ## module Rexml
|
393
|
+
|
394
|
+
end
|
@@ -0,0 +1,275 @@
|
|
1
|
+
##
|
2
|
+
## translate Kwaff node-tree to XML document or Kwaff document
|
3
|
+
##
|
4
|
+
## $Id: translator.rb 8 2005-05-18 17:33:43Z kwatch $
|
5
|
+
## $Release: 1.0.0 $
|
6
|
+
## copyright(c) 2005 kuwata-lab.com all rights reserved
|
7
|
+
##
|
8
|
+
|
9
|
+
require 'kwaff/errors'
|
10
|
+
require 'kwaff/node'
|
11
|
+
require 'kwaff/doctype'
|
12
|
+
|
13
|
+
module Kwaff
|
14
|
+
|
15
|
+
class TranslationError < KwaffError
|
16
|
+
end
|
17
|
+
|
18
|
+
|
19
|
+
## abstract class for XmlTranslator and KwaffTranslator
|
20
|
+
class Translator
|
21
|
+
def initialize(toppings={})
|
22
|
+
@toppings = toppings
|
23
|
+
end
|
24
|
+
attr_reader :toppings
|
25
|
+
|
26
|
+
|
27
|
+
## concrete method (don't override!)
|
28
|
+
def translate(node, level=0) ## don't override!
|
29
|
+
return node.accept(self, level)
|
30
|
+
end
|
31
|
+
|
32
|
+
## abstract method
|
33
|
+
def translate_document(document, level=0)
|
34
|
+
raise NotImplementedError.new("#{self.class.name}#translate_document() is not implemented.")
|
35
|
+
end
|
36
|
+
|
37
|
+
## abstract method
|
38
|
+
def translate_element(document, level=0)
|
39
|
+
raise NotImplementedError.new("#{self.class.name}#translate_element() is not implemented.")
|
40
|
+
end
|
41
|
+
|
42
|
+
## abstract method
|
43
|
+
def translate_comment(comment, level=0)
|
44
|
+
raise NotImplementedError.new("#{self.class.name}#translate_comment() is not implemented.")
|
45
|
+
end
|
46
|
+
|
47
|
+
## abstract method
|
48
|
+
def translate_text(text, level=0)
|
49
|
+
raise NotImplementedError.new("#{self.class.name}#translate_text() is not implemented.")
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
|
56
|
+
## translate Kwaff::Document into XML string
|
57
|
+
##
|
58
|
+
## ex.
|
59
|
+
## kwaff_str = File.open('file.kwaff') { |f| f.read }
|
60
|
+
## parser = Kwaff::Parser.new(kwaff_str)
|
61
|
+
## document = parser.parse_document()
|
62
|
+
## toppings = { :newline => parser.newline, :output_indent_width=>2 }
|
63
|
+
## translator = XmlTranslator.new(toppings)
|
64
|
+
## xml_str = translator.translate(document)
|
65
|
+
##
|
66
|
+
class XmlTranslator < Translator
|
67
|
+
|
68
|
+
def initialize(toppings={})
|
69
|
+
super(toppings)
|
70
|
+
@newline = toppings[:newline] || "\n"
|
71
|
+
@output = ""
|
72
|
+
width = toppings[:output_indent_width]
|
73
|
+
@space = width ? ' ' * width.to_i : ' '
|
74
|
+
end
|
75
|
+
|
76
|
+
|
77
|
+
def translate_element(elem, level=0)
|
78
|
+
n = elem.empty_lines()
|
79
|
+
n.times { @output << @newline } if n
|
80
|
+
|
81
|
+
@output << @space * level if @output[-1] == ?\n
|
82
|
+
@output << "<" << elem.tag
|
83
|
+
elem.attrs.each do |aname, avalue|
|
84
|
+
@output << " #{aname}=\"#{_escape_attrval(avalue)}\""
|
85
|
+
end
|
86
|
+
|
87
|
+
children = elem.children
|
88
|
+
if children.empty?
|
89
|
+
@output << "/>#{@newline}"
|
90
|
+
elsif children.length == 1 && children[0].is_a?(Text)
|
91
|
+
text = children[0]
|
92
|
+
str = text.escape? ? _escape(text.str) : text.str
|
93
|
+
@output << ">#{str}</#{elem.tag}>#{@newline}"
|
94
|
+
else
|
95
|
+
@output << ">#{@newline}"
|
96
|
+
children.each do |child|
|
97
|
+
translate(child, level+1)
|
98
|
+
end
|
99
|
+
n = children[0].empty_lines
|
100
|
+
n.times { @output << @newline } if n && n > 0
|
101
|
+
@output << @space * level if @output[-1] == ?\n
|
102
|
+
@output << "</#{elem.tag}>#{@newline}"
|
103
|
+
end
|
104
|
+
return @output
|
105
|
+
end
|
106
|
+
|
107
|
+
|
108
|
+
def translate_document(document, level=0)
|
109
|
+
headers = document.headers()
|
110
|
+
xmlversion = headers[:xmlversion] || '1.0'
|
111
|
+
encoding = headers[:encoding] ? " encoding=\"#{headers[:encoding]}\"" : ''
|
112
|
+
doctype = headers[:doctype]
|
113
|
+
@output << "<?xml version=\"#{xmlversion}\"#{encoding}?>#{@newline}"
|
114
|
+
@output << doctype.to_s if doctype
|
115
|
+
@output << "\n" if @output[-1] != ?\n
|
116
|
+
if document.root
|
117
|
+
translate_element(document.root, level)
|
118
|
+
#if (n = document.empty_lines) != nil && n > 0
|
119
|
+
# @output.sub!(/^\s*<\/.*?>\r?\n?\z/, (@newline * n) + '\&')
|
120
|
+
#end
|
121
|
+
end
|
122
|
+
return @output
|
123
|
+
end
|
124
|
+
|
125
|
+
|
126
|
+
def translate_comment(comment, level=0)
|
127
|
+
n = comment.empty_lines()
|
128
|
+
n.times { @output << @newline } if n
|
129
|
+
@output << @space * level
|
130
|
+
@output << "<!-- #{comment.str} -->#{@newline}"
|
131
|
+
return @output
|
132
|
+
end
|
133
|
+
|
134
|
+
|
135
|
+
def translate_text(text, level=0)
|
136
|
+
n = text.empty_lines()
|
137
|
+
n.times { @output << @newline } if n
|
138
|
+
#@output << @space * level
|
139
|
+
str = text.escape? ? _escape(text.str) : text.str
|
140
|
+
@output << "#{str}"
|
141
|
+
return @output
|
142
|
+
end
|
143
|
+
|
144
|
+
|
145
|
+
private
|
146
|
+
|
147
|
+
def _escape_attrval(str)
|
148
|
+
s = str.dup
|
149
|
+
s.gsub!(/\&/, '&')
|
150
|
+
s.gsub!(/</, '<')
|
151
|
+
s.gsub!(/>/, '>') # should be comment-out?
|
152
|
+
s.gsub!(/"/, '"') #"
|
153
|
+
return s
|
154
|
+
end
|
155
|
+
|
156
|
+
def _escape(str)
|
157
|
+
s = str.dup
|
158
|
+
s.gsub!(/\&/, '&')
|
159
|
+
s.gsub!(/</, '<')
|
160
|
+
s.gsub!(/>/, '>')
|
161
|
+
return s
|
162
|
+
end
|
163
|
+
|
164
|
+
end
|
165
|
+
|
166
|
+
|
167
|
+
## translate Kwaff::Document into Kwaff string
|
168
|
+
##
|
169
|
+
## ex.
|
170
|
+
## kwaff_str = File.open('file.kwaff') { |f| f.read }
|
171
|
+
## parser = Kwaff::Parser.new(kwaff_str)
|
172
|
+
## document = parser.parse_document()
|
173
|
+
## toppings = { :newline => parser.newline, :output_indent_width=>2 }
|
174
|
+
## translator = KwaffTranslator.new(toppings)
|
175
|
+
## xml_str = translator.translate(document)
|
176
|
+
##
|
177
|
+
## if you want to convert XML string to Kwaff string,
|
178
|
+
## use Kwaff::Rexml::revert() or Kwaff::Rexml::KwaffTranslator.
|
179
|
+
##
|
180
|
+
class KwaffTranslator < Translator
|
181
|
+
|
182
|
+
def initialize(toppings={})
|
183
|
+
super(toppings)
|
184
|
+
@toppings = toppings
|
185
|
+
@space = toppings[:indent_width] || ' '
|
186
|
+
@newline = toppings[:newline] || "\n"
|
187
|
+
@output = ''
|
188
|
+
end
|
189
|
+
|
190
|
+
def translate_element(elem, level=0)
|
191
|
+
## check value
|
192
|
+
children = elem.children
|
193
|
+
value = nil
|
194
|
+
if children.length == 1 && children[0].is_a?(Text)
|
195
|
+
text = children[0]
|
196
|
+
str = text.str
|
197
|
+
value = str if !str.index(?\n)
|
198
|
+
end
|
199
|
+
|
200
|
+
## create string
|
201
|
+
@output << (@space * level) if level > 0
|
202
|
+
@output << '* ' << elem.tag ## *pattern*
|
203
|
+
@output << " = #{value}" if value
|
204
|
+
@output << @newline
|
205
|
+
elem.attrs.each do |aname, avalue|
|
206
|
+
@output << (@space * (level+1))
|
207
|
+
@output << "- #{aname} = #{avalue}#{@newline}" ## *pattern*
|
208
|
+
end
|
209
|
+
if !value && children.length > 0
|
210
|
+
children.each do |child|
|
211
|
+
translate_element(child, level+1)
|
212
|
+
end
|
213
|
+
end
|
214
|
+
return @output
|
215
|
+
end
|
216
|
+
|
217
|
+
def translate_document(document, level=0)
|
218
|
+
headers = document.headers
|
219
|
+
if headers
|
220
|
+
#if headers[:doctype]
|
221
|
+
# headers[:doctype] = headers[:doctype].gsub(/\n(.)/, ' \1')
|
222
|
+
#end
|
223
|
+
doctype = headers[:doctype]
|
224
|
+
if doctype && doctype.is_a?(DocType)
|
225
|
+
doctype2 = DocType.find { |dt| dt.public_id && dt.public_id == doctype.public_id }
|
226
|
+
if doctype2 != nil && (nickname = DocType.nickname(doctype2)) != nil
|
227
|
+
headers[:doctype] = nickname
|
228
|
+
end
|
229
|
+
end
|
230
|
+
headers.each do |key, value|
|
231
|
+
@output ||= ""
|
232
|
+
@output << "?#{key} = #{value.to_s}" ## *pattern*
|
233
|
+
@output << @newline if @output[-1] != ?\n
|
234
|
+
end
|
235
|
+
end
|
236
|
+
translate_element(document.root, level) if document.root
|
237
|
+
return @output
|
238
|
+
end
|
239
|
+
|
240
|
+
def translate_comment(comment, level=0)
|
241
|
+
@output ||= ""
|
242
|
+
@output << @space * level
|
243
|
+
@output << "# #{comment.str}#{@newline}" ## *pattern*
|
244
|
+
return @output
|
245
|
+
end
|
246
|
+
|
247
|
+
def translate_text(text, level=0)
|
248
|
+
@output ||= ""
|
249
|
+
@output << @space * level
|
250
|
+
@output << ". #{text.str}#{@newline}" ## *pattern*
|
251
|
+
return @output
|
252
|
+
end
|
253
|
+
|
254
|
+
end
|
255
|
+
|
256
|
+
|
257
|
+
##
|
258
|
+
## convert Kwaff string to XML string
|
259
|
+
##
|
260
|
+
## ex.
|
261
|
+
## kwaff_str = File.open('file.kwaff') { |f| f.read }
|
262
|
+
## xml_str = Kwaff::convert(kwaff_str)
|
263
|
+
##
|
264
|
+
def self.convert(kwaff_str, toppings={})
|
265
|
+
parser = Parser.new(kwaff_str, toppings)
|
266
|
+
document = parser.parse_document()
|
267
|
+
if !toppings.key?(:newline)
|
268
|
+
toppings[:newline] = parser.newline
|
269
|
+
end
|
270
|
+
translator = Kwaff::XmlTranslator.new(toppings)
|
271
|
+
xml_str = translator.translate(document)
|
272
|
+
return xml_str
|
273
|
+
end
|
274
|
+
|
275
|
+
end
|