lutaml-xsd 1.1.3 → 1.1.4

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ab65095d3489bfa5198ceb55652108b864e7a5be7c71c11e4bf4e008c434cdf1
4
- data.tar.gz: eeb2e432c1cceceec5bc5b88197ba86a12e07deb7402a49bdc9b054ee9e5f051
3
+ metadata.gz: 8f86df66b1872004805859211c3ece8ab95f01471382e5c44c828f0b4477f299
4
+ data.tar.gz: 35e1d8b3636c7717185a52cd5be3f7656153ea5f17231327c77ad3ea5c13299c
5
5
  SHA512:
6
- metadata.gz: ae06973a7e5c075298b86870a414d398329f57d74fc6eba07f435a0af51002bfbda1ace3e9021fda1ccd586eadc0875c3c576150cd2bf30aad5aef1557852277
7
- data.tar.gz: 34b409a1da1fb13fca086a57ad18aba81d0d3ebc6e4aaf0fcd9f4e1b7df2653240cd094dab9f64974f618d6fa4a208af0f7b739d804ccf16d4baa720ad7634c2
6
+ metadata.gz: 2fb32fab3985d140b465aee99a2076831156dca986cb961a1fdda2388e08a85de4c1bbb10ff7b88964063202d0abccb3a870d816cd545d731229170baff6d877
7
+ data.tar.gz: e8a6436f162216cec2a8cd641f72467eb6a0ab4c38aa2da42aec9b7606d970866e617fa5efcdc8939c31725b59c504ed5c5e074cebc657b37cb3abeda59e04aa
data/.gitignore CHANGED
@@ -35,3 +35,4 @@ frontend/index.html
35
35
  examples/*/pkg/
36
36
  examples/*.html
37
37
  examples/archive-old/
38
+ examples/02-urban-function/urban_function_docs.html
data/Gemfile CHANGED
@@ -12,7 +12,6 @@ gem "liquid"
12
12
  gem "lutaml-model", github: "lutaml/lutaml-model", branch: "main"
13
13
  gem "nokogiri"
14
14
  gem "rake"
15
- gem "rng", github: "lutaml/rng", branch: "fix-include-define"
16
15
  gem "rspec"
17
16
  gem "rubocop"
18
17
  gem "rubocop-performance"
data/README.adoc CHANGED
@@ -11,7 +11,8 @@ image:https://github.com/lutaml/lutaml-xsd/actions/workflows/rake.yml/badge.svg[
11
11
  Lutaml::Xsd is a Ruby gem designed to parse and manipulate XML Schema Definition
12
12
  (XSD) files. It provides a robust framework for handling XSD elements,
13
13
  attributes, complex types, and all other XSD constructs, allowing users to
14
- programmatically work with XML schemas.
14
+ programmatically work with XML schemas. It also supports RELAX NG (RNG/RNC)
15
+ schemas through automatic conversion to XSD.
15
16
 
16
17
  NOTE: For UML-to-XSD mapping and YAML documentation generation (including
17
18
  ShapeChange integration), see the
@@ -45,8 +46,16 @@ allowing you to shape and structure your data into useful forms.
45
46
  - Single-file mode
46
47
  - Entrypoint prioritization in sidebar
47
48
  - Schema detail views with elements/types/attributes tables
49
+ - Interactive group tree view with nested choices and sequences
50
+ - Inline complex type display for anonymous types within elements
48
51
  - Hash-based navigation with browser back/forward support
49
52
  - Dark mode with automatic theme detection
53
+ * <<rng-rnc-support,RELAX NG (RNG/RNC) support>> - Convert and build from
54
+ RELAX NG schemas
55
+ - Automatic RNG/RNC to XSD conversion via `RngToXsdConverter`
56
+ - Build LXR packages directly from `.rng` and `.rnc` files
57
+ - Support for both XML syntax (`.rng`) and compact syntax (`.rnc`)
58
+ - Automatic include directive conversion
50
59
  * <<schema-validation,XSD schema validation>> with automatic version detection
51
60
  - Pre-parsing validation to ensure valid XSD schema documents
52
61
  - Automatic detection of XSD 1.0 vs 1.1 features
@@ -138,6 +147,8 @@ lutaml-xsd spa schemas.lxr --output docs.html \
138
147
  * Schema navigation with entrypoints prioritized
139
148
  * Element and type detail views
140
149
  * XML Instance Representation for each component
150
+ * Inline complex type display for anonymous types within elements
151
+ * Interactive group tree view showing nested choices, sequences, and sub-groups
141
152
  * Clickable cross-references throughout
142
153
  * xs3p-quality documentation
143
154
 
@@ -231,6 +242,88 @@ For comprehensive documentation on SPA generation, see:
231
242
  * link:docs/SPA_DEPLOYMENT.adoc[Deployment Guide] - Hosting and CI/CD integration
232
243
  * link:docs/SPA_ARCHITECTURE.adoc[Architecture Documentation] - Design and extension guide
233
244
 
245
+ [[rng-rnc-support]]
246
+ == RELAX NG (RNG/RNC) support
247
+
248
+ === General
249
+
250
+ Lutaml::Xsd can convert RELAX NG schema files (`.rng` XML syntax and `.rnc`
251
+ compact syntax) to XSD, allowing you to build LXR packages and generate
252
+ documentation from RELAX NG schemas using the same tools and workflows.
253
+
254
+ The `RngToXsdConverter` follows the same mapping logic as jing-trang's RNG-to-XSD
255
+ conversion, handling define resolution, element classification, collision
256
+ detection, and include directives.
257
+
258
+ === Building from RNG/RNC files
259
+
260
+ Use `.rng` or `.rnc` files directly in your YAML configuration:
261
+
262
+ [source,yaml]
263
+ ----
264
+ # config.yml
265
+ files:
266
+ - path/to/schema.rng
267
+ ----
268
+
269
+ Or point to a compact syntax file:
270
+
271
+ [source,yaml]
272
+ ----
273
+ # config.yml
274
+ files:
275
+ - path/to/schema.rnc
276
+ ----
277
+
278
+ Then build the package as usual:
279
+
280
+ [source,bash]
281
+ ----
282
+ lutaml-xsd pkg build config.yml --output schema.lxr
283
+ ----
284
+
285
+ During package creation, the RNG/RNC file is automatically converted to XSD.
286
+ The generated `.xsd` file is written alongside the original source file (or to a
287
+ temporary directory if the original location is not writable).
288
+
289
+ === Ruby API
290
+
291
+ .Load and query an RNG schema programmatically
292
+ [example]
293
+ ====
294
+ [source,ruby]
295
+ ----
296
+ require 'lutaml/xsd'
297
+
298
+ # Load directly from an RNG or RNC file
299
+ repo = Lutaml::Xsd::SchemaRepository.load_from_file('schema.rng')
300
+
301
+ # Or use the converter directly
302
+ require 'rng'
303
+ grammar = Rng.parse(File.read('schema.rng'))
304
+ xsd_schema = Lutaml::Xsd::RngToXsdConverter.new(grammar).convert
305
+
306
+ # Serialize to XML
307
+ puts xsd_schema.to_formatted_xml
308
+ ----
309
+ ====
310
+
311
+ === Conversion details
312
+
313
+ The converter handles:
314
+
315
+ * **Define resolution** — Named `<define>` blocks are resolved and expanded
316
+ * **Include directives** — RNC `include "path"` and RNG `<include href="..."/>` are
317
+ converted to XSD `<include>` elements
318
+ * **Collision detection** — Element name collisions from multiple defines are
319
+ detected and handled
320
+ * **Pattern mapping** — RNG patterns (`<element>`, `<attribute>`, `<choice>`,
321
+ `<group>`, `<interleave>`, `<optional>`, `<zeroOrMore>`, `<oneOrMore>`,
322
+ `<data>`, `<value>`, `<list>`, `<text>`) are mapped to their XSD equivalents
323
+ * **Attribute classification** — Patterns that resolve to attributes (including
324
+ those wrapped in `<optional>`) are correctly classified
325
+ * **Namespace handling** — Target namespace is preserved from the source grammar
326
+
234
327
  [[schema-validation]]
235
328
  == XSD schema validation
236
329
 
@@ -839,13 +932,17 @@ lutaml-xsd xml validate-batch <directory/> --package <file.lxr>
839
932
 
840
933
  === BUILD commands (package creation)
841
934
 
842
- Create LXR packages from configurations.
935
+ Create LXR packages from configurations. Supports XSD, RNG, and RNC input
936
+ files.
843
937
 
844
938
  [source,bash]
845
939
  ----
846
- # Build from YAML config
940
+ # Build from YAML config (XSD files)
847
941
  lutaml-xsd pkg build <config.yml>
848
942
 
943
+ # Build from RNG/RNC files (automatically converted to XSD)
944
+ lutaml-xsd pkg build <config.yml> # config.yml can reference .rng/.rnc files
945
+
849
946
  # Interactive initialization
850
947
  lutaml-xsd build init <entrypoint.xsd>
851
948
 
@@ -1055,18 +1152,23 @@ and their relationships:
1055
1152
 
1056
1153
  === Data transformation flow
1057
1154
 
1058
- The following diagram shows how XSD files are processed through the parsing
1059
- pipeline:
1155
+ The following diagram shows how XSD and RNG/RNC files are processed through the
1156
+ parsing pipeline:
1060
1157
 
1061
1158
  [source]
1062
1159
  ----
1063
- ╔═══════════════════╗ ╔═══════════════════════╗
1064
- ║ XSD File(s) ║ ║ Schema Mappings ║
1065
- ║ ║ ║ (Local redirects) ║
1066
- ╚═════════┬═════════╝ ╚═══════════┬═══════════╝
1067
- │ │
1068
- └────────────┬────────────────────┘
1069
-
1160
+ ╔═══════════════════╗ ╔═══════════════════╗ ╔═══════════════════════╗
1161
+ ║ XSD File(s) ║ RNG/RNC File(s) ║ ║ Schema Mappings ║
1162
+ ║ ║ ║ ║ (Local redirects) ║
1163
+ ╚═════════╦═════════╝ ╚═════════╦═════════╝ ╚═══════════╦═══════════╝
1164
+ ║ ║ ║
1165
+ ║ ╔═════════╩════════════╗ ║
1166
+ ║ ║ RngToXsdConverter ║ ║
1167
+ ║ ║ (RNG/RNC → XSD) ║ ║
1168
+ ║ ╚═════════╦════════════╝ ║
1169
+ ║ ║ ║
1170
+ ╚════════════╦══════════╩═══════════════════════════╝
1171
+
1070
1172
 
1071
1173
  ┌────────────────┐
1072
1174
  │ XSD Parser │
@@ -1453,6 +1555,8 @@ Syntax:
1453
1555
  ----
1454
1556
  files: <1>
1455
1557
  - path/to/schema.xsd
1558
+ - path/to/schema.rng # RELAX NG XML syntax
1559
+ - path/to/schema.rnc # RELAX NG Compact syntax
1456
1560
 
1457
1561
  schema_location_mappings: <2>
1458
1562
  - from: "http://schemas.example.com/schema.xsd"
@@ -1465,13 +1569,13 @@ namespace_mappings: <3>
1465
1569
  - prefix: "ex"
1466
1570
  uri: "http://example.com/namespace"
1467
1571
  ----
1468
- <1> List of XSD file paths to include in the package (required)
1572
+ <1> List of schema file paths (`.xsd`, `.rng`, or `.rnc`) to include (required)
1469
1573
  <2> Schema location mappings for imports/includes (optional)
1470
1574
  <3> Namespace prefix mappings (optional)
1471
1575
 
1472
1576
  Where,
1473
1577
 
1474
- `files`:: Array of XSD file paths to include in the package (required)
1578
+ `files`:: Array of schema file paths (`.xsd`, `.rng`, or `.rnc`) to include in the package (required). RNG/RNC files are automatically converted to XSD.
1475
1579
  `schema_location_mappings`:: Array of schema location redirections (optional)
1476
1580
  `namespace_mappings`:: Array of namespace prefix-to-URI mappings (optional)
1477
1581
 
@@ -1545,9 +1649,13 @@ NOTE: The `pkg build` command requires a YAML configuration file as input. Direc
1545
1649
  [example]
1546
1650
  [source,yaml]
1547
1651
  ----
1548
- # minimal_config.yaml
1652
+ # minimal_config.yaml (XSD)
1549
1653
  files:
1550
1654
  - path/to/schema.xsd
1655
+
1656
+ # minimal_config.yaml (RNG/RNC — automatically converted to XSD)
1657
+ files:
1658
+ - path/to/schema.rng
1551
1659
  ----
1552
1660
 
1553
1661
  Then build the package:
@@ -457,6 +457,33 @@ The [`Lutaml::Xsd::Glob`](lib/lutaml/xsd/glob.rb) class manages schema location
457
457
 
458
458
  This design allows offline development, schema version control, and consistent schema handling across environments.
459
459
 
460
+ === RNG to XSD Converter
461
+
462
+ The [`Lutaml::Xsd::RngToXsdConverter`](lib/lutaml/xsd/rng_to_xsd_converter.rb) converts RELAX NG (`.rng` / `.rnc`) schemas to XSD.
463
+
464
+ **Responsibilities:**
465
+
466
+ * Convert `Rng::Grammar` objects to `Lutaml::Xsd::Schema` objects
467
+ * Resolve named `<define>` blocks with cycle detection
468
+ * Classify patterns as elements, attributes, or particles
469
+ * Detect and handle element name collisions across defines
470
+ * Convert include directives from RNC/RNG to XSD `<include>` elements
471
+ * Map RNG patterns (`<element>`, `<attribute>`, `<choice>`, `<group>`, `<interleave>`, `<optional>`, `<zeroOrMore>`, `<oneOrMore>`, `<data>`, `<value>`, `<list>`, `<text>`) to XSD equivalents
472
+
473
+ **Integration points:**
474
+
475
+ * `SchemaRepository#parse_schema_file` — automatically invokes the converter for `.rng`/`.rnc` files
476
+ * `SchemaRepository.from_file` — accepts `.rng` and `.rnc` paths
477
+
478
+ **Conversion pipeline:**
479
+
480
+ . Parse RNG/RNC file into `Rng::Grammar` object (via the `rng` gem)
481
+ . `RngToXsdConverter#convert` maps the grammar to XSD constructs
482
+ . Phase 0: Convert include directives
483
+ . Phase 1: Convert all named defines (with caching and cycle guards)
484
+ . Phase 2: Convert start elements and top-level elements
485
+ . Result is a standard `Lutaml::Xsd::Schema` object usable by all downstream components
486
+
460
487
  === Schema Repository
461
488
 
462
489
  The [`Lutaml::Xsd::SchemaRepository`](lib/lutaml/xsd/schema_repository.rb) provides namespace-aware type resolution across multiple schemas.
data/docs/CHANGELOG.md CHANGED
@@ -11,6 +11,37 @@ All notable changes to lutaml-xsd will be documented in this file.
11
11
 
12
12
  ## [Unreleased]
13
13
 
14
+ ## [1.1.3] - 2025-05-15
15
+
16
+ ### Added
17
+
18
+ - RELAX NG (RNG/RNC) to XSD conversion via `Lutaml::Xsd::RngToXsdConverter`
19
+ - Build LXR packages directly from `.rng` and `.rnc` files
20
+ - `SchemaRepository.load_from_file` accepts `.rng` and `.rnc` schema files
21
+ - Inline/anonymous complex type display in SPA documentation — complex types defined within elements are now surfaced with synthetic names
22
+ - Group tree view in SPA — new `GroupTreeItem` component for interactive, nested rendering of groups with choices and sequences
23
+ - Sequence and choice serialization in SPA — `xs:sequence` and `xs:choice` model groups are fully serialized with nesting support
24
+ - Schema include display in SPA documentation
25
+
26
+ ### Fixed
27
+
28
+ - SPA generation error when serializing SimpleContent types
29
+ - Schema validation error handling
30
+
31
+ ## [1.1.2] - 2025-05-12
32
+
33
+ - Refactor: eliminate `send()` calls in lutaml-xsd (22 → 0)
34
+ - Refactor: eliminate `respond_to?` duck-typing in lutaml-xsd (371 → 1)
35
+ - Fix: merge included schemas by namespace, refactor SchemaSerializer for DRY/security
36
+
37
+ ## [1.1.1] - 2025-05-09
38
+
39
+ - Fix: merge included schemas by namespace, refactor SchemaSerializer for DRY/security
40
+
41
+ ## [1.1.0] - 2025-05-08
42
+
43
+ - Fix: SVG diagram generation for XSD type definitions
44
+
14
45
  ## [0.1.0] - 2024-11-18
15
46
 
16
47
  - Initial release
data/docs/CLI.adoc CHANGED
@@ -47,7 +47,9 @@ Package commands create, validate, and inspect LXR schema repository packages.
47
47
 
48
48
  === pkg build
49
49
 
50
- Build an LXR package from a YAML configuration file.
50
+ Build an LXR package from a YAML configuration file. The `files` list in the
51
+ configuration may reference `.xsd`, `.rng`, or `.rnc` files. RNG/RNC files are
52
+ automatically converted to XSD during the build process.
51
53
 
52
54
  Syntax:
53
55
 
@@ -58,7 +60,9 @@ lutaml-xsd pkg build CONFIG_FILE [options]
58
60
 
59
61
  Where,
60
62
 
61
- `CONFIG_FILE`:: Path to YAML configuration file (required)
63
+ `CONFIG_FILE`:: Path to YAML configuration file (required). The `files` list
64
+ supports `.xsd`, `.rng` (RELAX NG XML syntax), and `.rnc` (RELAX NG Compact
65
+ syntax) files.
62
66
 
63
67
  Options:
64
68
 
@@ -1483,6 +1487,31 @@ lutaml-xsd stats show pkg/urban.lxr
1483
1487
  ----
1484
1488
  ====
1485
1489
 
1490
+ === Building from RELAX NG schemas
1491
+
1492
+ .Building a package from RNG/RNC files
1493
+ [example]
1494
+ ====
1495
+ [source,bash]
1496
+ ----
1497
+ # 1. Create configuration file referencing .rng or .rnc files
1498
+ cat > rng_schemas.yml << 'EOF'
1499
+ files:
1500
+ - schemas/isostandard.rnc
1501
+ - schemas/biblio.rnc
1502
+ EOF
1503
+
1504
+ # 2. Build package (RNG/RNC files are automatically converted to XSD)
1505
+ lutaml-xsd pkg build rng_schemas.yml \
1506
+ --name "ISO Standard Schemas" \
1507
+ --version "1.0" \
1508
+ --output pkg/iso_schemas.lxr
1509
+
1510
+ # 3. Query types as normal
1511
+ lutaml-xsd type list --from pkg/iso_schemas.lxr
1512
+ ----
1513
+ ====
1514
+
1486
1515
  === Validating package integrity
1487
1516
 
1488
1517
  .Package validation workflow
data/docs/INDEX.adoc CHANGED
@@ -15,10 +15,13 @@ basic usage to advanced technical topics.
15
15
 
16
16
  == What's new in lutaml-xsd
17
17
 
18
- Latest version: 1.0.4
18
+ Latest version: 1.1.3
19
19
 
20
20
  Recent highlights:
21
21
 
22
+ * 🎉 **RELAX NG Support** - Build packages from `.rng` and `.rnc` files with automatic XSD conversion
23
+ * 🌳 **Interactive Group Tree** - Expandable tree view for groups with nested choices and sequences
24
+ * 📝 **Inline Complex Types** - Anonymous complex types within elements displayed with synthetic names
22
25
  * 🎉 **LXR Packages** - Self-contained, portable schema repositories
23
26
  * ⚡ **Fast Type Index** - Pre-built indexes for instant lookups
24
27
  * 🔧 **Three Configuration Axes** - XSD mode, resolution mode, serialization
@@ -337,13 +337,13 @@ namespace_mappings: <3>
337
337
  - prefix: "ex"
338
338
  uri: "http://example.com/namespace"
339
339
  ----
340
- <1> List of XSD files to include (required)
340
+ <1> List of schema files (`.xsd`, `.rng`, or `.rnc`) to include (required)
341
341
  <2> Schema location mappings for imports/includes (optional)
342
342
  <3> Namespace prefix mappings (optional)
343
343
 
344
344
  Where,
345
345
 
346
- `files`:: Array of XSD file paths to include in the package (required)
346
+ `files`:: Array of schema file paths (`.xsd`, `.rng`, or `.rnc`) to include in the package (required). RNG/RNC files are automatically converted to XSD.
347
347
  `schema_location_mappings`:: Array of schema location redirections (optional)
348
348
  `namespace_mappings`:: Array of namespace prefix-to-URI mappings (optional)
349
349
 
@@ -22,13 +22,15 @@ LXR packages are highly configurable through three independent axes, allowing yo
22
22
 
23
23
  ==== `files` (required for standalone packages)
24
24
 
25
- Array of XSD file paths to include in the package. Required when building a standalone package (not using `base_packages`).
25
+ Array of schema file paths to include in the package. Supports `.xsd` (XML Schema), `.rng` (RELAX NG XML syntax), and `.rnc` (RELAX NG Compact syntax) files. RNG/RNC files are automatically converted to XSD during the build process. Required when building a standalone package (not using `base_packages`).
26
26
 
27
27
  [source,yaml]
28
28
  ----
29
29
  files:
30
30
  - path/to/schema.xsd
31
31
  - path/to/another.xsd
32
+ - path/to/schema.rng # RELAX NG XML syntax
33
+ - path/to/schema.rnc # RELAX NG Compact syntax
32
34
  ----
33
35
 
34
36
  ==== `output_package` (optional)
@@ -29,6 +29,8 @@ See link:INSTALLATION[Installation guide] for detailed instructions.
29
29
 
30
30
  Create a simple XSD file:
31
31
 
32
+ Create a simple XSD file:
33
+
32
34
  .Creating example.xsd
33
35
  [example]
34
36
  ====
@@ -251,6 +253,56 @@ Package statistics:
251
253
  ----
252
254
  ====
253
255
 
256
+ == Working with RELAX NG schemas
257
+
258
+ Lutaml::Xsd supports building packages directly from RELAX NG schemas (`.rng`
259
+ XML syntax and `.rnc` compact syntax). The schemas are automatically converted
260
+ to XSD during the build process.
261
+
262
+ === Creating a package from an RNC file
263
+
264
+ .Building from RELAX NG Compact syntax
265
+ [example]
266
+ ====
267
+ [source,bash]
268
+ ----
269
+ # 1. Create minimal configuration
270
+ cat > rng_config.yml << 'EOF'
271
+ files:
272
+ - path/to/schema.rnc
273
+ EOF
274
+
275
+ # 2. Build package
276
+ lutaml-xsd pkg build rng_config.yml \
277
+ --name "My RNG Schemas" \
278
+ --output my_rng_schemas.lxr
279
+
280
+ # 3. Query types as normal
281
+ lutaml-xsd type list --from my_rng_schemas.lxr
282
+ ----
283
+ ====
284
+
285
+ === Using the Ruby API with RNG files
286
+
287
+ .Loading RNG files programmatically
288
+ [example]
289
+ ====
290
+ [source,ruby]
291
+ ----
292
+ require 'lutaml/xsd'
293
+
294
+ # Load directly from an RNG file
295
+ repo = Lutaml::Xsd::SchemaRepository.load_from_file('schema.rng')
296
+
297
+ # Or from an RNC file
298
+ repo = Lutaml::Xsd::SchemaRepository.load_from_file('schema.rnc')
299
+
300
+ # Query types exactly as with XSD packages
301
+ result = repo.find_type('TypeName')
302
+ puts result.qname if result.resolved?
303
+ ----
304
+ ====
305
+
254
306
  == Working with schema location mappings
255
307
 
256
308
  When schemas import other schemas, you need schema location mappings:
data/docs/RUBY_API.adoc CHANGED
@@ -1333,6 +1333,93 @@ puts "Loaded #{stats[:total_types]} types"
1333
1333
  ----
1334
1334
  ====
1335
1335
 
1336
+ ==== from_file()
1337
+
1338
+ Load repository from a single schema file. Supports XSD (`.xsd`), RELAX NG
1339
+ XML syntax (`.rng`), and RELAX NG Compact syntax (`.rnc`) files. RNG/RNC files
1340
+ are automatically converted to XSD.
1341
+
1342
+ Syntax:
1343
+
1344
+ [source,ruby]
1345
+ ----
1346
+ repo = Lutaml::Xsd::SchemaRepository.from_file(path) <1>
1347
+ ----
1348
+ <1> Load repository from a schema file
1349
+
1350
+ Where,
1351
+
1352
+ `path`:: Path to a schema file (`.xsd`, `.rng`, or `.rnc`) (String) (required)
1353
+
1354
+ Returns a new [`SchemaRepository`](lib/lutaml/xsd/schema_repository.rb:10) instance.
1355
+
1356
+ .Loading from different schema formats
1357
+ [example]
1358
+ ====
1359
+ [source,ruby]
1360
+ ----
1361
+ # Load from XSD
1362
+ repo = Lutaml::Xsd::SchemaRepository.from_file('schema.xsd')
1363
+
1364
+ # Load from RELAX NG XML syntax
1365
+ repo = Lutaml::Xsd::SchemaRepository.from_file('schema.rng')
1366
+
1367
+ # Load from RELAX NG Compact syntax
1368
+ repo = Lutaml::Xsd::SchemaRepository.from_file('schema.rnc')
1369
+
1370
+ # All formats produce the same type of repository object
1371
+ repo.parse.resolve
1372
+ result = repo.find_type('TypeName')
1373
+ ----
1374
+ ====
1375
+
1376
+ ==== RngToXsdConverter
1377
+
1378
+ Convert a RELAX NG grammar to an XSD Schema object directly.
1379
+
1380
+ Syntax:
1381
+
1382
+ [source,ruby]
1383
+ ----
1384
+ require 'rng'
1385
+ grammar = Rng.parse(rng_content)
1386
+ schema = Lutaml::Xsd::RngToXsdConverter.new(grammar, file_path: 'schema.rng').convert
1387
+ ----
1388
+
1389
+ Where,
1390
+
1391
+ `grammar`:: A parsed `Rng::Grammar` object (required)
1392
+ `file_path`:: Original file path for include directive extraction (optional)
1393
+
1394
+ Returns an [`Lutaml::Xsd::Schema`](lib/lutaml/xsd/schema.rb) object.
1395
+
1396
+ .Converting RELAX NG to XSD
1397
+ [example]
1398
+ ====
1399
+ [source,ruby]
1400
+ ----
1401
+ require 'lutaml/xsd'
1402
+ require 'rng'
1403
+
1404
+ # Parse an RNG file
1405
+ rng_content = File.read('schema.rng')
1406
+ grammar = Rng.parse(rng_content,
1407
+ location: File.dirname('schema.rng'),
1408
+ resolve_external: true)
1409
+
1410
+ # Convert to XSD
1411
+ converter = Lutaml::Xsd::RngToXsdConverter.new(grammar, file_path: 'schema.rng')
1412
+ xsd_schema = converter.convert
1413
+
1414
+ # Serialize the result
1415
+ puts xsd_schema.to_formatted_xml
1416
+
1417
+ # Or parse an RNC file directly
1418
+ grammar = Rng.parse_file('schema.rnc')
1419
+ xsd_schema = Lutaml::Xsd::RngToXsdConverter.new(grammar, file_path: 'schema.rnc').convert
1420
+ ----
1421
+ ====
1422
+
1336
1423
  ==== from_yaml_file()
1337
1424
 
1338
1425
  Load repository configuration from a YAML file.
data/docs/SPA_GUIDE.adoc CHANGED
@@ -15,6 +15,8 @@ The SPA (Single Page Application) Documentation Generator creates modern, intera
15
15
  * **Dark mode support** - Automatic system preference detection with manual toggle
16
16
  * **Advanced search** - Real-time fuzzy matching across all schema components
17
17
  * **Type filtering** - Filter by element, complex type, simple type, attribute group, group
18
+ * **Inline complex types** - Anonymous complex types within elements are displayed with synthetic names
19
+ * **Interactive group tree view** - Expandable tree for groups with nested choices and sequences
18
20
  * **Zero dependencies** - Self-contained HTML, CSS, and JavaScript
19
21
  * **Offline-capable** - Works without internet connection (inlined mode)
20
22
  * **Accessibility** - WCAG 2.1 AA compliant
@@ -185,6 +187,27 @@ Click on any schema component to view:
185
187
  * **Structure** - Elements, attributes, restrictions
186
188
  * **Relationships** - Used by, extends, references
187
189
 
190
+ === Inline complex types
191
+
192
+ Elements that define an anonymous `<xs:complexType>` inline (without a `name`
193
+ attribute) are automatically surfaced in the documentation with a synthetic
194
+ name derived from the element name (e.g., `Person_type` for an element named
195
+ `Person`). These inline types appear alongside named complex types in the type
196
+ listing and include all their elements, attributes, sequences, and choices.
197
+
198
+ === Group tree view
199
+
200
+ Schema groups (`xs:group`) are rendered as expandable tree items that show
201
+ nested structure:
202
+
203
+ * **Groups** — Display name or reference, cardinality, and expandable content
204
+ * **Choices** — Shown with `⟨choice⟩` labels and nested options
205
+ * **Sequences** — Shown with their contained elements and sub-groups
206
+ * **Recursive nesting** — Groups can contain choices containing sequences
207
+ containing groups, all navigable in the tree
208
+
209
+ The tree supports arbitrary nesting depth and lazy expansion for large schemas.
210
+
188
211
  == Configuration
189
212
 
190
213
  === Overview
@@ -219,6 +219,14 @@ module Lutaml
219
219
  if xsd_elem
220
220
  @schema&.element(xsd_elem)
221
221
 
222
+ if xsd_elem&.complex_type&.mixed
223
+ ct = xsd_elem.complex_type
224
+ ct.name = "#{elem_name}_type"
225
+ @schema&.complex_type(ct)
226
+ xsd_elem.type = "#{elem_name}_type"
227
+ xsd_elem.complex_type = nil
228
+ end
229
+
222
230
  if name == elem_name
223
231
  # Define result IS the element itself
224
232
  result[:element] = xsd_elem
@@ -313,11 +321,23 @@ module Lutaml
313
321
  end
314
322
 
315
323
  # Check if a Ref resolves to an attribute group define
324
+ # Check if a ref name follows attribute group naming conventions.
325
+ # Used as a fallback when the define is not in @define_map (e.g., from
326
+ # unresolved include files where the Rng gem's IncludeProcessor fails).
327
+ def attribute_group_name?(name)
328
+ name.end_with?("Attributes", "Id")
329
+ end
330
+
316
331
  def ref_resolves_to_attribute_group?(ref)
317
332
  return false unless ref.is_a?(Rng::Ref) && ref.name
318
333
 
319
334
  define = @define_map[ref.name]
320
- return false unless define
335
+ unless define
336
+ # Ref not in define map — likely from an unresolved include.
337
+ # Fall back to name convention: attribute groups in RELAX NG
338
+ # schemas consistently end with "Attributes" or "Id".
339
+ return attribute_group_name?(ref.name)
340
+ end
321
341
 
322
342
  patterns = get_all_patterns(define)
323
343
  # Unwrap single Group
@@ -618,8 +638,16 @@ module Lutaml
618
638
  attr_group_refs = []
619
639
 
620
640
  attributes.each do |a|
621
- if a.is_a?(Rng::Ref)
641
+ case a
642
+ when Rng::Ref
622
643
  attr_group_refs << Lutaml::Xml::Schema::Xsd::AttributeGroup.new(ref: a.name)
644
+ when Rng::Optional, Rng::ZeroOrMore, Rng::OneOrMore
645
+ # Unwrap occurrence wrappers to reach the inner attribute pattern
646
+ inner = get_all_patterns(a).find { |p| p.is_a?(Rng::Attribute) }
647
+ if inner
648
+ converted = convert_attribute_pattern(inner)
649
+ xsd_attrs << converted if converted
650
+ end
623
651
  else
624
652
  converted = convert_attribute_pattern(a)
625
653
  xsd_attrs << converted if converted
@@ -679,6 +707,13 @@ module Lutaml
679
707
  attributes.each do |a|
680
708
  if a.is_a?(Rng::Ref)
681
709
  xsd_attr_group_refs << Lutaml::Xml::Schema::Xsd::AttributeGroup.new(ref: a.name)
710
+ elsif a.is_a?(Rng::Optional) || a.is_a?(Rng::ZeroOrMore) || a.is_a?(Rng::OneOrMore)
711
+ # Unwrap occurrence wrappers to reach the inner attribute pattern
712
+ inner = get_all_patterns(a).find { |p| p.is_a?(Rng::Attribute) }
713
+ if inner
714
+ converted = convert_attribute_pattern(inner)
715
+ xsd_attrs << converted if converted
716
+ end
682
717
  else
683
718
  converted = convert_attribute_pattern(a)
684
719
  xsd_attrs << converted if converted
@@ -970,6 +1005,14 @@ module Lutaml
970
1005
  end
971
1006
  end
972
1007
 
1008
+ if !has_mixed &&
1009
+ data_child.nil? &&
1010
+ attribute_children.any? &&
1011
+ particle_children.any?
1012
+
1013
+ has_mixed = true
1014
+ end
1015
+
973
1016
  xsd_elem = Lutaml::Xml::Schema::Xsd::Element.new(name: name)
974
1017
 
975
1018
  # Add documentation if present
@@ -96,7 +96,7 @@ module Lutaml
96
96
  entry.get_input_stream.read,
97
97
  permitted_classes: [Time, Date, Symbol],
98
98
  )
99
- when %r{^schemas/.+\.xsd$}, %r{^schemas/.+\.xml$}, %r{^schemas/.+\.xs$}
99
+ when %r{^schemas/.+\.xsd$}, %r{^schemas/.+\.rng$}, %r{^schemas/.+\.rnc$}
100
100
  schema_entries << entry.name
101
101
  end
102
102
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Lutaml
4
4
  module Xsd
5
- VERSION = "1.1.3"
5
+ VERSION = "1.1.4"
6
6
  end
7
7
  end
data/lutaml-xsd.gemspec CHANGED
@@ -35,7 +35,7 @@ Gem::Specification.new do |spec|
35
35
  spec.add_dependency "lutaml-model", "~> 0.8.0"
36
36
  spec.add_dependency "moxml"
37
37
  spec.add_dependency "paint", "~> 2.3"
38
- spec.add_dependency "rng", "~> 0.3"
38
+ spec.add_dependency "rng", "~> 0.3.5"
39
39
  spec.add_dependency "rubyzip", "~> 2.3"
40
40
  spec.add_dependency "table_tennis", "~> 0.0.7"
41
41
  spec.add_dependency "thor", "~> 1.0"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lutaml-xsd
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.3
4
+ version: 1.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2026-05-14 00:00:00.000000000 Z
11
+ date: 2026-05-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: liquid
@@ -78,14 +78,14 @@ dependencies:
78
78
  requirements:
79
79
  - - "~>"
80
80
  - !ruby/object:Gem::Version
81
- version: '0.3'
81
+ version: 0.3.5
82
82
  type: :runtime
83
83
  prerelease: false
84
84
  version_requirements: !ruby/object:Gem::Requirement
85
85
  requirements:
86
86
  - - "~>"
87
87
  - !ruby/object:Gem::Version
88
- version: '0.3'
88
+ version: 0.3.5
89
89
  - !ruby/object:Gem::Dependency
90
90
  name: rubyzip
91
91
  requirement: !ruby/object:Gem::Requirement