first commit
This commit is contained in:
64
docs/foundation/data/mime/src/charset/sniff-xml-decl.md
Normal file
64
docs/foundation/data/mime/src/charset/sniff-xml-decl.md
Normal file
@@ -0,0 +1,64 @@
|
||||
# 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
|
||||
|
||||
```typescript
|
||||
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
|
||||
|
||||
```typescript
|
||||
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.
|
||||
Reference in New Issue
Block a user