xsdvi 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.
- checksums.yaml +7 -0
- data/LICENSE +30 -0
- data/README.adoc +317 -0
- data/exe/xsdvi +6 -0
- data/lib/xsdvi/cli.rb +163 -0
- data/lib/xsdvi/svg/generator.rb +93 -0
- data/lib/xsdvi/svg/symbol.rb +234 -0
- data/lib/xsdvi/svg/symbols/all.rb +46 -0
- data/lib/xsdvi/svg/symbols/any.rb +59 -0
- data/lib/xsdvi/svg/symbols/any_attribute.rb +58 -0
- data/lib/xsdvi/svg/symbols/attribute.rb +64 -0
- data/lib/xsdvi/svg/symbols/choice.rb +46 -0
- data/lib/xsdvi/svg/symbols/element.rb +91 -0
- data/lib/xsdvi/svg/symbols/field.rb +42 -0
- data/lib/xsdvi/svg/symbols/key.rb +46 -0
- data/lib/xsdvi/svg/symbols/keyref.rb +49 -0
- data/lib/xsdvi/svg/symbols/loop.rb +35 -0
- data/lib/xsdvi/svg/symbols/schema.rb +42 -0
- data/lib/xsdvi/svg/symbols/selector.rb +42 -0
- data/lib/xsdvi/svg/symbols/sequence.rb +48 -0
- data/lib/xsdvi/svg/symbols/unique.rb +46 -0
- data/lib/xsdvi/tree/builder.rb +31 -0
- data/lib/xsdvi/tree/element.rb +62 -0
- data/lib/xsdvi/utils/resource_loader.rb +21 -0
- data/lib/xsdvi/utils/width_calculator.rb +23 -0
- data/lib/xsdvi/utils/writer.rb +29 -0
- data/lib/xsdvi/version.rb +5 -0
- data/lib/xsdvi/xsd_handler.rb +323 -0
- data/lib/xsdvi.rb +30 -0
- data/resources/svg/defined_symbols.svg +9 -0
- data/resources/svg/doctype.txt +1 -0
- data/resources/svg/menu_buttons.svg +7 -0
- data/resources/svg/script.js +265 -0
- data/resources/svg/style.css +29 -0
- data/resources/svg/style.html +3 -0
- data/resources/svg/style.xml +1 -0
- data/resources/svg/svg_end.txt +1 -0
- data/resources/svg/svg_start.txt +1 -0
- data/resources/svg/title.txt +1 -0
- data/resources/svg/xml_declaration.xml +1 -0
- metadata +113 -0
|
@@ -0,0 +1,323 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "nokogiri"
|
|
4
|
+
|
|
5
|
+
module Xsdvi
|
|
6
|
+
# Handles XSD parsing and tree building
|
|
7
|
+
class XsdHandler
|
|
8
|
+
XSD_NAMESPACE = "http://www.w3.org/2001/XMLSchema"
|
|
9
|
+
|
|
10
|
+
attr_accessor :root_node_name, :one_node_only
|
|
11
|
+
attr_reader :builder, :schema_namespace
|
|
12
|
+
|
|
13
|
+
def initialize(builder)
|
|
14
|
+
@builder = builder
|
|
15
|
+
@stack = []
|
|
16
|
+
@root_node_name = nil
|
|
17
|
+
@one_node_only = false
|
|
18
|
+
@schema_namespace = nil
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def process_file(file_path)
|
|
22
|
+
doc = Nokogiri::XML(File.read(file_path))
|
|
23
|
+
process_model(doc)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def process_model(doc)
|
|
27
|
+
return unless doc
|
|
28
|
+
|
|
29
|
+
# Extract target namespace
|
|
30
|
+
schema_node = doc.at_xpath("/xs:schema", "xs" => XSD_NAMESPACE)
|
|
31
|
+
@schema_namespace = schema_node["targetNamespace"] if schema_node
|
|
32
|
+
|
|
33
|
+
# Create schema symbol when no root node specified (matches Java line 65-68)
|
|
34
|
+
if root_node_name.nil?
|
|
35
|
+
symbol = SVG::Symbols::Schema.new
|
|
36
|
+
builder.set_root(symbol)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
process_element_declarations(doc)
|
|
40
|
+
|
|
41
|
+
# Level up after processing all elements (matches Java line 71-73)
|
|
42
|
+
builder.level_up if root_node_name.nil?
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def get_elements_names(doc)
|
|
46
|
+
elements = doc.xpath("//xs:schema/xs:element", "xs" => XSD_NAMESPACE)
|
|
47
|
+
elements.filter_map { |elem| elem["name"] }
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def set_schema_namespace(doc, element_name)
|
|
51
|
+
elements = doc.xpath("//xs:schema/xs:element", "xs" => XSD_NAMESPACE)
|
|
52
|
+
elements.each do |elem|
|
|
53
|
+
if elem["name"] == element_name
|
|
54
|
+
@schema_namespace = schema_node = doc.at_xpath("/xs:schema",
|
|
55
|
+
"xs" => XSD_NAMESPACE)
|
|
56
|
+
@schema_namespace = schema_node["targetNamespace"] if schema_node
|
|
57
|
+
break
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
private
|
|
63
|
+
|
|
64
|
+
def process_element_declarations(doc)
|
|
65
|
+
elements = doc.xpath("//xs:schema/xs:element", "xs" => XSD_NAMESPACE)
|
|
66
|
+
|
|
67
|
+
elements.each do |elem|
|
|
68
|
+
name = elem["name"]
|
|
69
|
+
is_root = name == root_node_name
|
|
70
|
+
if is_root || root_node_name.nil?
|
|
71
|
+
process_element_declaration(elem, nil,
|
|
72
|
+
is_root)
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def process_element_declaration(elem_node, cardinality, is_root)
|
|
78
|
+
name = elem_node["name"]
|
|
79
|
+
elem_namespace = elem_node["namespace"]
|
|
80
|
+
elem_node["ref"]
|
|
81
|
+
type_attr = elem_node["type"]
|
|
82
|
+
nillable = elem_node["nillable"] == "true"
|
|
83
|
+
abstract = elem_node["abstract"] == "true"
|
|
84
|
+
|
|
85
|
+
symbol = SVG::Symbols::Element.new
|
|
86
|
+
symbol.name = name
|
|
87
|
+
|
|
88
|
+
# Set namespace if different from schema namespace (matches Java line 228-231)
|
|
89
|
+
if elem_namespace && elem_namespace != schema_namespace
|
|
90
|
+
symbol.namespace = elem_namespace
|
|
91
|
+
elsif schema_namespace && schema_namespace != elem_namespace
|
|
92
|
+
# Show schema namespace on element when element doesn't override it
|
|
93
|
+
symbol.namespace = schema_namespace
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# Get type string (matches Java getTypeString logic)
|
|
97
|
+
symbol.type = get_type_string(elem_node, type_attr)
|
|
98
|
+
symbol.cardinality = cardinality
|
|
99
|
+
symbol.nillable = nillable
|
|
100
|
+
symbol.abstract = abstract
|
|
101
|
+
symbol.description = extract_documentation(elem_node)
|
|
102
|
+
symbol.start_y_position = 20 if is_root && one_node_only
|
|
103
|
+
|
|
104
|
+
# Set root or append child (matches Java line 241-245)
|
|
105
|
+
if is_root
|
|
106
|
+
builder.set_root(symbol)
|
|
107
|
+
else
|
|
108
|
+
builder.append_child(symbol)
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
# Check for loops (matches Java line 247-250)
|
|
112
|
+
if process_loop?(elem_node)
|
|
113
|
+
builder.level_up
|
|
114
|
+
return
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
@stack.push(elem_node)
|
|
118
|
+
|
|
119
|
+
# Skip processing children if stack size > 1 and oneNodeOnly (matches Java line 253-260)
|
|
120
|
+
unless @stack.size > 1 && one_node_only
|
|
121
|
+
# Check if element has inline complexType
|
|
122
|
+
complex_type = elem_node.at_xpath("xs:complexType",
|
|
123
|
+
"xs" => XSD_NAMESPACE)
|
|
124
|
+
if complex_type
|
|
125
|
+
process_complex_type_node(complex_type)
|
|
126
|
+
elsif !type_attr
|
|
127
|
+
# No type means anyType - expand it
|
|
128
|
+
process_any_type_default
|
|
129
|
+
elsif type_attr == "anyType"
|
|
130
|
+
process_any_type_default
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
@stack.pop
|
|
135
|
+
builder.level_up
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def get_type_string(elem_node, type_attr)
|
|
139
|
+
return "type: #{type_attr}" if type_attr
|
|
140
|
+
|
|
141
|
+
# Check for inline simpleType or complexType
|
|
142
|
+
complex_type = elem_node.at_xpath("xs:complexType", "xs" => XSD_NAMESPACE)
|
|
143
|
+
simple_type = elem_node.at_xpath("xs:simpleType", "xs" => XSD_NAMESPACE)
|
|
144
|
+
|
|
145
|
+
return nil if complex_type # Anonymous complex type
|
|
146
|
+
|
|
147
|
+
if simple_type
|
|
148
|
+
return "base: #{simple_type.at_xpath('xs:restriction',
|
|
149
|
+
'xs' => XSD_NAMESPACE)['base']}"
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
"type: anyType" # Default
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
def process_any_type_default
|
|
156
|
+
# anyType default content model: sequence containing 0..unbounded any and anyAttribute
|
|
157
|
+
symbol = SVG::Symbols::Sequence.new
|
|
158
|
+
symbol.cardinality = nil
|
|
159
|
+
builder.append_child(symbol)
|
|
160
|
+
|
|
161
|
+
# Add any element
|
|
162
|
+
any_symbol = SVG::Symbols::Any.new
|
|
163
|
+
any_symbol.namespace = "any NS"
|
|
164
|
+
any_symbol.process_contents = SVG::Symbol::PC_LAX
|
|
165
|
+
any_symbol.cardinality = "0..∞"
|
|
166
|
+
builder.append_child(any_symbol)
|
|
167
|
+
builder.level_up
|
|
168
|
+
|
|
169
|
+
builder.level_up
|
|
170
|
+
|
|
171
|
+
# Add anyAttribute
|
|
172
|
+
any_attr_symbol = SVG::Symbols::AnyAttribute.new
|
|
173
|
+
any_attr_symbol.namespace = "any NS"
|
|
174
|
+
any_attr_symbol.process_contents = SVG::Symbol::PC_LAX
|
|
175
|
+
builder.append_child(any_attr_symbol)
|
|
176
|
+
builder.level_up
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
def process_complex_type_node(complex_type_node)
|
|
180
|
+
# Process particles (sequence/choice/all)
|
|
181
|
+
sequence = complex_type_node.at_xpath("xs:sequence",
|
|
182
|
+
"xs" => XSD_NAMESPACE)
|
|
183
|
+
process_sequence(sequence, nil) if sequence
|
|
184
|
+
|
|
185
|
+
choice = complex_type_node.at_xpath("xs:choice", "xs" => XSD_NAMESPACE)
|
|
186
|
+
process_choice(choice, nil) if choice
|
|
187
|
+
|
|
188
|
+
all_node = complex_type_node.at_xpath("xs:all", "xs" => XSD_NAMESPACE)
|
|
189
|
+
process_all(all_node, nil) if all_node
|
|
190
|
+
|
|
191
|
+
# Process attributes
|
|
192
|
+
attributes = complex_type_node.xpath("xs:attribute",
|
|
193
|
+
"xs" => XSD_NAMESPACE)
|
|
194
|
+
attributes.each { |attr| process_attribute(attr) }
|
|
195
|
+
|
|
196
|
+
# Process attribute wildcard
|
|
197
|
+
any_attr = complex_type_node.at_xpath("xs:anyAttribute",
|
|
198
|
+
"xs" => XSD_NAMESPACE)
|
|
199
|
+
process_any_attribute(any_attr) if any_attr
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
def process_sequence(sequence_node, cardinality)
|
|
203
|
+
card = cardinality || get_cardinality(sequence_node)
|
|
204
|
+
symbol = SVG::Symbols::Sequence.new
|
|
205
|
+
symbol.cardinality = card
|
|
206
|
+
symbol.description = extract_documentation(sequence_node)
|
|
207
|
+
builder.append_child(symbol)
|
|
208
|
+
|
|
209
|
+
# Process child elements
|
|
210
|
+
sequence_node.xpath("xs:element", "xs" => XSD_NAMESPACE).each do |elem|
|
|
211
|
+
process_element_declaration(elem, get_cardinality(elem), false)
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
# Process any
|
|
215
|
+
sequence_node.xpath("xs:any", "xs" => XSD_NAMESPACE).each do |any|
|
|
216
|
+
process_any(any)
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
builder.level_up
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
def process_choice(choice_node, cardinality)
|
|
223
|
+
card = cardinality || get_cardinality(choice_node)
|
|
224
|
+
symbol = SVG::Symbols::Choice.new
|
|
225
|
+
symbol.cardinality = card
|
|
226
|
+
symbol.description = extract_documentation(choice_node)
|
|
227
|
+
builder.append_child(symbol)
|
|
228
|
+
|
|
229
|
+
# Process child elements
|
|
230
|
+
choice_node.xpath("xs:element", "xs" => XSD_NAMESPACE).each do |elem|
|
|
231
|
+
process_element_declaration(elem, get_cardinality(elem), false)
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
builder.level_up
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
def process_all(all_node, cardinality)
|
|
238
|
+
card = cardinality || get_cardinality(all_node)
|
|
239
|
+
symbol = SVG::Symbols::All.new
|
|
240
|
+
symbol.cardinality = card
|
|
241
|
+
symbol.description = extract_documentation(all_node)
|
|
242
|
+
builder.append_child(symbol)
|
|
243
|
+
|
|
244
|
+
# Process child elements
|
|
245
|
+
all_node.xpath("xs:element", "xs" => XSD_NAMESPACE).each do |elem|
|
|
246
|
+
process_element_declaration(elem, get_cardinality(elem), false)
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
builder.level_up
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
def process_any(any_node)
|
|
253
|
+
symbol = SVG::Symbols::Any.new
|
|
254
|
+
namespace = any_node["namespace"]
|
|
255
|
+
symbol.namespace = namespace || "any NS"
|
|
256
|
+
process_contents = any_node["processContents"]
|
|
257
|
+
symbol.process_contents = case process_contents
|
|
258
|
+
when "skip" then SVG::Symbol::PC_SKIP
|
|
259
|
+
when "lax" then SVG::Symbol::PC_LAX
|
|
260
|
+
when "strict" then SVG::Symbol::PC_STRICT
|
|
261
|
+
else SVG::Symbol::PC_LAX # Default is lax for anyType
|
|
262
|
+
end
|
|
263
|
+
symbol.cardinality = get_cardinality(any_node)
|
|
264
|
+
symbol.description = extract_documentation(any_node)
|
|
265
|
+
builder.append_child(symbol)
|
|
266
|
+
builder.level_up
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
def process_attribute(attr_node)
|
|
270
|
+
symbol = SVG::Symbols::Attribute.new
|
|
271
|
+
symbol.name = attr_node["name"]
|
|
272
|
+
namespace = attr_node["namespace"]
|
|
273
|
+
symbol.namespace = namespace if namespace && namespace != schema_namespace
|
|
274
|
+
symbol.type = attr_node["type"] ? "type: #{attr_node['type']}" : nil
|
|
275
|
+
symbol.required = attr_node["use"] == "required"
|
|
276
|
+
symbol.description = extract_documentation(attr_node)
|
|
277
|
+
|
|
278
|
+
builder.append_child(symbol)
|
|
279
|
+
builder.level_up
|
|
280
|
+
end
|
|
281
|
+
|
|
282
|
+
def process_any_attribute(any_attr_node)
|
|
283
|
+
symbol = SVG::Symbols::AnyAttribute.new
|
|
284
|
+
namespace = any_attr_node["namespace"]
|
|
285
|
+
symbol.namespace = namespace || "any NS"
|
|
286
|
+
process_contents = any_attr_node["processContents"]
|
|
287
|
+
symbol.process_contents = case process_contents
|
|
288
|
+
when "skip" then SVG::Symbol::PC_SKIP
|
|
289
|
+
when "lax" then SVG::Symbol::PC_LAX
|
|
290
|
+
when "strict" then SVG::Symbol::PC_STRICT
|
|
291
|
+
else SVG::Symbol::PC_LAX # Default is lax for anyType
|
|
292
|
+
end
|
|
293
|
+
symbol.description = extract_documentation(any_attr_node)
|
|
294
|
+
builder.append_child(symbol)
|
|
295
|
+
builder.level_up
|
|
296
|
+
end
|
|
297
|
+
|
|
298
|
+
def process_loop?(elem_node)
|
|
299
|
+
@stack.any?(elem_node)
|
|
300
|
+
end
|
|
301
|
+
|
|
302
|
+
def get_cardinality(node)
|
|
303
|
+
min_occurs = node["minOccurs"]&.to_i || 1
|
|
304
|
+
max_occurs = node["maxOccurs"]
|
|
305
|
+
|
|
306
|
+
return nil if min_occurs == 1 && (max_occurs.nil? || max_occurs == "1")
|
|
307
|
+
|
|
308
|
+
if max_occurs == "unbounded"
|
|
309
|
+
"#{min_occurs}..∞"
|
|
310
|
+
elsif max_occurs
|
|
311
|
+
"#{min_occurs}..#{max_occurs}"
|
|
312
|
+
end
|
|
313
|
+
end
|
|
314
|
+
|
|
315
|
+
def extract_documentation(node)
|
|
316
|
+
docs = node.xpath(
|
|
317
|
+
".//xs:annotation/xs:documentation",
|
|
318
|
+
"xs" => XSD_NAMESPACE,
|
|
319
|
+
)
|
|
320
|
+
docs.map(&:text).map { |text| text.gsub(/\n[ \t]+/, "\n") }
|
|
321
|
+
end
|
|
322
|
+
end
|
|
323
|
+
end
|
data/lib/xsdvi.rb
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "xsdvi/version"
|
|
4
|
+
require_relative "xsdvi/cli"
|
|
5
|
+
require_relative "xsdvi/xsd_handler"
|
|
6
|
+
require_relative "xsdvi/tree/element"
|
|
7
|
+
require_relative "xsdvi/tree/builder"
|
|
8
|
+
require_relative "xsdvi/svg/generator"
|
|
9
|
+
require_relative "xsdvi/svg/symbol"
|
|
10
|
+
require_relative "xsdvi/svg/symbols/all"
|
|
11
|
+
require_relative "xsdvi/svg/symbols/any"
|
|
12
|
+
require_relative "xsdvi/svg/symbols/any_attribute"
|
|
13
|
+
require_relative "xsdvi/svg/symbols/attribute"
|
|
14
|
+
require_relative "xsdvi/svg/symbols/choice"
|
|
15
|
+
require_relative "xsdvi/svg/symbols/element"
|
|
16
|
+
require_relative "xsdvi/svg/symbols/field"
|
|
17
|
+
require_relative "xsdvi/svg/symbols/key"
|
|
18
|
+
require_relative "xsdvi/svg/symbols/keyref"
|
|
19
|
+
require_relative "xsdvi/svg/symbols/loop"
|
|
20
|
+
require_relative "xsdvi/svg/symbols/schema"
|
|
21
|
+
require_relative "xsdvi/svg/symbols/selector"
|
|
22
|
+
require_relative "xsdvi/svg/symbols/sequence"
|
|
23
|
+
require_relative "xsdvi/svg/symbols/unique"
|
|
24
|
+
require_relative "xsdvi/utils/writer"
|
|
25
|
+
require_relative "xsdvi/utils/resource_loader"
|
|
26
|
+
require_relative "xsdvi/utils/width_calculator"
|
|
27
|
+
|
|
28
|
+
module Xsdvi
|
|
29
|
+
class Error < StandardError; end
|
|
30
|
+
end
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
<symbol class='button' id='plus'>
|
|
2
|
+
<rect x='1' y='1' width='10' height='10'/>
|
|
3
|
+
<line x1='3' y1='6' x2='9' y2='6'/>
|
|
4
|
+
<line x1='6' y1='3' x2='6' y2='9'/>
|
|
5
|
+
</symbol>
|
|
6
|
+
<symbol class='button' id='minus'>
|
|
7
|
+
<rect x='1' y='1' width='10' height='10'/>
|
|
8
|
+
<line x1='3' y1='6' x2='9' y2='6'/>
|
|
9
|
+
</symbol>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'>
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
<rect class='button' x='300' y='10' width='20' height='20' onclick='collapseAll()'/>
|
|
2
|
+
<line x1='303' y1='20' x2='317' y2='20'/>
|
|
3
|
+
<text x='330' y='20'>collapse all</text>
|
|
4
|
+
<rect class='button' x='400' y='10' width='20' height='20' onclick='expandAll()'/>
|
|
5
|
+
<line x1='403' y1='20' x2='417' y2='20'/>
|
|
6
|
+
<line x1='410' y1='13' x2='410' y2='27'/>
|
|
7
|
+
<text x='430' y='20'>expand all</text>
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
<script type='text/ecmascript'><![CDATA[
|
|
2
|
+
|
|
3
|
+
var efBoxes = [];
|
|
4
|
+
var eSvg = null;
|
|
5
|
+
|
|
6
|
+
////////// loadSVG()
|
|
7
|
+
function loadSVG() {
|
|
8
|
+
efBoxes = getElementsByClassName('box', document.getElementsByTagName('g'));
|
|
9
|
+
eSvg = document.getElementById('svg');
|
|
10
|
+
expandAll();
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
////////// getElementsByClassName(string, nodeList)
|
|
14
|
+
function getElementsByClassName(sClass, nlNodes) {
|
|
15
|
+
var elements = [];
|
|
16
|
+
for (var i=0; i<nlNodes.length; i++) {
|
|
17
|
+
if(nlNodes.item(i).nodeType==1 && sClass==nlNodes.item(i).getAttribute('class')) {
|
|
18
|
+
elements.push(nlNodes.item(i));
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return elements;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
////////// show(string)
|
|
25
|
+
function show(sId) {
|
|
26
|
+
var useElement = document.getElementById('s'+sId);
|
|
27
|
+
var moveNext = false;
|
|
28
|
+
var eBoxLast;
|
|
29
|
+
var maxX = 500;
|
|
30
|
+
|
|
31
|
+
if (notPlus(useElement)) {
|
|
32
|
+
eBoxLast = document.getElementById(sId);
|
|
33
|
+
setPlus(useElement);
|
|
34
|
+
for (var i=0; i<efBoxes.length; i++) {
|
|
35
|
+
var eBox = efBoxes[i];
|
|
36
|
+
if (moveNext) {
|
|
37
|
+
move(eBoxLast, eBox);
|
|
38
|
+
}
|
|
39
|
+
else if (isDescendant(sId, eBox.id)) {
|
|
40
|
+
eBox.setAttribute('visibility', 'hidden');
|
|
41
|
+
}
|
|
42
|
+
else if (isHigherBranch(sId, eBox.id)) {
|
|
43
|
+
move(eBoxLast, eBox);
|
|
44
|
+
moveNext = true;
|
|
45
|
+
}
|
|
46
|
+
if (eBox.getAttribute('visibility') != 'hidden') {
|
|
47
|
+
eBoxLast = eBox;
|
|
48
|
+
x = xTrans(eBox);
|
|
49
|
+
if (x > maxX) maxX = x;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
else {
|
|
55
|
+
setMinus(useElement);
|
|
56
|
+
var skipDescendantsOf;
|
|
57
|
+
for (var i=0; i<efBoxes.length; i++) {
|
|
58
|
+
var eBox = efBoxes[i];
|
|
59
|
+
if (moveNext) {
|
|
60
|
+
move(eBoxLast, eBox);
|
|
61
|
+
}
|
|
62
|
+
else if (isDescendant(sId, eBox.id) && (!skipDescendantsOf || !isDescendant(skipDescendantsOf.id, eBox.id))) {
|
|
63
|
+
eBox.setAttribute('visibility', 'visible');
|
|
64
|
+
move(eBoxLast, eBox);
|
|
65
|
+
if (nextClosed(eBox)) skipDescendantsOf = eBox;
|
|
66
|
+
}
|
|
67
|
+
else if (isHigherBranch(sId, eBox.id)) {
|
|
68
|
+
move(eBoxLast, eBox);
|
|
69
|
+
moveNext = true;
|
|
70
|
+
}
|
|
71
|
+
if (eBox.getAttribute('visibility') != 'hidden') {
|
|
72
|
+
eBoxLast = eBox;
|
|
73
|
+
x = xTrans(eBox);
|
|
74
|
+
if (x > maxX) maxX = x;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
//setHeight(yTrans(eBoxLast)+"+(AbstractSymbol.MAX_HEIGHT+AbstractSymbol.Y_INDENT)+");\n"+
|
|
79
|
+
setHeight(yTrans(eBoxLast)+%HEIGHT_SUM%);
|
|
80
|
+
setWidth(maxX+360);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
////////// collapseAll()
|
|
84
|
+
function collapseAll() {
|
|
85
|
+
for (var i=0; i<efBoxes.length; i++) {
|
|
86
|
+
var eBox = efBoxes[i];
|
|
87
|
+
var useElement = document.getElementById('s'+eBox.id);
|
|
88
|
+
if (useElement) setPlus(useElement);
|
|
89
|
+
if (eBox.id != '_1') eBox.setAttribute('visibility', 'hidden');
|
|
90
|
+
}
|
|
91
|
+
setHeight(400);
|
|
92
|
+
setWidth(500);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
////////// expandAll()
|
|
96
|
+
function expandAll() {
|
|
97
|
+
var eBoxLast;
|
|
98
|
+
var maxX = 0;
|
|
99
|
+
for (var i=0; i<efBoxes.length; i++) {
|
|
100
|
+
var eBox = efBoxes[i];
|
|
101
|
+
var useElement = document.getElementById('s'+eBox.id);
|
|
102
|
+
if (useElement) setMinus(useElement);
|
|
103
|
+
move(eBoxLast, eBox);
|
|
104
|
+
eBox.setAttribute('visibility', 'visible');
|
|
105
|
+
eBoxLast = eBox;
|
|
106
|
+
var x = xTrans(eBox);
|
|
107
|
+
if (x > maxX) maxX = x;
|
|
108
|
+
}
|
|
109
|
+
//setHeight(yTrans(eBoxLast)+"+(AbstractSymbol.MAX_HEIGHT+AbstractSymbol.Y_INDENT)+");\n"+
|
|
110
|
+
setHeight(yTrans(eBoxLast)+%HEIGHT_SUM%);
|
|
111
|
+
setWidth(maxX+360);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
////////// makeVisible(string)
|
|
115
|
+
function makeVisible(sId) {
|
|
116
|
+
var childNodes = document.getElementById(sId).childNodes;
|
|
117
|
+
var hidden = getElementsByClassName('hidden', childNodes);
|
|
118
|
+
var visible = getElementsByClassName('visible', childNodes);
|
|
119
|
+
inheritVisibility(hidden);
|
|
120
|
+
hiddenVisibility(visible);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
////////// makeHidden(string)
|
|
124
|
+
function makeHidden(sId) {
|
|
125
|
+
var childNodes = document.getElementById(sId).childNodes;
|
|
126
|
+
var hidden = getElementsByClassName('hidden', childNodes);
|
|
127
|
+
var visible = getElementsByClassName('visible', childNodes);
|
|
128
|
+
inheritVisibility(visible);
|
|
129
|
+
hiddenVisibility(hidden);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
////////// inheritVisibility(element[])
|
|
133
|
+
function inheritVisibility(efElements) {
|
|
134
|
+
for (var i=0; i<efElements.length; i++) {
|
|
135
|
+
efElements[i].setAttribute('visibility', 'inherit');
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
////////// hiddenVisibility(element[])
|
|
140
|
+
function hiddenVisibility(efElements) {
|
|
141
|
+
for (var i=0; i<efElements.length; i++) {
|
|
142
|
+
efElements[i].setAttribute('visibility', 'hidden');
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
////////// nextClosed(element)
|
|
147
|
+
function nextClosed(eBox) {
|
|
148
|
+
var useElement = document.getElementById('s'+eBox.id);
|
|
149
|
+
return (useElement && !notPlus(useElement));
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
////////// isHigherBranch(string, string)
|
|
153
|
+
function isHigherBranch(sSerialLower, sSerialHigher) {
|
|
154
|
+
var sLower = sSerialLower.split('_');
|
|
155
|
+
var sHigher = sSerialHigher.split('_');
|
|
156
|
+
for (var i=0; i<sLower.length; i++) {
|
|
157
|
+
if (Number(sHigher[i]) > Number(sLower[i])) return true;
|
|
158
|
+
else if (Number(sHigher[i]) < Number(sLower[i])) return false;
|
|
159
|
+
}
|
|
160
|
+
return false;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
////////// isOnHigherLevel(element, element)
|
|
164
|
+
function isOnHigherLevel(eBoxLower, eBoxHigher) {
|
|
165
|
+
var sLower = eBoxLower.id.split('_');
|
|
166
|
+
var sHigher = eBoxHigher.id.split('_');
|
|
167
|
+
for (var i=0; i<sLower.length; i++) {
|
|
168
|
+
if (Number(sHigher[i]) > Number(sLower[i])) return true;
|
|
169
|
+
}
|
|
170
|
+
return false;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
////////// isDescendant(string, string)
|
|
174
|
+
function isDescendant(sSerialAsc, sSerialDesc) {
|
|
175
|
+
return (sSerialDesc.length > sSerialAsc.length && sSerialDesc.indexOf(sSerialAsc) === 0);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
////////// getParent(element)
|
|
179
|
+
function getParent(eBox) {
|
|
180
|
+
var serial = eBox.id.substring(0, eBox.id.lastIndexOf('_'));
|
|
181
|
+
return document.getElementById(serial);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
////////// move(element, element)
|
|
185
|
+
function move(eBoxLast, eBox) {
|
|
186
|
+
if (!eBoxLast) return;
|
|
187
|
+
if (isOnHigherLevel(eBoxLast, eBox)) {
|
|
188
|
+
//setYTrans(eBox, yTrans(eBoxLast)+"+(AbstractSymbol.MAX_HEIGHT+AbstractSymbol.Y_INDENT)+");\n"+
|
|
189
|
+
var attDescHeight = eBoxLast.getAttribute('data-desc-height-rest');
|
|
190
|
+
var attDescX = Number(eBoxLast.getAttribute('data-desc-x'));
|
|
191
|
+
var attX = xTrans(eBox);
|
|
192
|
+
var descHeight = Number(attDescHeight);
|
|
193
|
+
var heightAddon = 0;
|
|
194
|
+
|
|
195
|
+
var currWidth = eBox.getElementsByClassName("shadow")[0];
|
|
196
|
+
if (currWidth) {
|
|
197
|
+
currWidth = Number(currWidth.getAttribute("width"));
|
|
198
|
+
} else {
|
|
199
|
+
currWidth = 0;
|
|
200
|
+
}
|
|
201
|
+
if(descHeight && ((attDescX >= attX && attDescX < attX + currWidth) || (attX < attDescX))) heightAddon = descHeight;
|
|
202
|
+
|
|
203
|
+
setYTrans(eBox, yTrans(eBoxLast)+%HEIGHT_SUM%+heightAddon);
|
|
204
|
+
var parent = getParent(eBox);
|
|
205
|
+
var line = document.getElementById('p'+eBox.id);
|
|
206
|
+
if (!parent || !line) return;
|
|
207
|
+
//" line.y1.baseVal.valueInSpecifiedUnits = yTrans(parent)-yTrans(eBox)+"+AbstractSymbol.MAX_HEIGHT/2+";
|
|
208
|
+
//line.setAttribute('y1', String(yTrans(parent)-yTrans(eBox)+"+AbstractSymbol.MAX_HEIGHT/2+"));\n"+
|
|
209
|
+
line.setAttribute('y1', String(yTrans(parent)-yTrans(eBox)+%HEIGHT_HALF%));
|
|
210
|
+
}
|
|
211
|
+
else {
|
|
212
|
+
setYTrans(eBox, yTrans(eBoxLast));
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
////////// notPlus(element)
|
|
217
|
+
function notPlus(eUseElement) {
|
|
218
|
+
return (eUseElement.getAttributeNS('http://www.w3.org/1999/xlink', 'href') != '#plus');
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
////////// setPlus(element)
|
|
222
|
+
function setPlus(eUseElement) {
|
|
223
|
+
eUseElement.setAttributeNS('http://www.w3.org/1999/xlink', 'href', '#plus');
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
////////// setMinus(element)
|
|
227
|
+
function setMinus(eUseElement) {
|
|
228
|
+
eUseElement.setAttributeNS('http://www.w3.org/1999/xlink', 'href', '#minus');
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
////////// setHeight(number)
|
|
232
|
+
function setHeight(nHeight) {
|
|
233
|
+
eSvg.setAttribute('height', nHeight);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
////////// setWidth(number)
|
|
237
|
+
function setWidth(nWidth) {
|
|
238
|
+
eSvg.setAttribute('width', nWidth);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
////////// xyTrans(element)
|
|
242
|
+
function xTrans(eBox) {
|
|
243
|
+
//" return eBox.transform.baseVal.getItem(0).matrix.e;
|
|
244
|
+
var transform = eBox.getAttribute('transform');
|
|
245
|
+
var x = Number(transform.substring(10, Number(transform.length)-1).split(',')[0]);
|
|
246
|
+
if(!x) x = 0;
|
|
247
|
+
return x;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
////////// yTrans(element)
|
|
251
|
+
function yTrans(eBox) {
|
|
252
|
+
//" return eBox.transform.baseVal.getItem(0).matrix.f;
|
|
253
|
+
var transform = eBox.getAttribute('transform');
|
|
254
|
+
var y = Number(transform.substring(10, Number(transform.length)-1).split(',')[1]);
|
|
255
|
+
if(!y) y = 0;
|
|
256
|
+
return y;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
////////// setYTrans(element, number)
|
|
260
|
+
function setYTrans(eBox, nValue) {
|
|
261
|
+
//" return eBox.transform.baseVal.getItem(0).matrix.f = nValue;
|
|
262
|
+
eBox.setAttribute('transform', 'translate('+xTrans(eBox)+','+nValue+')');
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
]]></script>
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
svg {pointer-events: none;}
|
|
2
|
+
text {font-family: arial; font-size: 11px;}
|
|
3
|
+
line, polyline, polygon {fill: none; stroke: black;}
|
|
4
|
+
|
|
5
|
+
.strong {font-size: 12px; font-weight: bold;}
|
|
6
|
+
.small {font-size: 10px;}
|
|
7
|
+
.big {font-size: 15px; fill: #882222;}
|
|
8
|
+
|
|
9
|
+
.button {fill: white; stroke: black; pointer-events: all;}
|
|
10
|
+
.shadow {fill: #ccccd8; stroke: none;}
|
|
11
|
+
.connection {fill: none; stroke: #666666;}
|
|
12
|
+
.empty {fill: none; stroke: black;}
|
|
13
|
+
.filled {fill: black; stroke: none;}
|
|
14
|
+
|
|
15
|
+
.boxelement, .boxany, .boxattribute1, .boxanyattribute {fill: #FFFFBB; stroke: #776633; pointer-events: all;}
|
|
16
|
+
.boxelementoptional {fill: #FFFFBB; stroke: #776633; pointer-events: all; stroke-dasharray: 2;}
|
|
17
|
+
.boxattribute2 {fill: #FFFFBB; stroke: #776633; pointer-events: all; stroke-dasharray: 2;}
|
|
18
|
+
.boxschema, .boxloop, .boxcompositor {fill: #E7EBF3; stroke: #666677;}
|
|
19
|
+
.boxselector, .boxfield, .boxidc {fill: #E0F7B7; stroke: #667733;}
|
|
20
|
+
|
|
21
|
+
.lax {fill: white; stroke: black;}
|
|
22
|
+
.skip {fill: #cc6666; stroke: black;}
|
|
23
|
+
.strict {fill: black; stroke: none;}
|
|
24
|
+
|
|
25
|
+
.border {fill: #f9f9f9; stroke: #dddddd;}
|
|
26
|
+
|
|
27
|
+
.elementlink {fill: blue;}
|
|
28
|
+
|
|
29
|
+
.desc {fill: #888888;}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<?xml-stylesheet href='%STYLE_URI%' type='text/css'?>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
</svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg id='svg' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' onload='loadSVG();'>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<title>XsdVi</title>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<?xml version='1.0' encoding='UTF-8'?>
|