PHP convert XML to JSON

前端 未结 20 1460
生来不讨喜
生来不讨喜 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:06

    This is an improvement of the most upvoted solution by Antonio Max, which also works with XML that has namespaces (by replacing the colon with an underscore). It also has some extra options (and does parse <person my-attribute='name'>John</person> correctly).

    function parse_xml_into_array($xml_string, $options = array()) {
        /*
        DESCRIPTION:
        - parse an XML string into an array
        INPUT:
        - $xml_string
        - $options : associative array with any of these keys:
            - 'flatten_cdata' : set to true to flatten CDATA elements
            - 'use_objects' : set to true to parse into objects instead of associative arrays
            - 'convert_booleans' : set to true to cast string values 'true' and 'false' into booleans
        OUTPUT:
        - associative array
        */
    
        // Remove namespaces by replacing ":" with "_"
        if (preg_match_all("|</([\\w\\-]+):([\\w\\-]+)>|", $xml_string, $matches, PREG_SET_ORDER)) {
            foreach ($matches as $match) {
                $xml_string = str_replace('<'. $match[1] .':'. $match[2], '<'. $match[1] .'_'. $match[2], $xml_string);
                $xml_string = str_replace('</'. $match[1] .':'. $match[2], '</'. $match[1] .'_'. $match[2], $xml_string);
            }
        }
    
        $output = json_decode(json_encode(@simplexml_load_string($xml_string, 'SimpleXMLElement', ($options['flatten_cdata'] ? LIBXML_NOCDATA : 0))), ($options['use_objects'] ? false : true));
    
        // Cast string values "true" and "false" to booleans
        if ($options['convert_booleans']) {
            $bool = function(&$item, $key) {
                if (in_array($item, array('true', 'TRUE', 'True'), true)) {
                    $item = true;
                } elseif (in_array($item, array('false', 'FALSE', 'False'), true)) {
                    $item = false;
                }
            };
            array_walk_recursive($output, $bool);
        }
    
        return $output;
    }
    
    0 讨论(0)
  • 2020-11-22 07:08

    Try to use this

    $xml = ... // Xml file data
    
    // first approach
    $Json = json_encode(simplexml_load_string($xml));
    
    ---------------- OR -----------------------
    
    // second approach
    $Json = json_encode(simplexml_load_string($xml, "SimpleXMLElement", LIBXML_NOCDATA));
    
    echo $Json;
    

    Or

    You can use this library : https://github.com/rentpost/xml2array

    0 讨论(0)
  • 2020-11-22 07:08

    If you would like to only convert a specific part of the XML to JSON, you can use XPath to retrieve this and convert that to JSON.

    <?php
    $file = @file_get_contents($xml_File, FILE_TEXT);
    $xml = new SimpleXMLElement($file);
    $xml_Excerpt = @$xml->xpath('/states/state[@id="AL"]')[0]; // [0] gets the node
    echo json_encode($xml_Excerpt);
    ?>
    

    Please note that if you Xpath is incorrect, this will die with an error. So if you're debugging this through AJAX calls I recommend you log the response bodies as well.

    0 讨论(0)
  • 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().

    /**
     * <root><a>5</a><b>6</b><b>8</b></root> -> {"root":[{"a":["5"],"b":["6","8"]}]}
     * <root a="5"><b>6</b><b>8</b></root> -> {"root":[{"a":"5","b":["6","8"]}]}
     * <root xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"><a>123</a><wsp:b>456</wsp:b></root> 
     *   -> {"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('<root a="5"><b>6</b></root>')));
    {"root":[{"a":"5","b":["6"]}]}
    
    0 讨论(0)
  • 2020-11-22 07:12

    Json & Array from XML in 3 lines:

    $xml = simplexml_load_string($xml_string);
    $json = json_encode($xml);
    $array = json_decode($json,TRUE);
    
    0 讨论(0)
  • 2020-11-22 07:12

    If you are ubuntu user install xml reader (i have php 5.6. if you have other please find package and install)

    sudo apt-get install php5.6-xml
    service apache2 restart
    
    $fileContents = file_get_contents('myDirPath/filename.xml');
    $fileContents = str_replace(array("\n", "\r", "\t"), '', $fileContents);
    $fileContents = trim(str_replace('"', "'", $fileContents));
    $oldXml = $fileContents;
    $simpleXml = simplexml_load_string($fileContents);
    $json = json_encode($simpleXml);
    
    0 讨论(0)
提交回复
热议问题