duxml 0.7.2 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,35 +1,35 @@
1
- # Copyright (c) 2016 Freescale Semiconductor Inc.
2
-
3
- require 'rubyXL'
4
-
5
- module Duxml
6
- # contains helper methods to convert spreadsheet of DTD rules into Duxml::Rules
7
- module Spreadsheet
8
- private
9
- # @param path [String] spreadsheet file
10
- def self.sheet_to_xml(path)
11
- worksheet = RubyXL::Parser.parse(path)[0]
12
- attr_val_rule_hash = {}
13
- g = GrammarClass.new
14
- worksheet.each_with_index do |row, index|
15
- next if index == 0
16
- break if row[3].nil? || row[4].nil?
17
- element_name = row[3].value
18
- statement_str = row[4].value
19
- g << ChildrenRuleClass.new(element_name, statement_str)
20
- attribute_rules = row[5].value.split(/\n/)
21
- attribute_rules.each_with_index do |rule, i|
22
- next if i == 0 or rule.empty?
23
- attr_name, value_expr, attr_req = *rule.split
24
- next if [attr_name, value_expr, attr_req].any? do |s| s.empty? or s.match(/\w/).nil? end
25
- g << AttrsRuleClass.new(element_name, attr_name, attr_req)
26
- unless attr_val_rule_hash[attr_name]
27
- g << ValueRuleClass.new(attr_name, value_expr)
28
- attr_val_rule_hash[attr_name] = true
29
- end
30
- end # attribute_rules.each_with_index
31
- end # worksheet.each_with_index
32
- g
33
- end # def sheet_to_xml(path)
34
- end # module Spreadsheet
1
+ # Copyright (c) 2016 Freescale Semiconductor Inc.
2
+
3
+ require 'rubyXL'
4
+
5
+ module Duxml
6
+ # contains helper methods to convert spreadsheet of DTD rules into Duxml::Rules
7
+ module Spreadsheet
8
+ private
9
+ # @param path [String] spreadsheet file
10
+ def self.sheet_to_xml(path)
11
+ worksheet = RubyXL::Parser.parse(path)[0]
12
+ attr_val_rule_hash = {}
13
+ g = GrammarClass.new
14
+ worksheet.each_with_index do |row, index|
15
+ next if index == 0
16
+ break if row[3].nil? || row[4].nil?
17
+ element_name = row[3].value
18
+ statement_str = row[4].value
19
+ g << ChildrenRuleClass.new(element_name, statement_str)
20
+ attribute_rules = row[5].value.split(/\n/)
21
+ attribute_rules.each_with_index do |rule, i|
22
+ next if i == 0 or rule.empty?
23
+ attr_name, value_expr, attr_req = *rule.split
24
+ next if [attr_name, value_expr, attr_req].any? do |s| s.empty? or s.match(/\w/).nil? end
25
+ g << AttrsRuleClass.new(element_name, attr_name, attr_req)
26
+ unless attr_val_rule_hash[attr_name]
27
+ g << ValueRuleClass.new(attr_name, value_expr)
28
+ attr_val_rule_hash[attr_name] = true
29
+ end
30
+ end # attribute_rules.each_with_index
31
+ end # worksheet.each_with_index
32
+ g
33
+ end # def sheet_to_xml(path)
34
+ end # module Spreadsheet
35
35
  end # module Duxml
@@ -50,9 +50,9 @@ module Duxml
50
50
  end
51
51
  end
52
52
 
53
- # @return [Element] returns self as XML element e.g. '<duxml:grammar/>'
54
- def self.xml
55
- Element.new(name.nmtokenize).extend self
53
+ # @return [Doc] returns self as XML document
54
+ def xml
55
+ Element.new('grammar') << rules.collect do |rule| rule.xml end
56
56
  end
57
57
 
58
58
  # @return [History] history that this grammar is currently reporting to
@@ -27,10 +27,10 @@ module Duxml
27
27
 
28
28
  def_delegators :@nodes, :[], :each
29
29
 
30
- # @param harsh_or_kind [Boolean] by default harsh i.e. true so that if this History detects an error it will raise an Exception; otherwise not
31
- def initialize(harsh_or_kind = true)
30
+ # @param strict_or_false [Boolean] by default strict i.e. true so that if this History detects an error it will raise an Exception; otherwise not
31
+ def initialize(strict_or_false = true)
32
32
  @nodes = []
33
- @strict = harsh_or_kind
33
+ @strict = strict_or_false
34
34
  end
35
35
 
36
36
  attr_reader :nodes
@@ -40,15 +40,16 @@ module Duxml
40
40
  module History
41
41
  # used when creating a new metadata file for a static XML file
42
42
  #
43
- # @return [Element] XML element for a new <duxml:history> node
44
- def self.xml
45
- Element.new(name.nmtokenize).extend self
43
+ # @return [Doc] returns self as XML document
44
+ def xml
45
+ h = Element.new('history')
46
+ events.each do |event| h << event.xml end
47
+ h
46
48
  end
47
49
 
48
50
  # @return [Boolean] toggles (true by default) whether History will raise exception or tolerate qualify errors
49
- def strict?(harsh_or_kind=nil)
50
- @strict = harsh_or_kind.nil? ? @strict : harsh_or_kind
51
- @strict
51
+ def strict?(strict_or_false=nil)
52
+ @strict = strict_or_false.nil? ? @strict : strict_or_false
52
53
  end
53
54
 
54
55
  # @return [ChangeClass, ErrorClass] the latest event
data/lib/duxml/meta.rb CHANGED
@@ -22,17 +22,10 @@ module Duxml
22
22
  @grammar_path = grammar_path
23
23
  end
24
24
 
25
- attr_reader :history, :grammar
25
+ attr_reader :history, :grammar, :grammar_path
26
26
  end
27
27
 
28
28
  module Meta
29
- # @return [Doc] metadata document
30
- def self.xml
31
- d = Doc.new << (Element.new(name.nmtokenize) << Grammar.xml << History.xml)
32
- d.root.grammar[:ref] = @grammar_path if @grammar_path
33
- d
34
- end
35
-
36
29
  # @param path [String] path of XML-content file
37
30
  # @return [String] full path of metadata file based on content file's name e.g.
38
31
  # 'design.xml' => '.design.xml.duxml'
@@ -41,11 +34,29 @@ module Duxml
41
34
  "#{dir}/.#{File.basename(path)}#{FILE_EXT}"
42
35
  end
43
36
 
37
+ # @param g [String, GrammarClass] either a grammar object or path to one
38
+ # @return [GrammarClass] grammar object
44
39
  def grammar=(g)
45
- @grammar = g.is_a?(GrammarClass) ? g : Grammar.import(g)
40
+ @grammar = if g.is_a?(GrammarClass)
41
+ g
42
+ else
43
+ @grammar_path = g if File.exists?(g)
44
+ Grammar.import(g)
45
+ end
46
46
  history.delete_observers if history.respond_to?(:delete_observers)
47
47
  history.add_observer(grammar, :qualify)
48
48
  grammar.add_observer history
49
+ grammar
50
+ end
51
+
52
+ def xml
53
+ if grammar_path
54
+ g = Duxml::Element.new('grammar')
55
+ g[:ref] = grammar_path
56
+ else
57
+ g = grammar.xml
58
+ end
59
+ Duxml::Element.new('meta') << g << history.xml
49
60
  end
50
61
  end # module Meta
51
62
  end # module Duxml
@@ -1,27 +1,29 @@
1
- # Copyright (c) 2016 Freescale Semiconductor Inc.
2
-
3
- require 'observer'
4
-
5
- module Reportable
6
- include Observable
7
-
8
- # @param obs [Object] observer to add to this Element as well as its NodeSet
9
- def add_observer(obs, sym=nil)
10
- super(obs, sym || :update)
11
- nodes.add_observer(obs) if self.respond_to?(:nodes) and nodes.respond_to?(:add_observer)
12
- end
13
-
14
- private
15
-
16
- # all public methods that alter XML must call #report in the full scope of that public method
17
- # in order to correctly acquire name of method that called #report
18
- #
19
- # @param *args [*several_variants]
20
- def report(*args)
21
- return nil if @observer_peers.nil?
22
- changed
23
- new_args = [args.first, self]
24
- args[1..-1].each do |a| new_args << a end if args.size > 1
25
- notify_observers(*new_args)
26
- end
1
+ # Copyright (c) 2016 Freescale Semiconductor Inc.
2
+
3
+ require 'observer'
4
+
5
+ module Reportable
6
+ include Observable
7
+
8
+ # @param obs [Object] observer to add to this Element as well as its NodeSet
9
+ def add_observer(obs, sym=nil)
10
+ super(obs, sym || :update)
11
+ nodes.add_observer(obs) if self.respond_to?(:nodes) and nodes.respond_to?(:add_observer)
12
+ end
13
+
14
+ attr_reader :observer_peers
15
+
16
+ private
17
+
18
+ # all public methods that alter XML must call #report in the full scope of that public method
19
+ # in order to correctly acquire name of method that called #report
20
+ #
21
+ # @param *args [*several_variants]
22
+ def report(*args)
23
+ return nil if @observer_peers.nil?
24
+ changed
25
+ new_args = [args.first, self]
26
+ args[1..-1].each do |a| new_args << a end if args.size > 1
27
+ notify_observers(*new_args)
28
+ end
27
29
  end
data/lib/duxml/saxer.rb CHANGED
@@ -14,7 +14,8 @@ module Duxml
14
14
  saxer = DocuLiner.new(Duxml::Doc.new, obs)
15
15
  Ox.sax_parse(saxer, io, {convert_special: true, symbolize: false})
16
16
  doc = saxer.cursor
17
- doc.add_observer obs if obs
17
+ doc.add_observer obs if obs and doc.count_observers < 1
18
+ doc.path = path
18
19
  doc
19
20
  end
20
21
 
@@ -37,7 +38,7 @@ module Duxml
37
38
  attr_accessor :cursor_stack
38
39
 
39
40
  def start_element(name)
40
- cursor << Duxml::Element.new(name, line, column)
41
+ cursor.nodes.insert(-1, Duxml::Element.new(name, line, column))
41
42
  cursor_stack << cursor.nodes.last
42
43
  end
43
44
 
@@ -46,7 +47,7 @@ module Duxml
46
47
  end
47
48
 
48
49
  def text(str)
49
- cursor << str
50
+ cursor.nodes.insert(-1, str)
50
51
  end
51
52
 
52
53
  def end_element(name)
data/lib/duxml.rb CHANGED
@@ -1,51 +1,46 @@
1
1
  # Copyright (c) 2016 Freescale Semiconductor Inc.
2
2
 
3
3
  require File.expand_path(File.dirname(__FILE__) + '/duxml/saxer')
4
- require File.expand_path(File.dirname(__FILE__) + '/duxml/meta')
5
4
 
6
5
  module Duxml
7
- DITA_GRAMMAR = File.expand_path(File.dirname(__FILE__) + '/../xml/dita_grammar.xml')
8
6
  include Saxer
9
- include Meta
10
7
 
11
- # path to XML file
12
- @file
13
- # current document
8
+ # most recently processed document - default location for validated documents that are not loaded explicitly
14
9
  @doc
15
- # meta data document
16
- @meta
17
10
 
18
- attr_reader :meta, :file, :doc
11
+ attr_reader :doc
19
12
 
20
- # @param file [String, Doc] loads or creates given file or document and finds or creates corresponding metadata file e.g. '.xml_file.duxml'
13
+ # @param _file [String] loads XML file from given path and finds or creates corresponding metadata file e.g. '.xml_file.duxml'
21
14
  # @param grammar_path [nil, String, Duxml::Grammar] optional - provide an external grammar file or object
22
- # @return [Duxml::Meta] combined Object tree from metadata root (metadata and content's XML documents are kept separate)
15
+ # @return [Doc] XML document as Ruby object
23
16
  def load(_file, grammar_path=nil)
24
- if _file.is_a?(String) and File.exists?(_file)
25
- @file = _file
17
+ meta_path = Meta.meta_path(_file)
18
+
19
+ if File.exists?(meta_path)
20
+ meta = Ox.parse_obj(File.read meta_path)
21
+ meta.grammar = grammar_path unless grammar_path.nil? or meta.grammar.defined?
26
22
  else
27
- @file = "#{(_file.respond_to?(:name) ? _file.name : _file.class.to_s) + _file.object_id.to_s}"
28
- File.write file, ''
23
+ meta = MetaClass.new(grammar_path)
29
24
  end
30
25
 
31
- set_metadata!(grammar_path)
32
- set_doc!
33
- end # def load
34
-
35
- # @param file [String] creates new XML file at given path
36
- # @param content [Doc, Element] XML content with which to initialize new file
37
- def create(file, content=nil)
38
- File.write(file, content.to_s)
39
- @doc = content.is_a?(Doc) ? content : Doc.new
40
- end
26
+ if File.exists?(_file)
27
+ @doc = sax(_file, meta.history)
28
+ else
29
+ @doc = Doc.new
30
+ @doc.path = _file
41
31
 
42
- # @param file [String] saves current content XML to given file path (Duxml@file by default)
43
- def save(file)
44
- meta_path = Meta.meta_path(file)
45
- unless File.exists?(meta_path)
46
- File.new meta_path, 'w+'
47
- File.write(meta_path, Meta.xml)
32
+ doc.delete_observers if doc.count_observers > 0 and doc.observer_peers.first.object_id != meta.history.object_id
33
+ doc.add_observer meta.history if doc.count_observers < 1
48
34
  end
35
+ doc.set_meta meta
36
+ end # def load
37
+
38
+ # @param file [String] saves current content XML to given file path
39
+ # @param xml [Doc, Element] current Doc by default, but can also be unattached XML Element
40
+ def save(file, xml=doc)
41
+ @doc = xml.respond_to?(:root) ? xml : Doc.new << xml
42
+ doc.write_to file
43
+ File.write(Meta.meta_path(file), Ox.dump(doc.meta, circular: true))
49
44
  end
50
45
 
51
46
  # @param file [String] output file path for logging human-readable validation error messages
@@ -53,45 +48,29 @@ module Duxml
53
48
  File.write(file, meta.history.description)
54
49
  end
55
50
 
56
- # @param *Args [*several_variants] @see #load
51
+ # @param *Args [String, Doc] if string then path to load Doc, else Doc to validate
52
+ # @param options [Hash, Symbol] currently just supports suppression of console output of results with :quiet
57
53
  # @return [Boolean] whether file passed validation
58
- def validate(*args)
59
- load(*args) unless args.empty?
60
- raise Exception, "grammar not defined!" unless meta.grammar.defined?
61
- raise Exception, "document not loaded!" unless doc.root
54
+ def validate(path_or_doc, options={})
55
+ doc = path_or_doc.is_a?(Doc) ? path_or_doc : load(path_or_doc)
56
+ unless doc.grammar.defined?
57
+ raise Exception, "grammar not defined!" unless options[:grammar]
58
+ doc.grammar = options[:grammar]
59
+ end
60
+ raise Exception, "XML document has no root element!" unless doc.root
62
61
  results = []
63
- doc.root.traverse do |n| results << meta.grammar.validate(n) unless n.is_a?(String) end
62
+ doc.root.traverse do |n| results << doc.grammar.validate(n) unless n.is_a?(String) end
63
+ puts(doc.history.description) unless options[:quiet]
64
64
  !results.any? do |r| !r end
65
65
  end # def validate
66
66
 
67
- # @return [Nokogiri::XML::RelaxNG] current metadata's grammar as a relaxng file
68
- def relaxng
69
- #meta.grammar.relaxng
70
- end
71
-
72
67
  private
73
-
74
- # @return [Doc] @doc is set to either file given by user or new Doc
75
- def set_doc!
76
- @doc ||= if file.nil?
77
- f = Doc.new
78
- f.add_observer meta.history
79
- f
80
- else
81
- f = File.open file
82
- sax(f, meta.history)
83
- end
68
+ # @param g_path [String, GrammarClass] grammar to associate with @doc, which must be set to a Doc and not nil
69
+ def associate_grammar(g_path)
70
+ doc.grammar = g_path if g_path
84
71
  end
85
72
 
86
- # @return [MetaClass] @meta is set to either file extrapolated from path of XML-content file or new MetaClass
87
- def set_metadata!(grammar_path=nil)
88
- meta_path = Meta.meta_path(file)
89
- if file and File.exists?(meta_path)
90
- @meta = sax(File.open(meta_path)).root
91
- meta.grammar=grammar_path unless grammar_path.nil? or meta.grammar.defined?
92
- else
93
- @meta = MetaClass.new(grammar_path)
94
- end
95
- meta
73
+ def find_meta
74
+
96
75
  end
97
76
  end # module Duxml
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: duxml
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.2
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peter Kong
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-06-24 00:00:00.000000000 Z
11
+ date: 2016-08-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ox
@@ -38,7 +38,7 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '3.3'
41
- description: execute 'validate_xml --help' for more info
41
+ description: see README.md
42
42
  email:
43
43
  - peter.kong@nxp.com
44
44
  executables:
@@ -88,7 +88,6 @@ files:
88
88
  - lib/duxml/ruby_ext/string.rb
89
89
  - lib/duxml/saxer.rb
90
90
  - lib/duxml.rb
91
- - xml/dita_grammar.xml
92
91
  - bin/validate_xml
93
92
  homepage: http://www.github.com/ruby-dita/duxml
94
93
  licenses: