duxml 0.7.2 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- 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:
|