All files / src/preprocessor resolveLocationRefs.ts

93.33% Statements 42/45
75% Branches 9/12
100% Functions 5/5
97.67% Lines 42/43

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87        1x       32x 32x     32x   32x 3x 3x     3x 3x       3x   25x     3x 11x   1x 1x 1x 1x     2x 2x 2x 2x     2x 2x 2x 2x     2x 2x 2x 2x     2x 2x 2x 2x     2x 2x 2x 2x                 3x     3x 25x     3x     32x    
import { DOMParser } from 'xmldom'
 
import LocationGenerator from '../generators/LocationGenerator'
 
export const resolveLocationRefs = (
    xml: string,
    locations: Record<string, LocationGenerator> = {}
): 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')
        Iif (!locationRef) return
 
        // get the person generator for this <UsePerson> tag
        const location = locations[locationRef]
        Iif (!location) return
 
        // get the children of the <UsePerson> 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 <UsePerson> node
        const parentContent = Array.from(useLocationNode.childNodes)
 
        // replace the <UsePerson> node with the children nodes
        parentContent.forEach((child) => {
            useLocationNode.parentNode?.insertBefore(child, useLocationNode)
        })
 
        useLocationNode.parentNode?.removeChild(useLocationNode)
    })
 
    return dom.toString()
}