You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: examples/README.md
+1Lines changed: 1 addition & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -4,3 +4,4 @@ Examples contained in this directory:
4
4
5
5
-[`read_write`](./read_write/README.md) - Generates code from a simple schema using a build script and then uses the generated code to deserialize and serialize a XML file during runtime.
6
6
-[`bpmn`](./bpmn/README.md) - Example that generates code for BPMN 2.0 and loads a diagram file.
7
+
-[`vsme`](./vsme/README.md) - Example that generates code for the XBRL based VSME taxonomy. It shows how a custom render step can be used to collapse the huge `xbrli:item` substitution group into a few `ItemWrapper` based types instead of generating one type per element.
This example generates and uses the code for the XBRL based [VSME](https://xbrl.efrag.org/) taxonomy (the *Voluntary standard for non-listed Small- and Medium-sized Enterprises*).
4
+
5
+
XBRL instance documents store their facts as members of the `xbrli:item` substitution group. The VSME taxonomy defines **thousands** of such facts, but most of them share the same underlying type and only differ by their XML tag name (e.g. `vsme:Assets`, `vsme:AverageNumberOfAnnualTrainingHoursPerMaleEmployee`, ...). Generating a dedicated Rust type (and `enum` variant) for every single element would produce a huge, unwieldy amount of code.
6
+
7
+
## What this example shows
8
+
9
+
Instead of generating one type per element, the [build script](build.rs) installs a custom [`RenderStep`] (`FixItemType`) that:
10
+
11
+
1. Looks up the content of the `xbrli:item` element (a big `xs:choice`).
12
+
2. Groups all element variants of the choice by their type and removes them from the choice.
13
+
3. Adds a single group element per type that references a synthetic `XxxWrapped` custom type.
14
+
4. Emits a type definition and an [`ItemTags`](src/item.rs) implementation for each of those wrapper types:
impl crate::item::ItemTags for AmountOfEmissionToAirWrappedTags {
23
+
fn tags() -> &'static [crate::item::ItemTag] {
24
+
static TAGS: [crate::item::ItemTag; 78] = [
25
+
crate::item::ItemTag {
26
+
tag: "vsme:Assets",
27
+
name: "Assets",
28
+
namespace: NS_VSME,
29
+
},
30
+
/* ... */
31
+
];
32
+
33
+
&TAGS
34
+
}
35
+
}
36
+
```
37
+
38
+
The [`ItemWrapper`](src/item.rs) type defined in this example provides the runtime support for this. It wraps the shared inner type and implements a `Serializer` and `Deserializer` that:
39
+
40
+
- on **deserialization**, only accept an element whose namespace-resolved tag is part of the associated `ItemTags` (so a document may use any prefix for the namespace), and remember which tag was used; and
41
+
- on **serialization**, write the value back using that remembered tag.
42
+
43
+
This way a few hundred elements collapse into just a handful of generated types while the round-trip still preserves the exact XML tag of every fact.
44
+
45
+
## Running
46
+
47
+
```sh
48
+
cargo run -p vsme
49
+
```
50
+
51
+
This deserializes [`xml/example.xml`](xml/example.xml), prints the parsed object and serializes it back to XML.
0 commit comments