Files
skills/docs/foundation/data/mime/src/charset/sniff-xml-decl.md
2026-05-29 08:20:56 +01:00

2.5 KiB

sniff-xml-decl

Purpose

Extracts the declared encoding from an XML or SVG document's processing instruction (<?xml version="1.0" encoding="UTF-8"?>). XML documents commonly declare their encoding in the prolog, and this declaration must be trusted before any BOM or HTTP header when present, per the XML specification (RFC 7303).

Features

  • Matches the encoding attribute in <?xml ... encoding="..."?> declarations
  • Supports both double-quoted and single-quoted attribute values
  • Case-insensitive matching — ENCODING and encoding both match
  • Scans only the first 256 characters (the XML prolog is always at the start)
  • Returns the encoding name in lowercase for canonical comparison
  • Returns null when no XML declaration or encoding attribute is found
  • Handles whitespace variations between attributes

Usage: Basic Example

import { sniffXmlDecl } from "@suaveplan/mime/charset/sniff-xml-decl";

const xml = '<?xml version="1.0" encoding="UTF-8"?><root/>';
const encoding = sniffXmlDecl(xml);
console.log(encoding); // "utf-8"

Usage: Advanced Example

import { sniffXmlDecl } from "@suaveplan/mime/charset/sniff-xml-decl";
import { sniffBom } from "@suaveplan/mime/charset/sniff-bom";

function detectXmlEncoding(bytes: Uint8Array): string {
    // BOM overrides XML declaration per RFC 7303 §4.3
    const bom = sniffBom(bytes);
    if (bom) return bom;

    // Use latin-1 to safely read the ASCII-range prolog
    const prolog = new TextDecoder("latin1").decode(bytes.slice(0, 256));
    const declared = sniffXmlDecl(prolog);

    return declared ?? "utf-8"; // XML default encoding
}

// Single-quoted attribute
const svgWithSingleQuotes = "<?xml version='1.0' encoding='iso-8859-1'?><svg/>";
console.log(sniffXmlDecl(svgWithSingleQuotes)); // "iso-8859-1"

API Reference

sniffXmlDecl(source: string): string | null

Parameter Type Description
source string XML/SVG content (or the first chunk thereof).

Returns: The lowercase IANA encoding name, or null when no encoding attribute is found.

Throws: Never.

Implementation Notes

The regex /<\?xml[^?]*encoding\s*=\s*["']([^"']+)["']/i intentionally uses [^?]* (non-greedy via exclusion) rather than .*? to avoid backtracking across large documents when no <?xml declaration is present. The 256-character scan window is sufficient because the XML specification mandates that the encoding declaration, if present, must appear in the document prolog before any other content.