{nixpkgs, ...}: { toXMLGeneric = let toXMLRecursive = toXmlRecursive' "\n" 0; indent = depth: ( if (depth <= 0) then "" else (" " + (indent (depth - 1))) ); toXmlRecursive' = str: depth: xml: let parseTag = str: depth: xml: (builtins.concatStringsSep "" [ str "${indent depth}<${xml.tag}${ if (builtins.hasAttr "content" xml) && ((builtins.isString xml.content) || (builtins.isList xml.content) && ((builtins.length xml.content) > 0)) then ">" else " " }" ( if (builtins.hasAttr "attrib" xml) then (" " + builtins.concatStringsSep " " (nixpkgs.lib.attrsets.mapAttrsToList (name: value: "${name}=\"${nixpkgs.lib.strings.escapeXML value}\"") xml.attrib)) else "" ) ( if (builtins.hasAttr "content" xml) && ((builtins.isString xml.content) || (builtins.isList xml.content) && ((builtins.length xml.content) > 0)) then ((toXmlRecursive' "\n" (depth + 1) xml.content) + "") else "/>" ) ]); in if (builtins.isAttrs xml) then "${parseTag str depth xml}\n${indent (depth - 1)}" else if (builtins.isList xml) then "\n${(builtins.concatStringsSep "" (builtins.map (x: (toXmlRecursive' "" depth x)) xml))}${indent (depth - 1)}" else if ((builtins.isBool xml) || (builtins.isInt xml) || (builtins.isNull xml) || (builtins.isFloat xml)) then (builtins.toString xml) else if (builtins.isString xml) then xml else throw "Cannot convert a ${builtins.typeOf xml} to XML. ${toString (builtins.trace xml xml)}"; in toXMLRecursive; }