xml_structure
Analyze XML file structure quickly by extracting element counts, attribute usage, namespaces, and hierarchy details without full file processing. Configure depth and byte limits for efficient handling of large files.
Instructions
Analyze XML file structure without reading the entire file. Returns statistical information about element counts, attribute usage, namespaces, and hierarchical structure. Useful for understanding the structure of large XML files before performing detailed queries. Requires maxBytes (default 10KB) and maxDepth (default 2) parameters. The path must be within allowed directories.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| includeAttributes | No | Whether to include attribute information | |
| maxBytes | Yes | Maximum bytes to read from the file. Must be a positive integer. Handler default: 10KB. | |
| maxDepth | Yes | How deep to analyze the hierarchy. Must be a positive integer. Handler default: 2. | |
| path | Yes | Path to the XML file to analyze |
Implementation Reference
- src/handlers/xml-handlers.ts:82-145 (handler)Main handler function for the 'xml_structure' tool. Validates arguments, reads and parses the XML file, extracts structure using extractXmlStructure, handles response size limits, and returns the structure as JSON.export async function handleXmlStructure( args: unknown, allowedDirectories: string[], symlinksMap: Map<string, string>, noFollowSymlinks: boolean ): Promise<{ content: Array<{ type: string; text: string }> }> { const parsed = parseArgs(XmlStructureArgsSchema, args, 'xml_structure'); const validPath = await validatePath( parsed.path, allowedDirectories, symlinksMap, noFollowSymlinks ); try { const xmlContent = await fs.readFile(validPath, 'utf8'); try { const parser = new XmldomDOMParser(); const doc: any = parser.parseFromString(xmlContent, 'text/xml'); const structure = extractXmlStructure( doc, parsed.maxDepth, parsed.includeAttributes ); const responseLimit = (parsed as any).maxResponseBytes ?? parsed.maxBytes ?? 200 * 1024; // 200KB default let json = JSON.stringify(structure, null, 2); if (typeof responseLimit === 'number' && responseLimit > 0) { const size = Buffer.byteLength(json, 'utf8'); if (size > responseLimit) { // Fallback to a summarized structure to respect response limit const summary = { rootElement: structure.rootElement, namespaces: structure.namespaces, elementTypeCount: Object.keys(structure.elements).length, attributeKeyCount: structure.attributes ? Object.keys(structure.attributes).length : 0, hierarchy: structure.hierarchy ? { name: structure.hierarchy.name, hasChildren: structure.hierarchy.hasChildren, childrenCount: structure.hierarchy.children?.length ?? 0 } : undefined, _meta: { truncated: true, note: `Full structure omitted to fit response limit of ${responseLimit} bytes` } }; json = JSON.stringify(summary, null, 2); } } return { content: [{ type: 'text', text: json }] }; } catch (err) { const errorMessage = err instanceof Error ? err.message : String(err); throw new Error(`Failed to extract XML structure: ${errorMessage}`); } } catch (err) { const errorMessage = err instanceof Error ? err.message : String(err); throw new Error(`Failed to analyze XML structure: ${errorMessage}`); } }
- src/handlers/xml-handlers.ts:313-347 (helper)Core helper function that extracts detailed XML structure: root element, element counts, attribute counts, namespaces, and hierarchy up to maxDepth.function extractXmlStructure(doc: any, maxDepth = 2, includeAttributes = true): XmlStructureInfo { const structure: XmlStructureInfo = { rootElement: doc.documentElement?.nodeName, elements: {}, attributes: includeAttributes ? {} : undefined, namespaces: extractNamespaces(doc), }; // Get all element names and counts const elementQuery = "//*"; const elements = xpath.select(elementQuery, doc) as any[]; elements.forEach((element) => { const el = element as any; const name = el.nodeName; structure.elements[name] = (structure.elements[name] || 0) + 1; if (includeAttributes && el.attributes && el.attributes.length > 0) { for (let i = 0; i < el.attributes.length; i++) { const attr = el.attributes[i]; const attrKey = `${name}@${attr.nodeName}`; if (structure.attributes) { structure.attributes[attrKey] = (structure.attributes[attrKey] || 0) + 1; } } } }); // Get child relationship structure up to maxDepth if (maxDepth > 0 && doc.documentElement) { structure.hierarchy = buildHierarchy(doc.documentElement, maxDepth); } return structure; }
- TypeBox schema defining input parameters for the xml_structure tool: path, maxDepth, includeAttributes, size limits.export const XmlStructureArgsSchema = Type.Object({ path: Type.String({ description: 'Path to the XML file to analyze' }), maxDepth: Type.Integer({ minimum: 1, description: 'How deep to analyze the hierarchy. Must be a positive integer. Handler default: 2.' }), includeAttributes: Type.Optional(Type.Boolean({ default: true, description: 'Whether to include attribute information' })), maxBytes: Type.Optional(Type.Integer({ minimum: 1, description: '[Deprecated semantics] Previously limited file bytes read; now treated as a response size cap in bytes.' })), maxResponseBytes: Type.Optional(Type.Integer({ minimum: 1, description: 'Maximum size, in bytes, of the returned content. Parsing reads full file; response may be truncated to respect this limit.' })) }); export type XmlStructureArgs = Static<typeof XmlStructureArgsSchema>;
- index.ts:259-260 (registration)Registers the handleXmlStructure function as the executor for the 'xml_structure' tool in the toolHandlers object, which is used in server.addTool.xml_structure: (a: unknown) => handleXmlStructure(a, allowedDirectories, symlinksMap, noFollowSymlinks),
- index.ts:322-322 (registration)Includes 'xml_structure' in the allTools list with description, used to conditionally add the tool via server.addTool.{ name: "xml_structure", description: "Analyze XML structure" },