XML and JSON do not map onto each other, so every converter picks a convention, and this one follows xmltodict’s, the most widely used. The root element is the single top-level key, an attribute becomes a key with @ in front (@id), an element’s text becomes a string, and when the element also has attributes or children its text goes under #text; the other common shape, attributes grouped under _attributes and text under _text, is one switch away. An element that appears more than once becomes an array, which is where most bugs come from: a feed with two <item> elements gives an array, the same feed with one gives an object, and code that loops over it breaks on the day there is only one. Always arrays takes a list of element names that are arrays however many there are, and the result names every element that became an array, so you know which to list. Empty elements become null, namespace prefixes stay part of the name, as in soap:Envelope, and xmlns declarations are kept as attributes unless you drop them.
Some of XML has no JSON form. Comments and processing instructions are dropped and counted. In mixed content, text sitting between child elements as in HTML-like markup, the text is joined into #text and its position among the elements is lost, and a warning names the element; the order of a repeated element interleaved with others is lost the same way. Every value is a string, because XML has no types. Convert numbers and booleans changes only text that prints back unchanged, so 42 and true convert while 007, 1e5 and 1.50 stay strings, as zip codes and version numbers must. Text is trimmed unless you turn that off, CDATA becomes ordinary text, the five predefined entities and numeric character references are decoded, and line ends and whitespace in attribute values are normalised as XML 1.0 requires.
The parser is strict where lenient ones guess: a bare & in a URL, an HTML entity such as , an attribute with no value or no quotes, a second root element and a mismatched closing tag are each an error with a line and column. A DOCTYPE is skipped, and one that declares entities is refused, because <!ENTITY> is how XML external entity (XXE) attacks read files and how a billion-laughs document grows to gigabytes; nothing here runs on a server, but no data needs them. From JSON to XML, the key of a one-key object becomes the root element and anything else is wrapped in a root you name; @ keys become attributes, arrays become repeated elements, & < and > are escaped, keys that are not XML names are renamed with a warning, and numbers are copied exactly as written.