R/processXML.R
insertAlamarTargetIDXML.RdSets an AlamarTargetID attribute on every //BarcodeA/Barcode
element that lacks one, using a caller-supplied targetName to
alamarTargetID table. Existing attributes are never changed.
insertAlamarTargetIDXML(
input_XML,
targetMap,
output_XML = NULL,
overwrite = FALSE
)Character vector of paths to input XML files. Must be
non-empty, with no NA values, and every path must exist.
A data.frame, or the path to a CSV file, with exactly one
targetName column and one alamarTargetID column
(case-insensitive matching, no fuzzy matching). Values are trimmed;
rows whose id or name is missing, empty, or the literal string
"NA" (the value NULISAseq XML files use for "no id") are
ignored; identical rows collapse.
Where to write. NULL (default) writes nothing:
the call then only checks that every target resolves. A single path is a
directory when it already exists as one, ends with a path separator, or
there is more than one input; each file is then written under its own
basename and missing directories are created. With one input, a single
path that meets none of those conditions is the output file itself. A
character vector the same length as input_XML gives an explicit
output path per file, including writing in place (an output path equal
to its own input path). Two outputs that resolve to one file, an output
that resolves to another input, or an output path that is a directory
stop the function before any file is written.
Logical, TRUE or FALSE (default). When
FALSE, any resolved output path that already exists stops the
function before any file is written.
TRUE, invisibly, when every input resolved and was written
as requested. Otherwise the function stops.
The call either succeeds for every input or fails for all of them. Every file is resolved first; writing starts only when each id-less target in each file maps to exactly one id and no existing id contradicts the table. Otherwise the function stops with a message that lists every offending target (file, target name, barcode, reason), also written to the log at error level, and nothing is written.
Reasons for failure:
the target name is not in the table;
the table lists the target name under more than one id;
the element already carries an id that differs from the single id the table gives for that name;
the file has no //BarcodeA/Barcode elements or cannot be read.
On success, a file that received at least one id is re-serialized by
xml2::write_xml. Every other output path that differs from its
input receives a byte for byte copy, so a run yields one output per input;
an in-place output with nothing to insert is left untouched. Outputs are
first staged as temporary files beside their targets and then moved into
place together; if any step fails, staged files are removed, already
replaced targets are restored from backups, and the function stops, so no
partial batch is left behind. Two output paths are one output when they
resolve to the same file, through symlinks (dangling ones included), dot
components, or hard links to an existing file. A symlink at an output path
counts as an existing output, and overwrite = TRUE replaces the link
entry itself rather than writing through it. Because
xml2::write_xml re-serializes the whole document, writing changes
more than the inserted attribute: on a space-indented file that already
declares an encoding, only the declaration line (utf-8 becomes
UTF-8) and the edited lines change; on a tab-indented file, or one
with no XML declaration, every line is rewritten and a declaration is
added. One line per file is logged at info level.
targetMap accepts any table with a targetName column and an
alamarTargetID column (case-insensitive), for example a hiplex
targets export, or the path to a CSV file with those columns.
insertCovariatesXML, which shares this file's
xml2 conventions but has a different contract: it returns the
modified in-memory document rather than writing files.
if (FALSE) { # \dontrun{
# one run, written next to the original
insertAlamarTargetIDXML("run.xml", targetMap = "hiplex_targets.csv",
output_XML = "run_with_ids.xml")
# a folder of legacy runs into a new folder; fails, writing nothing,
# if any target cannot be resolved from the table
xmls <- list.files("legacy", pattern = "\\.xml$", full.names = TRUE)
insertAlamarTargetIDXML(xmls, targetMap = hiplex_targets,
output_XML = "legacy_with_ids/")
} # }