Emits the specification as a Define-XML 2.1 file: an ODM 1.3.2 root carrying the def 2.1 namespace and def:DefineVersion="2.1.0", a Study with GlobalVariables, and a MetaDataVersion holding def:Standards, one ItemGroupDef per dataset (with Purpose, def:Structure, def:Class, def:ArchiveLocationID and its def:leaf), one ItemDef per variable (with DataType, Length, def:DisplayFormat, def:Origin and CodeListRef), ItemRefs carrying OrderNumber, Mandatory, KeySequence, Role and MethodOID, plus CodeList, MethodDef and def:CommentDef elements.

write_define(spec, path)

Arguments

spec

A define21_spec object from define_spec() or read_define().

path

File path to write to.

Value

path, invisibly.

Details

Value level metadata is emitted as one def:ValueListDef per variable that has values, referenced from the variable's ItemDef by def:ValueListRef; each of its ItemRefs carries a def:WhereClauseRef into a def:WhereClauseDef built from RangeCheck/CheckValue. Both are written before ItemGroupDef, which is where the 2.1 content model puts them. Codelists in spec$external_codelists are emitted as a CodeList holding a single ExternalCodeList with Dictionary and Version.

This replaces the usual round trip through Excel and a PROC TEMPLATE / vendor generator: the XML is built from the same object check_define() compares against the data, so the document and the checks cannot disagree.

Analysis results metadata (ARM) is not written. It is a separate model with its own namespace and its own conformance rules, and half of it is worse than none: see the package README for the reasoning.

Examples

spec <- define21_example()$spec
out <- write_define(spec, tempfile(fileext = ".xml"))
doc <- xml2::read_xml(out)
xml2::xml_attr(xml2::xml_find_first(doc, "//d1:MetaDataVersion", xml2::xml_ns(doc)),
               "def:DefineVersion", ns = xml2::xml_ns(doc))
#> [1] "2.1.0"