XMP has no fixed binary layout, so this is a layered regex scan over the
XML text (browsers and Node share no streaming XML DOM we can rely on, and
the packets are small). The passes run in this order — LATER passes DO NOT
overwrite values set by EARLIER ones except where a tag is in xmpPriority:
renameContextProperties: scoped rewrites inside crs:Look /
crs:CorrectionMasks structs (crs:Version -> crs:LookVersion etc.) so
nested names map to their flattened exiftool names.
docPattern attributes: attributes on rdf:Description open tags.
listPattern elements: child elements of rdf:Description; rdf:Bag/Seq/Alt
-> arrays (lang-alts resolved via x-default), simple text -> scalars,
struct elements -> their ATTRIBUTES mapped as tags (self-closing ones
handled by a dedicated pass — this is how <xmpMM:DerivedFrom
stRef:documentID="..."> and <Iptc4xmpCore:CreatorContactInfo
Iptc4xmpCore:CiUrlWork="..."> flatten).
structPattern / allDescPattern: attributes on every rdf:Description
(self-closing and open), catching values written as properties.
childElPattern / liAttrPattern: orphan simple elements and attributed
rdf:li items anywhere in the document.
Normalization at the end: XML entities decoded once (& last), booleans
lower-cased, numeric strings trimmed of trailing zeros, XMP rationals
("39/100") rendered as floats, ISO dates rewritten to EXIF "YYYY:MM:DD
HH:MM:SS[±tz]" form. Namespace prefixes with hyphens (XMP-lr, XMP-iptcCore)
are matched throughout.
Names: TAG_REMAP maps "prefix:local" to exiftool's tag name; unmapped tags
fall back to their local name.
Parses an XMP packet into exiftool-named tags.
XMP has no fixed binary layout, so this is a layered regex scan over the XML text (browsers and Node share no streaming XML DOM we can rely on, and the packets are small). The passes run in this order — LATER passes DO NOT overwrite values set by EARLIER ones except where a tag is in xmpPriority:
Normalization at the end: XML entities decoded once (& last), booleans lower-cased, numeric strings trimmed of trailing zeros, XMP rationals ("39/100") rendered as floats, ISO dates rewritten to EXIF "YYYY:MM:DD HH:MM:SS[±tz]" form. Namespace prefixes with hyphens (XMP-lr, XMP-iptcCore) are matched throughout.
Names: TAG_REMAP maps "prefix:local" to exiftool's tag name; unmapped tags fall back to their local name.