Specification text into a model (reverse-doc)
reverse rebuilds a model from a NodeSet2.xml, but a NodeSet carries no prose. reverse-doc
brings back the text of the published specification: it reads the Markdown export of the
OPC Foundation online reference and writes it into the documentation keys of the model, so
that generate produces the full companion-specification document again, ready to be revised
for the next release.
opcua-modeler reverse-doc -i Opc.Ua.ECM.NodeSet2.model.yaml \
-s https://reference.opcfoundation.org/specs/OPC-34100/v1.0.1/t63919218554/download/markdown \
--figures https://reference.opcfoundation.org/specs/OPC-34100/full
-s takes the Markdown export of the specification: the URL of its "download Markdown"
link on the online reference (.../specs/<id>/<version>/<token>/download/markdown), or a
downloaded copy of it. The HTML page itself (.../specs/<id>/full) is refused; it is the
--figures source. The model is rewritten in place unless --output is given.
Where the text goes
| Specification | Model |
|---|---|
| Clauses before the first type clause (Scope, references, terms, overview) | root documentation.description, numbers kept in the ## headings |
| The "Conventions for Node descriptions" clause | one sentence: the type tables are generated, the PDF conventions do not apply |
| A type clause | documentation of that type |
A <Name> Method clause | documentation of that method of the enclosing type |
| The Instances clause | a normative annex "Instances" (the generated document does not render instances) |
| Profiles and ConformanceUnits, Namespaces | normative annexes |
| Annex A, B, ... | annexes |
| Bibliography | documentation.bibliography |
Type clauses are found from the model: the clause number at the end of a type's or a method's
specRef (https://reference.opcfoundation.org/specs/OPC-34100/7.1.1), else a heading that
starts with the BrowseName of a type. Clauses the tool cannot place are listed as notes; route
them with --map.
Tables and figures
Tables the generator rebuilds from the model are dropped: captions ending in Definition,
Structure or Items, and the method signatures with their argument tables. Every other table,
including "Attribute values for child Nodes" and the definition tables of instances, is kept as
a Markdown table, because the generated document does not render child-node values or instances.
The NamespaceMetadata table becomes !generate(namespace-metadata).
A figure becomes  followed by its caption in italics.
--figures <url> downloads the images from the online reference page (or a saved copy of its
HTML) into images/ next to the model; existing files are kept.
What is left untouched
Only documentation keys are written. description attributes are never changed, so the
NodeSet2.xml that generate produces stays identical. Every line of the model outside the
documentation keys stays byte-for-byte as it was, comments included. Running the command a
second time replaces what the first run wrote.
Options
| Option | Meaning |
|---|---|
-i, --input <model.yaml> | the model to document (required) |
-s, --spec <spec.md or URL> | the Markdown export of the specification, a file or its download/markdown URL (required) |
-o, --output <file> | write here instead of rewriting the input |
--title <text> | root documentation title (default: keep the model's, else the spec id and version) |
--preface <file.md> | Markdown put before the spec text in the root description |
--keep-description [heading] | keep the model's own root description after the spec text, under a ## heading of that name. Without it the description is replaced |
--map <clause>=<Type>[.<Method>] | route a clause to a node (repeatable) |
--move-table <N>=<Type>[.<Method>] | append table N to another node's documentation, e.g. result codes shared by several methods (repeatable) |
--images-dir <dir> | figure folder relative to the model (default images) |
--figures <url or html> | download the figure images |
-v, --verbose | print the routing and every dropped table |
Existing annexes of the model that the specification does not provide are kept after the generated ones.
Example: a draft of the next release
opcua-modeler reverse-doc -i Opc.Ua.ECM.NodeSet2.model.yaml -s OPC-34100-v1.0.1.md \
--title "OPC 34100: OPC UA for Energy Consumption Management - Release 1.1.0 (draft)" \
--preface preface.md --keep-description "What is new in 1.1.0 (draft)" \
--move-table 33=EnergyStandbyManagementType --move-table 34=EnergyStandbyManagementType
The draft's own notes stay at the end of the root description under "What is new in 1.1.0 (draft)", and the two result-code tables, which apply to all three standby methods, move from the EndPause clause to the type.
Limits
- The generator resolves
!includeand annexfile:paths against its own working folder, not the model's, so the text is written inline. - The DSL has no
symbolicNamekey: a SymbolicName that the specification gives in a table stays in that table's text, it is not applied to the node. - Text directly under a container clause (e.g. "7 OPC UA ObjectTypes") is not written; it is listed as a note.