Canonical XML 1.0 without comments, the form XMLDSig digests.
OTP ships no xmerl_c14n, so this is written here. Output is compared
byte for byte against xmllint --c14n in the test suite: a canonicalisation
that disagrees with the reference by one byte produces a valid-looking
signature that SEFAZ rejects, and the failure gives no hint why.
What the specification asks for
Empty elements become a start and end tag pair, attribute values and text are escaped to a fixed set, namespace declarations come before attributes, and both are sorted — namespaces by prefix, attributes by namespace URI then local name.
The apex rule
A subtree being signed is canonicalised out of its document, so the top
element must render every namespace it merely inherited. infNFe carries no
xmlns of its own — the declaration sits on NFe — and omitting it there is
the classic reason an NF-e signature verifies locally and is refused by
SEFAZ. Descendants render only what differs from what an ancestor already
rendered.
This is Canonical XML 1.0, not the exclusive variant: every in-scope namespace is rendered, whether or not the subtree uses it.
Summary
Functions
Canonicalises element and everything under it.