(name: string, value: string)
| 228 | } |
| 229 | |
| 230 | onAttribute(name: string, value: string): void { |
| 231 | if (this.#hasPendingElement) { |
| 232 | // Validate QName syntax for attribute name (Namespaces §3) |
| 233 | const colonIndex = name.indexOf(":"); |
| 234 | const qnameError = validateQName(name, colonIndex); |
| 235 | if (qnameError) { |
| 236 | throw new XmlSyntaxError( |
| 237 | `Invalid attribute name '${name}': ${qnameError}`, |
| 238 | { |
| 239 | line: this.#pendingLine, |
| 240 | column: this.#pendingColumn, |
| 241 | offset: this.#pendingOffset, |
| 242 | }, |
| 243 | ); |
| 244 | } |
| 245 | |
| 246 | // Validate namespace binding if this is an xmlns attribute |
| 247 | if (name === "xmlns" || name.startsWith("xmlns:")) { |
| 248 | // Normalize the attribute value for namespace URI |
| 249 | const normalizedValue = normalizeAttributeValue(value, this.#xml11); |
| 250 | const nsError = validateNamespaceBinding( |
| 251 | name, |
| 252 | normalizedValue, |
| 253 | this.#xml11, |
| 254 | ); |
| 255 | if (nsError) { |
| 256 | throw new XmlSyntaxError( |
| 257 | nsError, |
| 258 | { |
| 259 | line: this.#pendingLine, |
| 260 | column: this.#pendingColumn, |
| 261 | offset: this.#pendingOffset, |
| 262 | }, |
| 263 | ); |
| 264 | } |
| 265 | // Track xmlns:prefix declarations |
| 266 | if (name.startsWith("xmlns:")) { |
| 267 | const prefix = name.slice(6); // After "xmlns:" |
| 268 | // Lazy init namespace bindings |
| 269 | if (!this.#nsBindings) { |
| 270 | this.#nsBindings = new Map([["xml", XML_NAMESPACE]]); |
| 271 | } |
| 272 | // Save previous binding for restoration |
| 273 | this.#pendingNsBindings.push([prefix, this.#nsBindings.get(prefix)]); |
| 274 | this.#nsBindings.set(prefix, normalizedValue); |
| 275 | } |
| 276 | } |
| 277 | |
| 278 | if (this.#attrIterator.count >= this.#maxAttributes) { |
| 279 | throw new XmlSyntaxError( |
| 280 | `Attribute count exceeds limit of ${this.#maxAttributes}`, |
| 281 | { |
| 282 | line: this.#pendingLine, |
| 283 | column: this.#pendingColumn, |
| 284 | offset: this.#pendingOffset, |
| 285 | }, |
| 286 | ); |
| 287 | } |
nothing calls this directly
no test coverage detected