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.
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