duxml 0.7.2 → 0.8.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a443f0b41070e85e05a9042711af460f1a9de0ce
4
- data.tar.gz: c25d6801574a1730e3a38a5ccab2ed91b482d37b
3
+ metadata.gz: 5cfc64bf0a2a0fc7d5dfa7eddf824a91de78019e
4
+ data.tar.gz: 68539178080588cf391bd98619dd994f2e55fd6a
5
5
  SHA512:
6
- metadata.gz: 2804f997a7fa48f9bd6c24ddef5e8b84df058b4bfbc1f6a41cbda340646378ef0d94a95a32b89cc1160819bb2d9bf37926c8196e2e8f5d9d70950a5baa973f3b
7
- data.tar.gz: d2cac9f2b2c16c07b754f98224eea4da660857a73345215bed10824818cd837de15ce2fe98bb06a2100eb69171537fd270ae27dd6199710c1e740c88fd3d2711
6
+ metadata.gz: f176dc33c32a6293ff8d3df5e04ac7e48b9fd6edf275b1fe0260c56b18e5baa24366f9335bad203367d1f2aee5413be9dd17e92be4f4bccb1190f92428ac8bbc
7
+ data.tar.gz: cc453d524c27917c4ad689023e4622090edc17c3a08b4ecb42383a93c7c0516422fcb958ad29333e04d859a48efe88939c26db1125491fc47aaba925cf6f7ec0
data/bin/validate_xml CHANGED
@@ -16,4 +16,16 @@ puts "loaded grammar file: #{DITA_GRAMMAR_FILE}"
16
16
  validate
17
17
  puts "validation complete"
18
18
  log log_file
19
- puts "logged errors to #{log_file}"
19
+ puts "logged errors to #{log_file}"
20
+
21
+
22
+ if conditions
23
+
24
+ end
25
+
26
+
27
+ def conditions
28
+ asdf and b and c
29
+ end
30
+
31
+ File
@@ -25,7 +25,7 @@ module Duxml
25
25
  # in Ruby mode, args are some combination of new attributes/values and/or child nodes (text or XML) with which to initialize this node
26
26
  #
27
27
  # @param name [String] name of element, in both Ruby and file modes
28
- # @param _line_content [Fixnum, Array, Hash] line number of element file mode; if Array, new child nodes; if Hash, attributes; can be nil
28
+ # @param _line_or_content [Fixnum, Array, Hash] line number of element file mode; if Array, new child nodes; if Hash, attributes; can be nil
29
29
  # @param _col_or_children [Fixnum, Array] column position in file mode; if Array, new child nodes; can be nil
30
30
  def initialize(name, _line_or_content=nil, _col_or_children=nil)
31
31
  super name
@@ -51,18 +51,31 @@ module Duxml
51
51
  # @see Ox::Element#<<
52
52
  # this override reports changes to history; NewText for Strings, Add for elements
53
53
  #
54
- # @param obj [Element] element or string to add to this Element
54
+ # @param obj [Element, Array] element or string to add to this Element; can insert arrays which are always inserted in order
55
55
  # @return [Element] self
56
56
  def <<(obj)
57
+ add(obj)
58
+ end
59
+
60
+ # @see #<<
61
+ # this version of the method allows insertions between existing elements
62
+ #
63
+ # @param obj [Element, Array] element or string to add to this Element; can insert arrays which are always inserted in order
64
+ # @param index [Fixnum] index at which to insert new node; inserts at end of element by default; when inserting arrays, index is incremented for each item to avoid reversing array order
65
+ # @return [Element] self
66
+ def add(obj, index=-1)
57
67
  case
58
68
  when obj.is_a?(Array), obj.is_a?(NodeSet)
59
- obj.each do |e| self << e end
69
+ obj.each_with_index do |e, i|
70
+ add(e, index == -1 ? index : index+i)
71
+ end
60
72
  when obj.is_a?(String)
61
73
  type = :NewText
62
- super(obj)
74
+ nodes.insert(index, obj)
75
+ report(type, nodes.size-1)
63
76
  else
64
77
  type = :Add
65
- super(obj)
78
+ nodes.insert(index, obj)
66
79
  if nodes.last.count_observers < 1 && @observer_peers
67
80
  nodes.last.add_observer(@observer_peers.first.first)
68
81
  end
@@ -71,10 +84,21 @@ module Duxml
71
84
  self
72
85
  end
73
86
 
74
- # @param attr_sym [String, Symbol] name of attribute
75
- # @param val [String]
87
+ # @param index_or_attr [String, Symbol, Fixnum] string or symbol of attribute or index of child node
88
+ # @return [Element, String] string if attribute value or text node; Element if XML node
89
+ def [](index_or_attr)
90
+ index_or_attr.is_a?(Fixnum) ? nodes[index_or_attr] : super(index_or_attr)
91
+ end
92
+
93
+ # @param attr_sym [String, Symbol, Fixnum] name of attribute or index of child to replace
94
+ # @param val [String] new attribute value or replacement child node
76
95
  # @return [Element] self
77
96
  def []=(attr_sym, val)
97
+ if attr_sym.is_a?(Fixnum)
98
+ remove nodes[attr_sym]
99
+ add(val, attr_sym)
100
+ return self
101
+ end
78
102
  attr = attr_sym.to_s
79
103
  raise "argument to [] must be a Symbol or a String." unless attr.is_a?(Symbol) or attr.is_a?(String)
80
104
  args = [attr]
@@ -1,153 +1,153 @@
1
- # Copyright (c) 2016 Freescale Semiconductor Inc.
2
-
3
- require File.expand_path(File.dirname(__FILE__) + '/../ruby_ext/string')
4
-
5
-
6
- module Duxml
7
- module LazyOx
8
- # welcome to Lazy-Ox - where any method that doesn't exist, you can create on the fly and assign its methods to
9
- # a corresponding Duxml::Element. see Regexp.nmtoken and String#nmtokenize and String#constantize to see how a given symbol
10
- # can be converted into XML element names and vice versa. it can also use Class names as method calls to return children by type
11
- #
12
- # this method uses Ox::Element's :method_missing but adds an additional rescue block that:
13
- # matches namespaced Ruby module to this Element's name and extends this node with module's methods
14
- # then method matching symbol is called again with given arguments, yielding result to block if given, returning result if not
15
- # e.g.
16
- # module Duxml
17
- # module Throwable
18
- # def throw
19
- # puts 'throwing!!'
20
- # end
21
- # end
22
- # end
23
- #
24
- # Element.new('throwable').throw => 'throwing!!'
25
- #
26
- # if symbol name matches a class then method yields to block or returns as array child nodes that matches class
27
- # you can further refine search results by adding the symbol of the child instance variable, including name, by which to filter
28
- # if block given, returns first child for which block evaluates to true
29
- #
30
- # e.g.
31
- # class Child; end
32
- #
33
- # n = Element.new('node')
34
- # n << 'text'
35
- # n << Element.new('child')
36
- # n << Element.new('child')
37
- # n.Element # returns Array of Element nodes
38
- # => [#<Duxml::Element:0x0002 @value="child" ...>,
39
- # #<Duxml::Element:0x0003 @value="child" ...>]
40
- #
41
- # n.Element.each do |child| child << 'some text' end # adding some text
42
- # => ['text',
43
- # #<Duxml::Element:0x0002 @value="child" ... @nodes=['some text']>,
44
- # #<Duxml::Element 0x0003 @value="child" ... @nodes=['some text']>]
45
- #
46
- # n.Element do |child| child.nodes.first == 'some text' end # returns all children for which block is true
47
- # => [#<Duxml::Element:0x0002 @value="child" ... @nodes=['some text']>]
48
- #
49
- # %w(bar mar).each_with_index do |x, i| next if i.zero?; n.Child[:foo] = x end # adding some attributes
50
- # => ['text',
51
- # #<Duxml::Element:0x0002 @value="child" @attributes={foo: 'bar'} ...>,
52
- # #<Duxml::Element:0x0003 @value="child" @attributes={foo: 'mar'} ...>]
53
- #
54
- # n.Element(:foo) # returns array of Child nodes with attribute :foo
55
- # => [#<Duxml::Element:0x0002 @value="child" @attributes={foo: 'bar'} ...>,
56
- # #<Duxml::Element:0x0003 @value="child" @attributes={foo: 'mar'} ...>]
57
- #
58
- # n.Element(foo: 'bar') # returns array of Child nodes with attribute :foo equal to 'bar'
59
- # => [#<Duxml::Element:0xfff @value="child" @attributes={foo: 'bar'} ...>]
60
- #
61
- #
62
- # if element name has no matching Class or Module in namespace,
63
- # if symbol is lower case, it is made into a method, given &block as definition, then called with *args
64
- # e.g. n.change_color('blue') do |new_color| => #<Duxml::Element:0xfff @value="node" @attributes={color: 'blue'} @nodes=[]>
65
- # @color = new_color
66
- # self
67
- # end
68
- # n.color => 'blue'
69
- # n.change_color('mauve').color => 'mauve'
70
- #
71
- # @param sym [Symbol] method, class or module
72
- # @param *args [*several_variants] either arguments to method or initializing values for instance of given class
73
- # @param &block [block] if yielding result, yields to given block; if defining new method, block defines its contents
74
- def method_missing(sym, *args, &block)
75
- super(sym, *args, &block)
76
- rescue NoMethodError
77
- # handling Constant look up to dynamically extend or add to element
78
- if lowercase?(sym)
79
- if (const = look_up_const) and const.is_a?(Module)
80
- extend const
81
- result = method(sym).call(*args)
82
- return(result) unless block_given?
83
- yield(result)
84
- elsif block_given?
85
- new_method = proc(&block)
86
- self.const_set(sym, new_method)
87
- return new_method.call *args
88
- else
89
- raise NoMethodError, "undefined method `#{sym.to_s}' for #{description}"
90
- end # if (const = look_up_const) ... elsif block_given? ... else ...
91
- else
92
- results = filter(sym, args)
93
- return results unless block_given?
94
- results.keep_if do |node| yield(node) end
95
- end # if lowercase? ... else ...
96
- end # def method_missing(sym, *args, &block)
97
-
98
- private
99
-
100
- # @param sym [Symbol] indicates which element type is being filtered for
101
- # @param args [several_variants] arguments for filtering element children that matched 'sym'
102
- # @return [[Element]] Elements of type 'sym' that match criteria 'args'
103
- def filter(sym, args)
104
- class_nodes = nodes.select do |node|
105
- node.name == sym.to_s.nmtokenize or simple_class(node) == sym.to_s
106
- end
107
- class_nodes.keep_if do |node|
108
- if args.empty?
109
- true
110
- else
111
- args.any? do |arg|
112
- if arg.is_a?(Hash)
113
- node[arg.first.first] == arg.first.last
114
- else
115
- !node[arg].nil?
116
- end
117
- end
118
- end # if args.empty? ... else ...
119
- end # class_nodes.keep_if do |node|
120
- end # def filter(args)
121
-
122
- # @param maudule [Module] module context in which to look for duck-called method's module
123
- # @return [Module, Class] requested module or class
124
- def look_up_const(maudule = Duxml)
125
- mod_names = name.split(':')
126
- until mod_names.empty?
127
- word = mod_names.shift
128
- k = word.constantize
129
- if maudule.const_defined?(k, true) or Module.const_defined?(simple_class, true)
130
- const = maudule.const_get(k)
131
- if const.is_a?(Module)
132
- maudule = const
133
- end
134
-
135
- return const if mod_names.empty? and [Module, Class].include?(const.class)
136
- end
137
- end
138
- nil
139
- end
140
-
141
- # @param sym [Symbol] symbol for a constant
142
- # @return [Boolean] is symbol lowercase?
143
- def lowercase?(sym)
144
- sym.to_s[0].match(/[A-Z]/).nil?
145
- end
146
-
147
- # @param obj [Object] usually Element
148
- # @return [String] name of final Class or Module of self
149
- def simple_class(obj=self)
150
- obj.class.to_s.split('::').last
151
- end
152
- end # module LazyOx
1
+ # Copyright (c) 2016 Freescale Semiconductor Inc.
2
+
3
+ require File.expand_path(File.dirname(__FILE__) + '/../ruby_ext/string')
4
+
5
+
6
+ module Duxml
7
+ module LazyOx
8
+ # welcome to Lazy-Ox - where any method that doesn't exist, you can create on the fly and assign its methods to
9
+ # a corresponding Duxml::Element. see Regexp.nmtoken and String#nmtokenize and String#constantize to see how a given symbol
10
+ # can be converted into XML element names and vice versa. it can also use Class names as method calls to return children by type
11
+ #
12
+ # this method uses Ox::Element's :method_missing but adds an additional rescue block that:
13
+ # matches namespaced Ruby module to this Element's name and extends this node with module's methods
14
+ # then method matching symbol is called again with given arguments, yielding result to block if given, returning result if not
15
+ # e.g.
16
+ # module Duxml
17
+ # module Throwable
18
+ # def throw
19
+ # puts 'throwing!!'
20
+ # end
21
+ # end
22
+ # end
23
+ #
24
+ # Element.new('throwable').throw => 'throwing!!'
25
+ #
26
+ # if symbol name matches a class then method yields to block or returns as array child nodes that matches class
27
+ # you can further refine search results by adding the symbol of the child instance variable, including name, by which to filter
28
+ # if block given, returns first child for which block evaluates to true
29
+ #
30
+ # e.g.
31
+ # class Child; end
32
+ #
33
+ # n = Element.new('node')
34
+ # n << 'text'
35
+ # n << Element.new('child')
36
+ # n << Element.new('child')
37
+ # n.Element # returns Array of Element nodes
38
+ # => [#<Duxml::Element:0x0002 @value="child" ...>,
39
+ # #<Duxml::Element:0x0003 @value="child" ...>]
40
+ #
41
+ # n.Element.each do |child| child << 'some text' end # adding some text
42
+ # => ['text',
43
+ # #<Duxml::Element:0x0002 @value="child" ... @nodes=['some text']>,
44
+ # #<Duxml::Element 0x0003 @value="child" ... @nodes=['some text']>]
45
+ #
46
+ # n.Element do |child| child.nodes.first == 'some text' end # returns all children for which block is true
47
+ # => [#<Duxml::Element:0x0002 @value="child" ... @nodes=['some text']>]
48
+ #
49
+ # %w(bar mar).each_with_index do |x, i| next if i.zero?; n.Child[:foo] = x end # adding some attributes
50
+ # => ['text',
51
+ # #<Duxml::Element:0x0002 @value="child" @attributes={foo: 'bar'} ...>,
52
+ # #<Duxml::Element:0x0003 @value="child" @attributes={foo: 'mar'} ...>]
53
+ #
54
+ # n.Element(:foo) # returns array of Child nodes with attribute :foo
55
+ # => [#<Duxml::Element:0x0002 @value="child" @attributes={foo: 'bar'} ...>,
56
+ # #<Duxml::Element:0x0003 @value="child" @attributes={foo: 'mar'} ...>]
57
+ #
58
+ # n.Element(foo: 'bar') # returns array of Child nodes with attribute :foo equal to 'bar'
59
+ # => [#<Duxml::Element:0xfff @value="child" @attributes={foo: 'bar'} ...>]
60
+ #
61
+ #
62
+ # if element name has no matching Class or Module in namespace,
63
+ # if symbol is lower case, it is made into a method, given &block as definition, then called with *args
64
+ # e.g. n.change_color('blue') do |new_color| => #<Duxml::Element:0xfff @value="node" @attributes={color: 'blue'} @nodes=[]>
65
+ # @color = new_color
66
+ # self
67
+ # end
68
+ # n.color => 'blue'
69
+ # n.change_color('mauve').color => 'mauve'
70
+ #
71
+ # @param sym [Symbol] method, class or module
72
+ # @param *args [*several_variants] either arguments to method or initializing values for instance of given class
73
+ # @param &block [block] if yielding result, yields to given block; if defining new method, block defines its contents
74
+ def method_missing(sym, *args, &block)
75
+ super(sym, *args, &block)
76
+ rescue NoMethodError
77
+ # handling Constant look up to dynamically extend or add to element
78
+ if lowercase?(sym)
79
+ if (const = look_up_const) and const.is_a?(Module)
80
+ extend const
81
+ result = method(sym).call(*args)
82
+ return(result) unless block_given?
83
+ yield(result)
84
+ elsif block_given?
85
+ new_method = proc(&block)
86
+ self.const_set(sym, new_method)
87
+ return new_method.call *args
88
+ else
89
+ raise NoMethodError, "undefined method `#{sym.to_s}' for #{description}"
90
+ end # if (const = look_up_const) ... elsif block_given? ... else ...
91
+ else
92
+ results = filter(sym, args)
93
+ return results unless block_given?
94
+ results.keep_if do |node| yield(node) end
95
+ end # if lowercase? ... else ...
96
+ end # def method_missing(sym, *args, &block)
97
+
98
+ private
99
+
100
+ # @param sym [Symbol] indicates which element type is being filtered for
101
+ # @param args [several_variants] arguments for filtering element children that matched 'sym'
102
+ # @return [[Element]] Elements of type 'sym' that match criteria 'args'
103
+ def filter(sym, args)
104
+ class_nodes = nodes.select do |node|
105
+ node.name == sym.to_s.nmtokenize or simple_class(node) == sym.to_s
106
+ end
107
+ class_nodes.keep_if do |node|
108
+ if args.empty?
109
+ true
110
+ else
111
+ args.any? do |arg|
112
+ if arg.is_a?(Hash)
113
+ node[arg.first.first] == arg.first.last
114
+ else
115
+ !node[arg].nil?
116
+ end
117
+ end
118
+ end # if args.empty? ... else ...
119
+ end # class_nodes.keep_if do |node|
120
+ end # def filter(args)
121
+
122
+ # @param maudule [Module] module context in which to look for duck-called method's module
123
+ # @return [Module, Class] requested module or class
124
+ def look_up_const(maudule = Duxml)
125
+ mod_names = name.split(':')
126
+ until mod_names.empty?
127
+ word = mod_names.shift
128
+ k = word.constantize
129
+ if maudule.const_defined?(k, true) or Module.const_defined?(simple_class, true)
130
+ const = maudule.const_get(k)
131
+ if const.is_a?(Module)
132
+ maudule = const
133
+ end
134
+
135
+ return const if mod_names.empty? and [Module, Class].include?(const.class)
136
+ end
137
+ end
138
+ nil
139
+ end
140
+
141
+ # @param sym [Symbol] symbol for a constant
142
+ # @return [Boolean] is symbol lowercase?
143
+ def lowercase?(sym)
144
+ sym.to_s[0].match(/[A-Z]/).nil?
145
+ end
146
+
147
+ # @param obj [Object] usually Element
148
+ # @return [String] name of final Class or Module of self
149
+ def simple_class(obj=self)
150
+ obj.class.to_s.split('::').last
151
+ end
152
+ end # module LazyOx
153
153
  end # module Duxml
@@ -1,39 +1,39 @@
1
- # Copyright (c) 2016 Freescale Semiconductor Inc.
2
-
3
- require 'observer'
4
-
5
- module Duxml
6
- # subclass of Array that is Observable by History
7
- # used to track changes in String nodes of XML Element
8
- class NodeSet < Array
9
- include Observable
10
-
11
- @parent
12
-
13
- attr_reader :parent
14
-
15
- # @param _parent [Element] Element that is parent to this NodeSet's elements
16
- # @param ary [[String, Element]] child nodes with which to initialize this NodeSet
17
- def initialize(_parent, ary=[])
18
- super ary
19
- @parent = _parent
20
- end
21
-
22
- # @return [HistoryClass] object that observes this NodeSet for changes
23
- def history
24
- @observer_peers.first.first if @observer_peers and @observer_peers.first.any?
25
- end
26
-
27
- # @param index [Fixnum] index of array where old String is to be replaced
28
- # @param str [String] replacing String
29
- # @return [self] reports old String and index to history
30
- def []=(index, str)
31
- raise Exception if count_observers < 1
32
- old_str = self[index]
33
- super(index, str)
34
- changed
35
- notify_observers(:ChangeText, parent, index, old_str)
36
- self
37
- end
38
- end # class NodeSet < Array
1
+ # Copyright (c) 2016 Freescale Semiconductor Inc.
2
+
3
+ require 'observer'
4
+
5
+ module Duxml
6
+ # subclass of Array that is Observable by History
7
+ # used to track changes in String nodes of XML Element
8
+ class NodeSet < Array
9
+ include Observable
10
+
11
+ @parent
12
+
13
+ attr_reader :parent
14
+
15
+ # @param _parent [Element] Element that is parent to this NodeSet's elements
16
+ # @param ary [[String, Element]] child nodes with which to initialize this NodeSet
17
+ def initialize(_parent, ary=[])
18
+ super ary
19
+ @parent = _parent
20
+ end
21
+
22
+ # @return [HistoryClass] object that observes this NodeSet for changes
23
+ def history
24
+ @observer_peers.first.first if @observer_peers and @observer_peers.first.any?
25
+ end
26
+
27
+ # @param index [Fixnum] index of array where old String is to be replaced
28
+ # @param str [String] replacing String
29
+ # @return [self] reports old String and index to history
30
+ def []=(index, str)
31
+ raise Exception if count_observers < 1
32
+ old_str = self[index]
33
+ super(index, str)
34
+ changed
35
+ notify_observers(:ChangeText, parent, index, old_str)
36
+ self
37
+ end
38
+ end # class NodeSet < Array
39
39
  end # module Duxml
data/lib/duxml/doc.rb CHANGED
@@ -1,26 +1,86 @@
1
1
  # Copyright (c) 2016 Freescale Semiconductor Inc.
2
2
 
3
3
  require File.expand_path(File.dirname(__FILE__) + '/doc/element')
4
+ require File.expand_path(File.dirname(__FILE__) + '/meta')
4
5
 
5
6
  module Duxml
6
7
  class Doc < ::Ox::Document
7
8
  include ElementGuts
9
+
10
+ # path of file where this Doc is saved to
11
+ @path
12
+
13
+ # meta data for this Doc; contains reference to grammar if it exists and history
14
+ @meta
15
+
16
+ attr_reader :meta, :path
17
+
8
18
  def initialize(prolog={})
9
19
  super(prolog)
10
20
  self[:version] ||= '1.0'
21
+ @meta = MetaClass.new
11
22
  @nodes = NodeSet.new(self)
12
- # TODO should also create new metadata!!
23
+ add_observer meta.history
13
24
  end
14
25
 
15
- def write_to(path)
16
- s = attributes.collect do |k, v| %( #{k}="#{v}") end.join
17
- %(<?xml #{s}?>)+nodes.first.to_s
18
- File.write(path, s)
19
- self
26
+ # @param _path [String] assigns file path to document, creating it if it does not already exist along with metadata file
27
+ def path=(_path)
28
+ @path = _path
29
+ set_meta _path unless path
30
+ unless File.exists?(path)
31
+ write_to(path)
32
+ end
20
33
  end
21
34
 
35
+ # @return [String] summary of XML document as Ruby object and description of root element
22
36
  def to_s
23
37
  "#<#{self.class.to_s} @object_id='#{object_id}' @root='#{root.nil? ? '' : root.description}'>"
24
38
  end
39
+
40
+ # @param path_or_obj [String, MetaClass] metadata object itself or path of metadata for this file; if none given, saves existing metadata to file using @path
41
+ # @return [Doc] self
42
+ def set_meta(path_or_obj=nil)
43
+ @meta = case path_or_obj
44
+ when MetaClass, Element then path_or_obj
45
+ when String && File.exists?(path_or_obj)
46
+ Ox.parse_obj(path_or_obj)
47
+ else
48
+ File.write(Meta.meta_path(path), Ox.dump(meta)) if path
49
+ meta
50
+ end
51
+ self
52
+ end
53
+
54
+ # shortcut method @see Meta#grammar
55
+ def grammar
56
+ meta.grammar
57
+ end
58
+
59
+ # shortcut method @see Meta#grammar=
60
+ def grammar=(grammar_or_file)
61
+ meta.grammar = grammar_or_file
62
+ end
63
+
64
+ # shortcut method @see Meta#history
65
+ def history
66
+ meta.history
67
+ end
68
+
69
+ # @return [String] one word description of what this object is: 'document'
70
+ def description
71
+ 'document'
72
+ end
73
+
74
+ # @param path [String] document's file path
75
+ # @return [Doc] returns self after writing contents to file
76
+ def write_to(path)
77
+ s = attributes.collect do |k, v| %( #{k}="#{v}") end.join
78
+ File.write(path, %(<?xml #{s}?>\n) + root.to_s)
79
+ x = meta.xml
80
+ File.write(Meta.meta_path(path), meta.xml.to_s)
81
+ self
82
+ end
25
83
  end # class Document < Element
26
- end
84
+ end
85
+
86
+ Hash
@@ -31,6 +31,20 @@ module Duxml
31
31
  module Pattern
32
32
  include Duxml
33
33
 
34
+ def xml
35
+ p = Element.new(simple_name)
36
+ instance_variables.each do |sym|
37
+ val = instance_variable_get(sym)
38
+ if val.respond_to?(:nodes)
39
+ d = Element.new(sym.to_s) << val
40
+ p << d
41
+ else
42
+ p[sym.to_s[1..-1].to_sym] = val.to_s unless sym == :@observer_peers
43
+ end
44
+ end
45
+ p
46
+ end
47
+
34
48
  # @return [String] nmtoken name of this pattern without namespace prefix e.g. ChildPattern.new(parent, child).name => 'child_pattern'
35
49
  def simple_name
36
50
  name.split(':').last