/** * Minimal offset-preserving XML reader for AOT metadata files. * * A real parse + re-serialize would reformat the whole file (D365FO metadata XML * is diffed by humans and by TFVC), so this walks the tags and records offsets * instead, leaving every byte we don't touch exactly as it was. Every writer * built on it splices strings at those offsets. * * It lived inside formExtensionControlXml.ts, which is where the shape was first * needed. It is not about form extensions: the control-REMOVAL writer needs the * same tree over an AxForm's , and a second copy of a tag scanner that * has to get CDATA, comments and quoted attributes right is the kind of * duplication that drifts silently — one copy learns about `` CDATA * and the other does not, and the second one corrupts a file under a ✅. */ export interface XmlNode { name: string; /** Offset of '<' of the open tag. */ start: number; /** Offset just past '>' of the open tag. */ openEnd: number; /** Offset of '<' of the close tag (=== start when self-closing). */ closeStart: number; /** Offset just past '>' of the close tag. */ end: number; selfClosing: boolean; children: XmlNode[]; } /** Find the '>' that ends the tag opening at `from`, ignoring '>' inside attribute values. */ export declare function findTagEnd(xml: string, from: number): number; /** * Build an offset-carrying element tree. Returns null when the document is * unbalanced or otherwise not something we should be splicing into — the caller * then declines rather than guessing. */ export declare function parseNodes(xml: string): XmlNode | null; export declare const firstChild: (n: XmlNode, name: string) => XmlNode | undefined; export declare const textOf: (xml: string, n: XmlNode) => string; /** * Element text as the caller spelled it, undoing the escaping the emitters apply * (see escapeXmlText). Without this the round trip breaks: a name written as * `A & B` would never match the `A & B` the caller passes back, so an * idempotency check would miss it and a removal would report "not found". * * `&` last, mirroring the escape order. */ export declare const decodeXmlText: (value: string) => string; /** Element text, decoded — the form to compare against caller input or display. */ export declare const textValueOf: (xml: string, n: XmlNode) => string; /** True when `n` is `container` itself or lives inside its subtree. */ export declare const isWithin: (n: XmlNode, container: XmlNode) => boolean; /** Leading whitespace of the line `offset` sits on, for matching the file's indentation. */ export declare function lineIndentOf(xml: string, offset: number): string; //# sourceMappingURL=xmlNodeTree.d.ts.map