PHP convert XML to JSON

前端 未结 20 1820
生来不讨喜
生来不讨喜 2020-11-22 06:25

I am trying to convert xml to json in php. If I do a simple convert using simple xml and json_encode none of the attributes in the xml show.

$xml = simplexml         


        
20条回答
  •  暗喜
    暗喜 (楼主)
    2020-11-22 07:08

    This solution handles namespaces, attributes, and produces consistent result with repeating elements (always in array, even if there is only one occurrence). Inspired by ratfactor's sxiToArray().

    /**
     * 568 -> {"root":[{"a":["5"],"b":["6","8"]}]}
     * 68 -> {"root":[{"a":"5","b":["6","8"]}]}
     * 123456 
     *   -> {"root":[{"xmlns:wsp":"http://schemas.xmlsoap.org/ws/2004/09/policy","a":["123"],"wsp:b":["456"]}]}
     */
    function domNodesToArray(array $tags, \DOMXPath $xpath)
    {
        $tagNameToArr = [];
        foreach ($tags as $tag) {
            $tagData = [];
            $attrs = $tag->attributes ? iterator_to_array($tag->attributes) : [];
            $subTags = $tag->childNodes ? iterator_to_array($tag->childNodes) : [];
            foreach ($xpath->query('namespace::*', $tag) as $nsNode) {
                // the only way to get xmlns:*, see https://stackoverflow.com/a/2470433/2750743
                if ($tag->hasAttribute($nsNode->nodeName)) {
                    $attrs[] = $nsNode;
                }
            }
    
            foreach ($attrs as $attr) {
                $tagData[$attr->nodeName] = $attr->nodeValue;
            }
            if (count($subTags) === 1 && $subTags[0] instanceof \DOMText) {
                $text = $subTags[0]->nodeValue;
            } elseif (count($subTags) === 0) {
                $text = '';
            } else {
                // ignore whitespace (and any other text if any) between nodes
                $isNotDomText = function($node){return !($node instanceof \DOMText);};
                $realNodes = array_filter($subTags, $isNotDomText);
                $subTagNameToArr = domNodesToArray($realNodes, $xpath);
                $tagData = array_merge($tagData, $subTagNameToArr);
                $text = null;
            }
            if (!is_null($text)) {
                if ($attrs) {
                    if ($text) {
                        $tagData['_'] = $text;
                    }
                } else {
                    $tagData = $text;
                }
            }
            $keyName = $tag->nodeName;
            $tagNameToArr[$keyName][] = $tagData;
        }
        return $tagNameToArr;
    }
    
    function xmlToArr(string $xml)
    {
        $doc = new \DOMDocument();
        $doc->loadXML($xml);
        $xpath = new \DOMXPath($doc);
        $tags = $doc->childNodes ? iterator_to_array($doc->childNodes) : [];
        return domNodesToArray($tags, $xpath);
    }
    

    Example:

    php > print(json_encode(xmlToArr('6')));
    {"root":[{"a":"5","b":["6"]}]}
    

提交回复
热议问题