Q:

Is it possible to load XML document with DOMElements case-folded?

I'm loading an XML document with DOMDocument's loadXML function. There doesn't appear to be any options to case fold DOMElement's tagName and attribute names.
I need to treat the XML document as being case-insensitive so this should be considered invalid (name and NAME should be the same, not unique):
<input name="field" NAME="field2" />

Likewise the getAttribute/setAttribute functions should treat "NAME" AND "name" as the same attribute.
The xml parser functions appear to have this functionality through the xml_parser_set_option function through the "XML_OPTION_CASE_FOLDING" constant. But DOMDocument and these functions appear to be mutually exclusive, with the only similarity being they both use libxml2 behind the scenes.
So is there any way to force DOMDocument to case-fold? Are there any drop in replacements that use the xml parser functions? I'm looking to avoid using anything that uses regular expressions. The appeal of DOMDocument is the object vs procedural design.
Normally the XML document nodes should be lowercase anyway. But I'd like my code to still work if someone capitalizes something and transform it to lowercase after parsing the document.

A:

I don't think there is a specific function to ignore case (or de-dupe attributes) in the DomDocument class, but you could just lower the case of the relevant XML parts before you load it in to get some of the way there?
function xml_case_fold($string)
{
    $string = preg_replace_callback('#(</?[^!><= ]+)([^><]*>)|(<!\[CDATA\[)(.*\]\]>)#si',
        function($tag)
        {
            if($tag[1])
            {
                $tag[2] = preg_replace_callback('#([^><= ]+)(=(["\']).*?\3)#s',
                        function($attr)
                        {
                            return strtolower($attr[1]) . $attr[2];
                        }, $tag[2]);

                return strtolower($tag[1]) . $tag[2];
            }
            else
            {
                return $tag[0];
            }
        }, $string);

    return $string;
}

