xsdvi 1.0.0 → 1.0.1
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/README.adoc +364 -6
- data/lib/xsdvi/cli.rb +162 -10
- data/lib/xsdvi/comparison/dual_generator.rb +190 -0
- data/lib/xsdvi/comparison/html_generator.rb +181 -0
- data/lib/xsdvi/comparison/java_manager.rb +124 -0
- data/lib/xsdvi/comparison/metadata_extractor.rb +75 -0
- data/lib/xsdvi/svg/generator.rb +1 -0
- data/lib/xsdvi/svg/symbol.rb +39 -30
- data/lib/xsdvi/svg/symbols/attribute.rb +1 -1
- data/lib/xsdvi/svg/symbols/element.rb +1 -1
- data/lib/xsdvi/version.rb +1 -1
- data/lib/xsdvi/xsd_handler.rb +459 -24
- data/lib/xsdvi.rb +6 -0
- data/resources/comparison/template.html +234 -0
- data/resources/svg/defined_symbols.svg +9 -9
- data/resources/svg/menu_buttons.svg +6 -6
- data/resources/svg/script.js +264 -264
- data/resources/svg/style.css +28 -28
- data/resources/svg/style.html +2 -2
- metadata +7 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 819798e045b576a5f2b55d8d80e6997c489c3d17988e30bbdace382be737f757
|
|
4
|
+
data.tar.gz: 7889f66439924400696c219fc0011f468580d56ad9a42a9cde21b0ef0d4995d0
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 997ebdc3af70469940d70e129302edb19f8226be440c94cb7093520107a6ce02a6e8115c6912e9b8cd8a80239efd41f8cb6fcba88c791b40d8df7579024795d8
|
|
7
|
+
data.tar.gz: 27a2ae348887b91af15a75172bb2d42c643384c74b389645385541b81879e369eed9f9ec2f8bb99db8450fe8196fc7dc05f7eda5b5f38dfbbd705a8dae2a6027
|
data/README.adoc
CHANGED
|
@@ -27,7 +27,7 @@ Ruby projects.
|
|
|
27
27
|
|
|
28
28
|
== Features
|
|
29
29
|
|
|
30
|
-
=== XSD
|
|
30
|
+
=== XSD component visualization
|
|
31
31
|
|
|
32
32
|
* Elements and Attributes: Visual boxes showing element names, types, cardinality (min..max occurrences), required/optional status, and namespace information
|
|
33
33
|
* Compositors: Graphical representation of sequence (ordered), choice (alternatives), and all (unordered) element groups
|
|
@@ -35,7 +35,7 @@ Ruby projects.
|
|
|
35
35
|
* Identity Constraints: Visualization of key, keyref, unique constraints with their selectors and fields
|
|
36
36
|
* Type Information: Display of simple and complex type definitions, base types, and anonymous types
|
|
37
37
|
|
|
38
|
-
=== Interactive SVG
|
|
38
|
+
=== Interactive SVG output
|
|
39
39
|
|
|
40
40
|
* Hierarchical Layout: Tree-structure visualization with proper indentation and connections
|
|
41
41
|
* Collapsible/Expandable: JavaScript-enabled expand/collapse functionality for complex schemas (optional)
|
|
@@ -43,20 +43,21 @@ Ruby projects.
|
|
|
43
43
|
* Documentation Display: Inline display of `<xs:documentation>` annotations
|
|
44
44
|
* Color-coded Symbols: Different visual styles for elements, attributes, compositors, and constraints
|
|
45
45
|
|
|
46
|
-
=== Flexible
|
|
46
|
+
=== Flexible output options
|
|
47
47
|
|
|
48
48
|
* Single Diagram: Generate one SVG showing the entire schema or a specific root element
|
|
49
49
|
* Per-Element Diagrams: Generate separate SVG files for each top-level element
|
|
50
50
|
* Custom Styling: Embed CSS in SVG files or use external stylesheets
|
|
51
51
|
* Output Directory: Organize generated diagrams in custom folder structures
|
|
52
52
|
|
|
53
|
-
=== Processing
|
|
53
|
+
=== Processing capabilities
|
|
54
54
|
|
|
55
55
|
* Multiple XSD Files: Process multiple schema files in a single run
|
|
56
56
|
* Loop Detection: Automatically detects and marks recursive element references
|
|
57
57
|
* Namespace Handling: Properly displays and distinguishes multiple namespaces
|
|
58
58
|
* Documentation Extraction: Extracts and formats XSD documentation for display
|
|
59
59
|
* Large Schema Support: Handles complex, real-world schemas with hundreds of elements
|
|
60
|
+
* Type Resolution: Comprehensive resolution of named types, group references, attribute groups, element references, and type inheritance (extension/restriction)
|
|
60
61
|
|
|
61
62
|
== Installation
|
|
62
63
|
|
|
@@ -194,6 +195,104 @@ Creates `output/schema.svg` and `output/custom.css`, with the SVG referencing
|
|
|
194
195
|
the external stylesheet. Useful for customizing diagram appearance.
|
|
195
196
|
====
|
|
196
197
|
|
|
198
|
+
=== Comparing Java and Ruby outputs
|
|
199
|
+
|
|
200
|
+
The `compare` command generates side-by-side visual comparisons of Java XsdVi
|
|
201
|
+
v1.3 and Ruby XsdVi outputs. This is useful for validation, documentation, and
|
|
202
|
+
visual quality assurance.
|
|
203
|
+
|
|
204
|
+
==== Basic comparison
|
|
205
|
+
|
|
206
|
+
[source,shell]
|
|
207
|
+
----
|
|
208
|
+
xsdvi compare schema.xsd
|
|
209
|
+
----
|
|
210
|
+
|
|
211
|
+
This command:
|
|
212
|
+
|
|
213
|
+
1. Automatically downloads Java XsdVi JAR v1.3 (first run only, cached in `~/.xsdvi/`)
|
|
214
|
+
2. Generates SVGs using both Java and Ruby implementations
|
|
215
|
+
3. Extracts metadata and symbol counts from both outputs
|
|
216
|
+
4. Creates an interactive HTML comparison page in `comparisons/<schema>-<timestamp>/`
|
|
217
|
+
|
|
218
|
+
==== Comparison command options
|
|
219
|
+
|
|
220
|
+
`-r, --root-node-name NAME`::
|
|
221
|
+
Specify the schema root element to visualize (same as `generate` command). Use "all" to generate comparisons for all top-level elements.
|
|
222
|
+
|
|
223
|
+
`-o, --output-path PATH`::
|
|
224
|
+
Specify output directory for comparison files. Default: `comparisons/<schema>-<timestamp>/`
|
|
225
|
+
|
|
226
|
+
`--skip-java`::
|
|
227
|
+
Skip Java generation and use existing Java outputs. Useful when re-running comparison with updated Ruby code.
|
|
228
|
+
|
|
229
|
+
`--skip-ruby`::
|
|
230
|
+
Skip Ruby generation and use existing Ruby outputs. Useful for comparing against manually generated Ruby outputs.
|
|
231
|
+
|
|
232
|
+
`-O, --open`::
|
|
233
|
+
Automatically open the comparison HTML in your default browser after generation.
|
|
234
|
+
|
|
235
|
+
==== Comparison examples
|
|
236
|
+
|
|
237
|
+
.Basic comparison
|
|
238
|
+
[example]
|
|
239
|
+
====
|
|
240
|
+
[source,shell]
|
|
241
|
+
----
|
|
242
|
+
xsdvi compare UnitsML-v1.0.xsd -r UnitsML
|
|
243
|
+
----
|
|
244
|
+
|
|
245
|
+
Downloads Java XsdVi (if needed), generates SVGs with both implementations, and creates an interactive comparison showing:
|
|
246
|
+
|
|
247
|
+
* Side-by-side SVG iframes
|
|
248
|
+
* Statistics table comparing file sizes and symbol counts
|
|
249
|
+
* Generation time for each implementation
|
|
250
|
+
* Visual diff highlighting any differences
|
|
251
|
+
====
|
|
252
|
+
|
|
253
|
+
.Compare all elements with auto-open
|
|
254
|
+
[example]
|
|
255
|
+
====
|
|
256
|
+
[source,shell]
|
|
257
|
+
----
|
|
258
|
+
xsdvi compare schema.xsd -r all -O
|
|
259
|
+
----
|
|
260
|
+
|
|
261
|
+
Generates comparison for all top-level elements and automatically opens the comparison page in your browser. The HTML includes an element selector dropdown to switch between different element diagrams.
|
|
262
|
+
====
|
|
263
|
+
|
|
264
|
+
.Compare using existing Java output
|
|
265
|
+
[example]
|
|
266
|
+
====
|
|
267
|
+
[source,shell]
|
|
268
|
+
----
|
|
269
|
+
xsdvi compare schema.xsd --skip-java -o my-comparison
|
|
270
|
+
----
|
|
271
|
+
|
|
272
|
+
Reuses existing Java output and generates fresh Ruby output, useful during Ruby development to quickly validate changes without regenerating Java outputs.
|
|
273
|
+
====
|
|
274
|
+
|
|
275
|
+
==== Comparison output structure
|
|
276
|
+
|
|
277
|
+
After running a comparison, you get:
|
|
278
|
+
|
|
279
|
+
[source]
|
|
280
|
+
----
|
|
281
|
+
comparisons/<schema>-<timestamp>/
|
|
282
|
+
├── java/
|
|
283
|
+
│ └── <schema>.svg # Java XsdVi output
|
|
284
|
+
├── ruby/
|
|
285
|
+
│ └── <schema>.svg # Ruby XsdVi output
|
|
286
|
+
└── comparison.html # Interactive comparison page
|
|
287
|
+
----
|
|
288
|
+
|
|
289
|
+
The comparison HTML displays:
|
|
290
|
+
|
|
291
|
+
* **Statistics table**: File counts, sizes, symbol counts by type, generation times
|
|
292
|
+
* **Visual indicators**: Green checkmarks for matches, red X for mismatches
|
|
293
|
+
* **Split-screen view**: Java output (left) and Ruby output (right) in synchronized iframes
|
|
294
|
+
* **Element selector**: Dropdown to switch between elements (when using `-r all`)
|
|
295
|
+
|
|
197
296
|
== Architecture
|
|
198
297
|
|
|
199
298
|
=== Core components
|
|
@@ -231,15 +330,122 @@ options with built-in help and validation.
|
|
|
231
330
|
----
|
|
232
331
|
XSD File → XsdHandler (Nokogiri parsing)
|
|
233
332
|
↓
|
|
234
|
-
|
|
333
|
+
Type Registry Collection (complexTypes, simpleTypes, groups, etc.)
|
|
334
|
+
↓
|
|
335
|
+
Symbol Tree Building (TreeBuilder with on-demand type resolution)
|
|
235
336
|
↓
|
|
236
337
|
Symbol Processing (prepare_box, calculate dimensions)
|
|
237
338
|
↓
|
|
238
|
-
SVG Generation (
|
|
339
|
+
SVG Generation (recursive drawing)
|
|
239
340
|
↓
|
|
240
341
|
SVG File Output
|
|
241
342
|
----
|
|
242
343
|
|
|
344
|
+
=== Type resolution architecture
|
|
345
|
+
|
|
346
|
+
The type resolution system is the core feature that enables XSDVI to correctly process all XSD schema structures. It resolves references to named types, groups, and elements, and handles type inheritance patterns.
|
|
347
|
+
|
|
348
|
+
==== Resolution mechanisms
|
|
349
|
+
|
|
350
|
+
The system implements six resolution mechanisms:
|
|
351
|
+
|
|
352
|
+
*Type Registry System*
|
|
353
|
+
|
|
354
|
+
All named type and group definitions are collected during schema parsing into hash-based registries for O(1) lookup performance:
|
|
355
|
+
|
|
356
|
+
* Complex types (`<xs:complexType name="...">`)
|
|
357
|
+
* Simple types (`<xs:simpleType name="...">`)
|
|
358
|
+
* Groups (`<xs:group name="...">`)
|
|
359
|
+
* Attribute groups (`<xs:attributeGroup name="...">`)
|
|
360
|
+
* Global elements (`<xs:element name="...">`)
|
|
361
|
+
|
|
362
|
+
*Named Type Resolution*
|
|
363
|
+
|
|
364
|
+
Resolves type references in element declarations:
|
|
365
|
+
|
|
366
|
+
[source,xml]
|
|
367
|
+
----
|
|
368
|
+
<xs:element name="Foo" type="BarType"/>
|
|
369
|
+
----
|
|
370
|
+
|
|
371
|
+
The system:
|
|
372
|
+
|
|
373
|
+
1. Strips namespace prefixes from type names
|
|
374
|
+
2. Checks if the type is a W3C builtin (string, boolean, decimal, etc.)
|
|
375
|
+
3. Looks up custom types in the complex/simple type registries
|
|
376
|
+
4. Processes the resolved type definition inline
|
|
377
|
+
|
|
378
|
+
*Group Reference Resolution*
|
|
379
|
+
|
|
380
|
+
Resolves group references in compositors:
|
|
381
|
+
|
|
382
|
+
[source,xml]
|
|
383
|
+
----
|
|
384
|
+
<xs:sequence>
|
|
385
|
+
<xs:group ref="CommonElements"/>
|
|
386
|
+
</xs:sequence>
|
|
387
|
+
----
|
|
388
|
+
|
|
389
|
+
The referenced group's contents are expanded inline, maintaining proper tree hierarchy.
|
|
390
|
+
|
|
391
|
+
*Attribute Group Reference Resolution*
|
|
392
|
+
|
|
393
|
+
Resolves attribute group references:
|
|
394
|
+
|
|
395
|
+
[source,xml]
|
|
396
|
+
----
|
|
397
|
+
<xs:complexType>
|
|
398
|
+
<xs:attributeGroup ref="CommonAttributes"/>
|
|
399
|
+
</xs:complexType>
|
|
400
|
+
----
|
|
401
|
+
|
|
402
|
+
Supports nested attribute group references (recursive resolution).
|
|
403
|
+
|
|
404
|
+
*Element Reference Resolution*
|
|
405
|
+
|
|
406
|
+
Resolves element references with proper cardinality:
|
|
407
|
+
|
|
408
|
+
[source,xml]
|
|
409
|
+
----
|
|
410
|
+
<xs:element ref="CommonElement" minOccurs="0" maxOccurs="unbounded"/>
|
|
411
|
+
----
|
|
412
|
+
|
|
413
|
+
The system preserves cardinality constraints while resolving to the element definition.
|
|
414
|
+
|
|
415
|
+
*Extension and Restriction Processing*
|
|
416
|
+
|
|
417
|
+
Handles type inheritance via `complexContent` and `simpleContent`:
|
|
418
|
+
|
|
419
|
+
[source,xml]
|
|
420
|
+
----
|
|
421
|
+
<xs:complexType name="ExtendedType">
|
|
422
|
+
<xs:complexContent>
|
|
423
|
+
<xs:extension base="BaseType">
|
|
424
|
+
<xs:sequence>
|
|
425
|
+
<!-- Additional elements -->
|
|
426
|
+
</xs:sequence>
|
|
427
|
+
</xs:extension>
|
|
428
|
+
</xs:complexContent>
|
|
429
|
+
</xs:complexType>
|
|
430
|
+
----
|
|
431
|
+
|
|
432
|
+
The system:
|
|
433
|
+
|
|
434
|
+
1. Resolves the base type from registries
|
|
435
|
+
2. Processes base type structure first (inherited elements/attributes)
|
|
436
|
+
3. Processes extension-specific additions
|
|
437
|
+
4. Maintains single inheritance hierarchy
|
|
438
|
+
|
|
439
|
+
==== Performance characteristics
|
|
440
|
+
|
|
441
|
+
* Registry collection: O(n) where n = total XSD nodes
|
|
442
|
+
* Type lookup: O(1) hash access
|
|
443
|
+
* Recursive resolution: Bounded by schema depth
|
|
444
|
+
* Loop detection prevents infinite recursion
|
|
445
|
+
* On-demand resolution (lazy evaluation)
|
|
446
|
+
|
|
447
|
+
This architecture enables XSDVI to correctly process 100% of XSD schema structures, matching the Java version's capabilities.
|
|
448
|
+
|
|
243
449
|
|
|
244
450
|
== Differences from Java version
|
|
245
451
|
|
|
@@ -295,6 +501,158 @@ Run rubocop:
|
|
|
295
501
|
bundle exec rubocop
|
|
296
502
|
----
|
|
297
503
|
|
|
504
|
+
=== Testing
|
|
505
|
+
|
|
506
|
+
==== Test suite overview
|
|
507
|
+
|
|
508
|
+
The XSDVI Ruby test suite provides comprehensive validation of all functionality with 46 tests across two categories:
|
|
509
|
+
|
|
510
|
+
* **Integration tests** (14 tests): Validate complete end-to-end processing and compare outputs with Java version
|
|
511
|
+
* **Type resolution tests** (32 tests): Validate all 7 type resolution mechanisms
|
|
512
|
+
|
|
513
|
+
==== Running tests
|
|
514
|
+
|
|
515
|
+
*Run all tests*
|
|
516
|
+
|
|
517
|
+
[source,shell]
|
|
518
|
+
----
|
|
519
|
+
bundle exec rspec
|
|
520
|
+
----
|
|
521
|
+
|
|
522
|
+
*Run specific test file*
|
|
523
|
+
|
|
524
|
+
[source,shell]
|
|
525
|
+
----
|
|
526
|
+
# Type resolution tests only
|
|
527
|
+
bundle exec rspec spec/xsdvi/type_resolution_spec.rb
|
|
528
|
+
|
|
529
|
+
# Output comparison tests only
|
|
530
|
+
bundle exec rspec spec/xsdvi/output_comparison_spec.rb
|
|
531
|
+
----
|
|
532
|
+
|
|
533
|
+
*Run with documentation format*
|
|
534
|
+
|
|
535
|
+
[source,shell]
|
|
536
|
+
----
|
|
537
|
+
bundle exec rspec --format documentation
|
|
538
|
+
----
|
|
539
|
+
|
|
540
|
+
*Run specific test group*
|
|
541
|
+
|
|
542
|
+
[source,shell]
|
|
543
|
+
----
|
|
544
|
+
bundle exec rspec spec/xsdvi/type_resolution_spec.rb -e "Named Type Resolution"
|
|
545
|
+
----
|
|
546
|
+
|
|
547
|
+
==== Type resolution test coverage
|
|
548
|
+
|
|
549
|
+
The type resolution test suite validates that XSDVI Ruby correctly processes all XSD schema constructs:
|
|
550
|
+
|
|
551
|
+
*7 Resolution Mechanisms Tested:*
|
|
552
|
+
|
|
553
|
+
1. **Named Type Resolution** - Complex and simple type references
|
|
554
|
+
2. **Group Reference Resolution** - Model group (`<xs:group ref="...">`) expansion
|
|
555
|
+
3. **Attribute Group Reference Resolution** - Attribute group references including nested
|
|
556
|
+
4. **Element Reference Resolution** - Global element references with cardinality
|
|
557
|
+
5. **Extension/Restriction Resolution** - Type inheritance via `complexContent`/`simpleContent`
|
|
558
|
+
6. **Identity Constraint Resolution** - Key, keyref, unique, selector, field
|
|
559
|
+
7. **Circular Reference Resolution** - Self-referencing and mutual circular references
|
|
560
|
+
|
|
561
|
+
*Test Fixtures:*
|
|
562
|
+
|
|
563
|
+
The test suite uses 7 XSD fixture files in `spec/fixtures/type_resolution/`:
|
|
564
|
+
|
|
565
|
+
* `named_types.xsd` - Type reference resolution
|
|
566
|
+
* `group_refs.xsd` - Group reference expansion
|
|
567
|
+
* `attribute_groups.xsd` - Attribute group references
|
|
568
|
+
* `element_refs.xsd` - Element references with cardinality
|
|
569
|
+
* `inheritance.xsd` - Extension and restriction
|
|
570
|
+
* `identity_constraints.xsd` - Key/keyref/unique constraints
|
|
571
|
+
* `circular.xsd` - Circular reference handling
|
|
572
|
+
|
|
573
|
+
For detailed test documentation, see `spec/xsdvi/TYPE_RESOLUTION_TESTING.md`.
|
|
574
|
+
|
|
575
|
+
==== Generating comparison files
|
|
576
|
+
|
|
577
|
+
To validate that XSDVI Ruby produces output identical to the Java version:
|
|
578
|
+
|
|
579
|
+
*Generate Ruby output for UnitsML schema*
|
|
580
|
+
|
|
581
|
+
[source,shell]
|
|
582
|
+
----
|
|
583
|
+
xsdvi generate spec/fixtures/UnitsML-v1.0-csd04.xsd -r UnitsML \
|
|
584
|
+
-p spec/fixtures/ruby
|
|
585
|
+
----
|
|
586
|
+
|
|
587
|
+
*Generate Ruby output for all elements*
|
|
588
|
+
|
|
589
|
+
[source,shell]
|
|
590
|
+
----
|
|
591
|
+
xsdvi generate spec/fixtures/UnitsML-v1.0-csd04.xsd -r all -o \
|
|
592
|
+
-p spec/fixtures/ruby/all
|
|
593
|
+
----
|
|
594
|
+
|
|
595
|
+
*Generate Ruby output for TestXMLEntities*
|
|
596
|
+
|
|
597
|
+
[source,shell]
|
|
598
|
+
----
|
|
599
|
+
xsdvi generate spec/fixtures/TestXMLEntities.xsd \
|
|
600
|
+
-p spec/fixtures/ruby
|
|
601
|
+
----
|
|
602
|
+
|
|
603
|
+
*Compare with Java version*
|
|
604
|
+
|
|
605
|
+
The test suite automatically compares Ruby outputs with Java reference outputs in `spec/fixtures/java/`. The comparison normalizes known differences (text wrapping) and validates structural equivalence:
|
|
606
|
+
|
|
607
|
+
[source,shell]
|
|
608
|
+
----
|
|
609
|
+
bundle exec rspec spec/xsdvi/output_comparison_spec.rb
|
|
610
|
+
----
|
|
611
|
+
|
|
612
|
+
*Manual comparison*
|
|
613
|
+
|
|
614
|
+
You can manually compare outputs using diff tools:
|
|
615
|
+
|
|
616
|
+
[source,shell]
|
|
617
|
+
----
|
|
618
|
+
# Compare UnitsML outputs
|
|
619
|
+
diff spec/fixtures/java/UnitsML-v1.0-csd04.svg \
|
|
620
|
+
spec/fixtures/ruby/UnitsML-v1.0-csd04.svg
|
|
621
|
+
|
|
622
|
+
# Compare specific element
|
|
623
|
+
diff spec/fixtures/java/all/Quantity.svg \
|
|
624
|
+
spec/fixtures/ruby/all/Quantity.svg
|
|
625
|
+
----
|
|
626
|
+
|
|
627
|
+
Note: Direct diff will show text wrapping differences. Use the RSpec comparison tests for structural validation.
|
|
628
|
+
|
|
629
|
+
*Generating fresh Java comparison files*
|
|
630
|
+
|
|
631
|
+
If you need to regenerate Java version outputs (requires Java XsdVi):
|
|
632
|
+
|
|
633
|
+
[source,shell]
|
|
634
|
+
----
|
|
635
|
+
# Assuming Java xsdvi.jar is available
|
|
636
|
+
java -jar xsdvi.jar --in spec/fixtures/UnitsML-v1.0-csd04.xsd \
|
|
637
|
+
--root UnitsML --out spec/fixtures/java/UnitsML-v1.0-csd04.svg
|
|
638
|
+
|
|
639
|
+
# For all elements
|
|
640
|
+
java -jar xsdvi.jar --in spec/fixtures/UnitsML-v1.0-csd04.xsd \
|
|
641
|
+
--root all --one-node-only --out spec/fixtures/java/all
|
|
642
|
+
----
|
|
643
|
+
|
|
644
|
+
==== Test validation approach
|
|
645
|
+
|
|
646
|
+
The test suite uses Canon gem for XML-aware comparison that:
|
|
647
|
+
|
|
648
|
+
* Normalizes whitespace differences
|
|
649
|
+
* Handles attribute ordering variations
|
|
650
|
+
* Validates structural equivalence
|
|
651
|
+
* Ignores text wrapping differences in `data-desc-*` attributes
|
|
652
|
+
* Focuses on semantic correctness rather than byte-identical output
|
|
653
|
+
|
|
654
|
+
This ensures that XSDVI Ruby produces functionally identical diagrams to the Java version while allowing minor presentational differences.
|
|
655
|
+
|
|
298
656
|
== Contributing
|
|
299
657
|
|
|
300
658
|
Bug reports and pull requests are welcome on GitHub at
|
data/lib/xsdvi/cli.rb
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require "thor"
|
|
4
|
+
require "fileutils"
|
|
4
5
|
|
|
5
6
|
module Xsdvi
|
|
6
7
|
# Command-line interface for XSDVI
|
|
@@ -67,16 +68,102 @@ module Xsdvi
|
|
|
67
68
|
apply_style_settings(svg_generator, style_mode, options)
|
|
68
69
|
|
|
69
70
|
inputs.each do |input|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
71
|
+
# Special handling for -r all: generate file for each element
|
|
72
|
+
if root_node_name == "all"
|
|
73
|
+
process_all_elements(
|
|
74
|
+
input,
|
|
75
|
+
xsd_handler,
|
|
76
|
+
svg_generator,
|
|
77
|
+
builder,
|
|
78
|
+
writer_helper,
|
|
79
|
+
output_path,
|
|
80
|
+
)
|
|
81
|
+
else
|
|
82
|
+
process_input_file(
|
|
83
|
+
input,
|
|
84
|
+
xsd_handler,
|
|
85
|
+
svg_generator,
|
|
86
|
+
builder,
|
|
87
|
+
writer_helper,
|
|
88
|
+
root_node_name,
|
|
89
|
+
one_node_only,
|
|
90
|
+
output_path,
|
|
91
|
+
)
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
desc "compare INPUT", "Compare Java and Ruby XsdVi outputs side-by-side"
|
|
97
|
+
method_option :root_node_name,
|
|
98
|
+
type: :string,
|
|
99
|
+
aliases: "-r",
|
|
100
|
+
desc: "Schema root node name (or 'all' for all elements)"
|
|
101
|
+
method_option :output_path,
|
|
102
|
+
type: :string,
|
|
103
|
+
aliases: "-o",
|
|
104
|
+
desc: "Output directory (default: ./comparisons/<name>-<timestamp>)"
|
|
105
|
+
method_option :skip_java,
|
|
106
|
+
type: :boolean,
|
|
107
|
+
default: false,
|
|
108
|
+
desc: "Skip Java generation (use existing output)"
|
|
109
|
+
method_option :skip_ruby,
|
|
110
|
+
type: :boolean,
|
|
111
|
+
default: false,
|
|
112
|
+
desc: "Skip Ruby generation (use existing output)"
|
|
113
|
+
method_option :open,
|
|
114
|
+
type: :boolean,
|
|
115
|
+
default: false,
|
|
116
|
+
aliases: "-O",
|
|
117
|
+
desc: "Open comparison HTML in browser automatically"
|
|
118
|
+
def compare(input)
|
|
119
|
+
unless File.exist?(input)
|
|
120
|
+
puts "Error: XSD file '#{input}' not found!"
|
|
121
|
+
exit(1)
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
puts "=" * 60
|
|
125
|
+
puts "XsdVi Comparison Tool"
|
|
126
|
+
puts "=" * 60
|
|
127
|
+
puts "Schema: #{input}"
|
|
128
|
+
puts ""
|
|
129
|
+
|
|
130
|
+
begin
|
|
131
|
+
generator = Comparison::DualGenerator.new(input, options)
|
|
132
|
+
result = generator.generate
|
|
133
|
+
|
|
134
|
+
puts ""
|
|
135
|
+
puts "=" * 60
|
|
136
|
+
puts "Comparison Complete!"
|
|
137
|
+
puts "=" * 60
|
|
138
|
+
puts ""
|
|
139
|
+
puts "Output directory: #{result[:output_dir]}"
|
|
140
|
+
puts "HTML comparison: #{result[:html_file]}"
|
|
141
|
+
puts ""
|
|
142
|
+
|
|
143
|
+
if result[:java][:file_count] && result[:java][:generation_time] && result[:java][:generation_time]
|
|
144
|
+
puts "Java: #{result[:java][:total_size_kb]} KB, " \
|
|
145
|
+
"#{result[:java][:file_count]} file(s), " \
|
|
146
|
+
"#{result[:java][:generation_time]}s"
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
if result[:ruby][:file_count] && result[:ruby][:generation_time] && result[:ruby][:generation_time]
|
|
150
|
+
puts "Ruby: #{result[:ruby][:total_size_kb]} KB, " \
|
|
151
|
+
"#{result[:ruby][:file_count]} file(s), " \
|
|
152
|
+
"#{result[:ruby][:generation_time]}s"
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
puts ""
|
|
156
|
+
|
|
157
|
+
if options[:open]
|
|
158
|
+
open_in_browser(result[:html_file])
|
|
159
|
+
else
|
|
160
|
+
puts "Open #{result[:html_file]} in your browser to view the comparison"
|
|
161
|
+
end
|
|
162
|
+
rescue StandardError => e
|
|
163
|
+
puts ""
|
|
164
|
+
puts "Error: #{e.message}"
|
|
165
|
+
puts e.backtrace.first(5).join("\n") if ENV["DEBUG"]
|
|
166
|
+
exit(1)
|
|
80
167
|
end
|
|
81
168
|
end
|
|
82
169
|
|
|
@@ -84,6 +171,52 @@ module Xsdvi
|
|
|
84
171
|
|
|
85
172
|
private
|
|
86
173
|
|
|
174
|
+
def process_all_elements(input, xsd_handler, svg_generator, builder,
|
|
175
|
+
writer_helper, output_path)
|
|
176
|
+
# First, parse the schema to get all element names
|
|
177
|
+
doc = Nokogiri::XML(File.read(input))
|
|
178
|
+
element_names = xsd_handler.get_elements_names(doc)
|
|
179
|
+
|
|
180
|
+
if element_names.empty?
|
|
181
|
+
warn "No root elements found in schema!"
|
|
182
|
+
return
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
puts "Generating #{element_names.size} diagrams for all elements..."
|
|
186
|
+
|
|
187
|
+
# Generate a separate diagram for each element
|
|
188
|
+
element_names.each do |elem_name|
|
|
189
|
+
# Reset builder for each element
|
|
190
|
+
builder = Tree::Builder.new
|
|
191
|
+
xsd_handler = XsdHandler.new(builder)
|
|
192
|
+
xsd_handler.root_node_name = elem_name
|
|
193
|
+
xsd_handler.one_node_only = true
|
|
194
|
+
xsd_handler.set_schema_namespace(doc, elem_name)
|
|
195
|
+
|
|
196
|
+
# Process the schema with this specific root element
|
|
197
|
+
xsd_handler.process_file(input)
|
|
198
|
+
|
|
199
|
+
# Generate output filename
|
|
200
|
+
output_file = generate_output_filename(
|
|
201
|
+
input,
|
|
202
|
+
elem_name,
|
|
203
|
+
true, # one_node_only
|
|
204
|
+
output_path,
|
|
205
|
+
)
|
|
206
|
+
|
|
207
|
+
writer_helper.new_writer(output_file)
|
|
208
|
+
|
|
209
|
+
if builder.root
|
|
210
|
+
svg_generator.draw(builder.root)
|
|
211
|
+
puts " Generated #{output_file}"
|
|
212
|
+
else
|
|
213
|
+
warn " Skipped #{elem_name} (empty)"
|
|
214
|
+
end
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
puts "Done."
|
|
218
|
+
end
|
|
219
|
+
|
|
87
220
|
def determine_style_mode(options)
|
|
88
221
|
return :generate_style if options[:generate_style]
|
|
89
222
|
return :use_style if options[:use_style]
|
|
@@ -159,5 +292,24 @@ module Xsdvi
|
|
|
159
292
|
filename
|
|
160
293
|
end
|
|
161
294
|
end
|
|
295
|
+
|
|
296
|
+
def open_in_browser(file)
|
|
297
|
+
puts "Opening comparison in browser..."
|
|
298
|
+
|
|
299
|
+
# Get absolute path for browser
|
|
300
|
+
abs_path = File.expand_path(file)
|
|
301
|
+
|
|
302
|
+
case RbConfig::CONFIG["host_os"]
|
|
303
|
+
when /darwin/
|
|
304
|
+
system("open", abs_path)
|
|
305
|
+
when /linux/
|
|
306
|
+
system("xdg-open", abs_path)
|
|
307
|
+
when /mswin|mingw|cygwin/
|
|
308
|
+
system("start", abs_path)
|
|
309
|
+
else
|
|
310
|
+
puts "Unable to auto-open browser on this platform"
|
|
311
|
+
puts "Please open #{file} manually"
|
|
312
|
+
end
|
|
313
|
+
end
|
|
162
314
|
end
|
|
163
315
|
end
|