xsd-lookup
Version:
Multi-schema XSD lookup utility
373 lines • 14.9 kB
TypeScript
export interface ElementLocation {
uri: string;
line: number;
column: number;
lengthOfStartTag: number;
}
export interface EnhancedAttributeInfo {
name: string;
type?: string;
location?: ElementLocation;
required?: boolean;
enumValues?: string[];
enumValuesAnnotations?: Map<string, string>;
annotation?: string;
patterns?: string[];
minLength?: number;
maxLength?: number;
minInclusive?: number;
maxInclusive?: number;
minExclusive?: number;
maxExclusive?: number;
}
export interface AttributeValidationResult {
isValid: boolean;
expectedType?: string;
allowedValues?: string[];
errorMessage?: string;
restrictions?: string[];
}
export declare class Schema {
private doc;
private name;
private schemaIndex;
private elementMap;
private cache;
private cacheStats;
private methodTimings;
private methodCalls;
private maxCacheSize;
private shouldProfileCaches;
private shouldProfileMethods;
private static readonly numericTypes;
private static readonly builtInTypes;
constructor(xsdFilePath: string, includeFiles?: string[]);
/**
* Initialize all cache structures with empty maps
*/
private initializeCaches;
private initializeCacheStats;
private printCacheStats;
private profStart;
private profEnd;
private printMethodStats;
/**
* Clear all caches by reinitializing them
*/
clearCache(): void;
/**
* Ensure cache sizes don't exceed the maximum limit using simple LRU eviction
*/
private ensureCacheSize;
/**
* Load and parse an XML file into a DOM Document
* @param filePath The path to the XML file to load
* @returns Parsed DOM Document
*/
private loadXml;
/**
* Merge included XSD documents into the main schema document
* @param mainDoc The main schema document to merge into
* @param includeDoc The included schema document to merge from
*/
private mergeXsds;
/**
* Recursively collect all element definitions from the schema DOM
* @param node The current node to examine
* @param parentName The name of the parent element
* @param elements Array to collect found elements into
* @returns Array of collected elements with their parent information
*/
private collectElements;
/**
* Build a map of element names to their definitions and parent relationships
* @returns Record mapping element names to arrays of their definitions
*/
private buildElementMap;
/**
* Index the schema by collecting all global elements, groups, attribute groups, and types
* @param root The root schema element
* @param ns The XML Schema namespace prefix
* @returns Complete schema index with all definitions and contexts
*/
private indexSchema;
/**
* Build comprehensive element contexts, including elements reachable through groups
*/
private buildElementContexts;
/**
* Extract all elements from a group and add them to element contexts
*/
private extractElementsFromGroup;
/**
* Extract elements from a group while maintaining parent context information
*/
private extractElementsFromGroupWithParentContext;
/**
* Extract all elements from a complex type and add them to element contexts
*/
private extractElementsFromType;
/**
* Extract inline elements from a global element definition
* This captures elements like param under params that are defined inline
*/
private extractInlineElementsFromElement;
getElementDefinition(elementName: string, hierarchy?: string[]): Element | undefined;
/**
* Get global element definitions by name (direct children of schema root only)
* @param elementName The name of the element to find
* @returns Array of global element definitions
*/
private getGlobalElementDefinitions;
/**
* Get global element or type definitions by name for hierarchical search
* @param name The name to search for
* @returns Array of element or type definitions matching the name
*/
private getGlobalElementOrTypeDefs;
/**
* Find element definitions within a parent definition by element name
* @param parentDef The parent element or type definition to search in
* @param elementName The name of the element to find
* @returns Array of matching element definitions
*/
private findElementsInDefinition;
/**
* Find ALL immediate child elements within a parent definition (without filtering by name)
* This is similar to findElementsInDefinition but returns all direct child elements
* @param parentDef The parent element or type definition to search in
* @returns Array of all immediate child element definitions
*/
private findAllElementsInDefinition;
/**
* Get enhanced attribute information including type and validation details
*/
getElementAttributes(elementName: string, hierarchy?: string[], element?: Element): Record<string, Element>;
/**
* Recursively collect attributes from element and type definitions
* @param node The current node to collect attributes from
* @param attributes Record to accumulate found attributes
* @param visited Set to track visited nodes and prevent infinite recursion
*/
private collectAttrs;
/**
* Get enhanced attribute information including type and validation details
*/
getElementAttributesWithTypes(elementName: string, hierarchy?: string[], element?: Element): Record<string, EnhancedAttributeInfo>;
/**
* Get comprehensive validation information for a type
*/
private getTypeValidationInfo;
/**
* Get validation information from inline type definitions (xs:simpleType within attribute)
*/
private getInlineTypeValidationInfo;
/**
* Get cached validation information for a node
*/
private getCachedValidationInfo;
/**
* Extract validation rules from a node (reusable logic)
*/
private extractValidationRulesFromNode;
/**
* Validate an attribute value against its XSD definition
*/
validateAttributeValue(elementName: string, attributeName: string, attributeValue: string, hierarchy?: string[]): AttributeValidationResult;
/**
* Normalize multi-line attribute values for validation
* Joins multiple lines into a single line, removing newlines and extra spaces
*/
private normalizeAttributeValue;
/**
* Validate a value against all possible XSD restrictions
*/
private validateValueWithRestrictions;
/**
* Check if a built-in XSD type is numeric (based on actual XSD built-in types)
*/
/**
* Check if a built-in XSD type is numeric (based on actual XSD built-in types)
* @param builtinType The built-in XSD type to check
* @returns True if the type is numeric, false otherwise
*/
private isBuiltinNumericType;
/**
* Validate basic XSD types based on actual XSD definitions, not hardcoded assumptions
*/
private validateBasicType;
/**
* Resolve a type name to its ultimate built-in XSD type
*/
private resolveToBuiltinType;
/**
* Helper method to find child elements by name
*/
private findChildElements;
/**
* Validate against built-in XSD types only
*/
private validateBuiltinXsdType;
/**
* Find element using top-down hierarchy search
* @param elementName The element to find
* @param topDownHierarchy Hierarchy from root to immediate parent [root, ..., immediate_parent]
* @returns Element definition if found, undefined otherwise
*/
private findElementTopDown;
/**
* Get the element source location: file URI and position in the source file.
* Uses the 'data-source-file' and 'start-tag-length' annotations (added during XSD load) and line/column info on the Element.
* Returns undefined if source file is unknown.
*/
static getElementLocation(element: Element): ElementLocation | undefined;
/**
* Extract annotation text from an XSD element's xs:annotation/xs:documentation
*/
extractAnnotationText(element: Element): string | undefined;
/**
* Extract enum value annotations from a type definition
* @param typeNode The type definition element to extract enum annotations from
* @returns Map of enum values to their annotation text
*/
private extractEnumValueAnnotations;
/**
* Get possible child elements for a given element by name and hierarchy
* @param elementName The parent element name
* @param hierarchy The element hierarchy in bottom-up order (parent → root)
* @param previousSibling Optional previous sibling element name to filter results based on sequence constraints
* @returns Map where key is child element name and value is its annotation text
*/
getPossibleChildElements(elementName: string, hierarchy?: string[], previousSibling?: string): Map<string, string>;
/**
* Check if a specific element is valid as a child of a given parent in the provided hierarchy,
* using the same engine and constraints as getPossibleChildElements, but without calling it directly.
*
* Contract:
* - Inputs: elementName, parentName, parentHierarchy (bottom-up: [immediate_parent, ..., root]), optional previousSibling
* - Output: boolean indicating if elementName can appear next under parentName respecting content model and sequence rules
*/
isValidChild(elementName: string, parentName: string, parentHierarchy?: string[], previousSibling?: string): boolean;
private getModelStartSet;
private getModelNextSet;
/**
* Filter child elements based on XSD sequence constraints and previous sibling
* @param elementDef The parent element definition
* @param allChildren All possible child elements
* @param previousSibling The name of the previous sibling element
* @returns Filtered array of elements that are valid as next elements
*/
private filterElementsBySequenceConstraints;
/**
* Find the content model (sequence/choice/all) within an element definition
* @param elementDef The element definition to search
* @returns The content model element, or null if not found
*/
private findContentModel;
private getCachedContentModel;
getAnnotationCached(el: Element): string;
/**
* Find direct content model in a complexType, extension, or restriction
* @param parent The parent element to search in
* @returns The content model element, or null if not found
*/
private findDirectContentModel;
/**
* Get valid next elements based on content model and previous sibling
* @param contentModel The sequence/choice/all element
* @param previousSibling The name of the previous sibling
* @param allChildren All possible child elements for reference
* @returns Filtered elements that are valid as next elements
*/
private getValidNextElementsInContentModel;
/**
* Get valid next elements in a choice based on previous sibling
* @param choice The choice element
* @param previousSibling The name of the previous sibling
* @param allChildren All possible child elements for reference
* @returns Valid next elements
*/
private getValidNextInChoice;
/**
* Get valid next elements in a sequence based on previous sibling
* @param sequence The sequence element
* @param previousSibling The name of the previous sibling
* @param allChildren All possible child elements for reference
* @returns Valid next elements in the sequence
*/
private getValidNextInSequence;
/**
* Collect element names that are part of sequence alternatives in a choice but are NOT start elements
* (i.e., elements that appear at position >= 2 in those sequences). Used to avoid leaking follow-up-only
* items like do_elseif/do_else when not continuing inside that sequence arm.
*/
private getNonStartElementsInChoiceSequences;
/**
* Check if a sequence item (element, choice, group) contains the specified element
* @param item The sequence item to check
* @param element The element name to look for
* @returns True if the item contains the element
*/
private itemContainsElement;
/**
* Find a nested sequence within a choice that contains the specified element
*/
private findNestedSequenceContainingElement;
/**
* Check if a choice contains the specified element
* @param choice The choice element
* @param elementItem The element name to look for
* @returns True if the choice contains the element
*/
private choiceContainsElement;
/**
* Get elements from a sequence item (element, choice, group)
* @param item The sequence item
* @param allChildren All possible child elements for reference
* @returns Array of elements from the item
*/
private getElementsFromSequenceItem;
/**
* Get all elements within a choice
* @param choice The choice element
* @param allChildren All possible child elements for reference
* @returns Array of elements that are options in the choice
*/
private getElementsInChoice;
/**
* Get the set of elements that can legally start the provided sequence, honoring minOccurs on leading items.
*/
private getStartElementsOfSequence;
/**
* Return the elements that can appear at the start position of a sequence item.
*/
private getStartElementsFromItem;
/**
* Compute effective minOccurs for a sequence child item, propagating from the enclosing sequence if undefined.
*/
private getEffectiveMinOccurs;
/**
* Compute effective maxOccurs for a sequence child item, propagating from the enclosing sequence if undefined.
*/
private getEffectiveMaxOccurs;
/**
* Check if a type name is a built-in XSD type
* @param typeName The type name to check
* @returns True if it's a built-in type
*/
private isBuiltInXsdType;
/**
* Get enumeration values for a named SimpleType
* @param simpleTypeName The name of the SimpleType to get enumeration values from
* @returns Object containing enumeration values and their annotations, or null if not found or not an enumeration
*/
getSimpleTypeEnumerationValues(simpleTypeName: string): {
values: string[];
annotations: Map<string, string>;
} | null;
/**
* Clear all caches and resources
*/
dispose(): void;
}
//# sourceMappingURL=Schema.d.ts.map