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 +4 -4
- data/bin/validate_xml +13 -1
- data/lib/duxml/doc/element.rb +31 -7
- data/lib/duxml/doc/lazy_ox.rb +152 -152
- data/lib/duxml/doc/node_set.rb +38 -38
- data/lib/duxml/doc.rb +67 -7
- data/lib/duxml/meta/grammar/pattern.rb +14 -0
- data/lib/duxml/meta/grammar/spreadsheet.rb +34 -34
- data/lib/duxml/meta/grammar.rb +3 -3
- data/lib/duxml/meta/history.rb +10 -9
- data/lib/duxml/meta.rb +20 -9
- data/lib/duxml/reportable.rb +28 -26
- data/lib/duxml/saxer.rb +4 -3
- data/lib/duxml.rb +42 -63
- metadata +3 -4
- data/xml/dita_grammar.xml +0 -2133
@@ -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
|
data/lib/duxml/meta/grammar.rb
CHANGED
@@ -50,9 +50,9 @@ module Duxml
|
|
50
50
|
end
|
51
51
|
end
|
52
52
|
|
53
|
-
# @return [
|
54
|
-
def
|
55
|
-
Element.new(
|
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
|
data/lib/duxml/meta/history.rb
CHANGED
@@ -27,10 +27,10 @@ module Duxml
|
|
27
27
|
|
28
28
|
def_delegators :@nodes, :[], :each
|
29
29
|
|
30
|
-
# @param
|
31
|
-
def initialize(
|
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 =
|
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 [
|
44
|
-
def
|
45
|
-
Element.new(
|
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?(
|
50
|
-
@strict =
|
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)
|
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
|
data/lib/duxml/reportable.rb
CHANGED
@@ -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
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
#
|
19
|
-
#
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
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
|
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
|
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
|
-
#
|
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 :
|
11
|
+
attr_reader :doc
|
19
12
|
|
20
|
-
# @param
|
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 [
|
15
|
+
# @return [Doc] XML document as Ruby object
|
23
16
|
def load(_file, grammar_path=nil)
|
24
|
-
|
25
|
-
|
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
|
-
|
28
|
-
File.write file, ''
|
23
|
+
meta = MetaClass.new(grammar_path)
|
29
24
|
end
|
30
25
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
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
|
-
|
43
|
-
|
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 [
|
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(
|
59
|
-
|
60
|
-
|
61
|
-
|
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 <<
|
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
|
-
|
75
|
-
|
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
|
-
|
87
|
-
|
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.
|
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-
|
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:
|
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:
|