kwaff 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (85) hide show
  1. data/COPYING +340 -0
  2. data/ChangeLog.txt +118 -0
  3. data/README.txt +96 -0
  4. data/bin/kwaff +131 -0
  5. data/doc/docstyle.css +307 -0
  6. data/doc/examples.html +1283 -0
  7. data/doc/users-guide.html +395 -0
  8. data/examples/Makefile +17 -0
  9. data/examples/ant/Makefile +7 -0
  10. data/examples/ant/build.kwaff +57 -0
  11. data/examples/hibernate/AuctionItem.hbm.kwaff +45 -0
  12. data/examples/hibernate/Bid.hbm.kwaff +42 -0
  13. data/examples/hibernate/Makefile +9 -0
  14. data/examples/hibernate/User.hbm.kwaff +65 -0
  15. data/examples/hibernate/hibernate.cfg.kwaff +17 -0
  16. data/examples/seasar2/Makefile +9 -0
  17. data/examples/seasar2/seasar2.kwaff +62 -0
  18. data/examples/servlet/Makefile +9 -0
  19. data/examples/servlet/web.kwaff +37 -0
  20. data/examples/spring/Makefile +9 -0
  21. data/examples/spring/applicationContext.kwaff +147 -0
  22. data/examples/xhtml/Makefile +9 -0
  23. data/examples/xhtml/README.kwaff +84 -0
  24. data/examples/xi/Makefile +9 -0
  25. data/examples/xi/bbs.kwaff +58 -0
  26. data/lib/kwaff.rb +85 -0
  27. data/lib/kwaff/doctype.rb +124 -0
  28. data/lib/kwaff/doctypes.yaml +138 -0
  29. data/lib/kwaff/errors.rb +26 -0
  30. data/lib/kwaff/node.rb +101 -0
  31. data/lib/kwaff/optparse.rb +101 -0
  32. data/lib/kwaff/orderedhash.rb +56 -0
  33. data/lib/kwaff/parser.rb +342 -0
  34. data/lib/kwaff/rexml.rb +394 -0
  35. data/lib/kwaff/translator.rb +275 -0
  36. data/setup.rb +1331 -0
  37. data/test/ex101.exp +10 -0
  38. data/test/ex101.in +8 -0
  39. data/test/ex102.exp +14 -0
  40. data/test/ex102.in +16 -0
  41. data/test/ex103.exp +13 -0
  42. data/test/ex103.in +13 -0
  43. data/test/ex104.exp +24 -0
  44. data/test/ex104.in +24 -0
  45. data/test/ex105.exp +12 -0
  46. data/test/ex105.in +18 -0
  47. data/test/ex106.exp +22 -0
  48. data/test/ex106.in +21 -0
  49. data/test/ex107.exp +14 -0
  50. data/test/ex107.in +14 -0
  51. data/test/ex111.exp +7 -0
  52. data/test/ex111.in +13 -0
  53. data/test/ex112.exp +15 -0
  54. data/test/ex112.in +16 -0
  55. data/test/ex113.exp +23 -0
  56. data/test/ex113.in +22 -0
  57. data/test/ex114.exp +12 -0
  58. data/test/ex114.in +17 -0
  59. data/test/ex115.exp +9 -0
  60. data/test/ex115.in +12 -0
  61. data/test/ex121.exp +10 -0
  62. data/test/ex121.in +8 -0
  63. data/test/ex122.exp +10 -0
  64. data/test/ex122.in +8 -0
  65. data/test/ex301.exp +13 -0
  66. data/test/ex301.in +14 -0
  67. data/test/ex302.exp +15 -0
  68. data/test/ex302.in +18 -0
  69. data/test/ex303.exp +15 -0
  70. data/test/ex303.in +16 -0
  71. data/test/ex304.exp +17 -0
  72. data/test/ex304.in +15 -0
  73. data/test/ex311.exp +18 -0
  74. data/test/ex311.in +32 -0
  75. data/test/ex312.exp +21 -0
  76. data/test/ex312.in +18 -0
  77. data/test/ex313.exp +20 -0
  78. data/test/ex313.in +33 -0
  79. data/test/ex314.exp +34 -0
  80. data/test/ex314.in +24 -0
  81. data/test/ex801.exp +16 -0
  82. data/test/ex801.in +15 -0
  83. data/test/test.rb +273 -0
  84. data/todo.txt +1 -0
  85. metadata +132 -0
@@ -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!(/\&/, '&amp;')
150
+ s.gsub!(/</, '&lt;')
151
+ s.gsub!(/>/, '&gt;') # should be comment-out?
152
+ s.gsub!(/"/, '&quot;') #"
153
+ return s
154
+ end
155
+
156
+ def _escape(str)
157
+ s = str.dup
158
+ s.gsub!(/\&/, '&amp;')
159
+ s.gsub!(/</, '&lt;')
160
+ s.gsub!(/>/, '&gt;')
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