import { DOMParser } from 'xmldom' import LocationGenerator from '../generators/LocationGenerator' export const resolveLocationRefs = ( xml: string, locations: Record = {} ): string => { const parser = new DOMParser() const dom = parser.parseFromString(xml, 'text/xml') // replace person nodes with their actual content const useLocationNodes = Array.from(dom.getElementsByTagName('UseLocation')) useLocationNodes.forEach( useLocationNode => { const locationRef = useLocationNode.getAttribute('ref') if (!locationRef) return // get the person generator for this tag const location = locations[locationRef] if (!location) return // get the children of the tag // these are the nodes that need to be resolved const children = Array .from(useLocationNode.childNodes) .filter((n) => n.nodeType === 1) // resolve the children nodes children.forEach((child) => { switch (child.nodeName) { case 'Address': { const address = location.getAddress() const textNode = dom.createTextNode(address) child.parentNode?.replaceChild(textNode, child) break } case 'Street': { const street = location.toString('{street}') const textNode = dom.createTextNode(street) child.parentNode?.replaceChild(textNode, child) break } case 'City': { const city = location.toString('{city}') const textNode = dom.createTextNode(city) child.parentNode?.replaceChild(textNode, child) break } case 'State': { const state = location.toString('{state}') const textNode = dom.createTextNode(state) child.parentNode?.replaceChild(textNode, child) break } case 'Zip': { const zip = location.toString('{zip}') const textNode = dom.createTextNode(zip) child.parentNode?.replaceChild(textNode, child) break } case 'Country': { const country = location.toString('{country}') const textNode = dom.createTextNode(country) child.parentNode?.replaceChild(textNode, child) break } default: throw new Error(`Unknown tag: ${child.nodeName}`) } }) // parent content is the child nodes of the node const parentContent = Array.from(useLocationNode.childNodes) // replace the node with the children nodes parentContent.forEach((child) => { useLocationNode.parentNode?.insertBefore(child, useLocationNode) }) useLocationNode.parentNode?.removeChild(useLocationNode) }) return dom.toString() }