php XML to Array Simplest way.

Strongly recommended book
Hi Guys,

I thought I should share this with you.

There are many times when you wish to convert your XML to a PHP Array.

Two things you should know

  1. There is no inbuilt PHP function to address this problem
  2. There are many ways to address this problem
I’ve highlighted couple of solutions which I think works and are really simple to understand.

Well lets get started.

Say you have an XML such as one below

 

  1. $xml= '<persons>
  2. <person>
  3. <name>Jaspreet Chahal</name>
  4. <age>33</age>
  5. <city>Melbourne</city>
  6. </person>
  7. <person>
  8. <name>Yuvraaj Chahal</name>
  9. <age>2</age>
  10. <city>Adelaide</city>
  11. </person>
  12. </persons>';

Now do this

  1. $xmlObj = simplexml_load_string($xml);
  2. $json = json_encode($xmlObj);
  3. $arr= json_decode($json);

Now just print that array as

  1. print_r($arr);

You will get result similar to this

  1. stdClass Object
  2. (
  3. [person] => Array
  4. (
  5. [0] => stdClass Object
  6. (
  7. [name] => Jaspreet Chahal
  8. [age] => 33
  9. [city] => Melbourne
  10. )
  11.  
  12. [1] => stdClass Object
  13. (
  14. [name] => Yuvraaj Chahal
  15. [age] => 2
  16. [city] => Adelaide
  17. )
  18.  
  19. )
  20.  
  21. )

Said that this is not a full or optimal solution because this method does not handle Element Attributes well. More interesting and good approach will be the one shown below. Please note: The Code below is taken from PHP.net. I did not write this code. I’ve changed it a bit to accept XML as string rather than reading from file.

  1. function xml2array($contents, $get_attributes = 1, $priority = 'tag')
  2. {
  3. if (!function_exists('xml_parser_create'))
  4. {
  5. return array ();
  6. }
  7. $parser = xml_parser_create();
  8. xml_parser_set_option($parser, XML_OPTION_TARGET_ENCODING, "UTF-8");
  9. xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
  10. xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
  11. xml_parse_into_struct($parser, trim($contents), $xml_values);
  12. xml_parser_free($parser);
  13. if (!$xml_values)
  14. return;
  15. $xml_array = array ();
  16. $parents = array ();
  17. $opened_tags = array ();
  18. $arr = array ();
  19. $current = & $xml_array;
  20. $repeated_tag_index = array ();
  21. foreach ($xml_values as $data)
  22. {
  23. unset ($attributes, $value);
  24. extract($data);
  25. $result = array ();
  26. $attributes_data = array ();
  27. if (isset ($value))
  28. {
  29. if ($priority == 'tag')
  30. $result = $value;
  31. else
  32. $result['value'] = $value;
  33. }
  34. if (isset ($attributes) and $get_attributes)
  35. {
  36. foreach ($attributes as $attr => $val)
  37. {
  38. if ($priority == 'tag')
  39. $attributes_data[$attr] = $val;
  40. else
  41. $result['attr'][$attr] = $val; //Set all the attributes in a array called 'attr'
  42. }
  43. }
  44. if ($type == "open")
  45. {
  46. $parent[$level -1] = & $current;
  47. if (!is_array($current) or (!in_array($tag, array_keys($current))))
  48. {
  49. $current[$tag] = $result;
  50. if ($attributes_data)
  51. $current[$tag . '_attr'] = $attributes_data;
  52. $repeated_tag_index[$tag . '_' . $level] = 1;
  53. $current = & $current[$tag];
  54. }
  55. else
  56. {
  57. if (isset ($current[$tag][0]))
  58. {
  59. $current[$tag][$repeated_tag_index[$tag . '_' . $level]] = $result;
  60. $repeated_tag_index[$tag . '_' . $level]++;
  61. }
  62. else
  63. {
  64. $current[$tag] = array (
  65. $current[$tag],
  66. $result
  67. );
  68. $repeated_tag_index[$tag . '_' . $level] = 2;
  69. if (isset ($current[$tag . '_attr']))
  70. {
  71. $current[$tag]['0_attr'] = $current[$tag . '_attr'];
  72. unset ($current[$tag . '_attr']);
  73. }
  74. }
  75. $last_item_index = $repeated_tag_index[$tag . '_' . $level] - 1;
  76. $current = & $current[$tag][$last_item_index];
  77. }
  78. }
  79. elseif ($type == "complete")
  80. {
  81. if (!isset ($current[$tag]))
  82. {
  83. $current[$tag] = $result;
  84. $repeated_tag_index[$tag . '_' . $level] = 1;
  85. if ($priority == 'tag' and $attributes_data)
  86. $current[$tag . '_attr'] = $attributes_data;
  87. }
  88. else
  89. {
  90. if (isset ($current[$tag][0]) and is_array($current[$tag]))
  91. {
  92. $current[$tag][$repeated_tag_index[$tag . '_' . $level]] = $result;
  93. if ($priority == 'tag' and $get_attributes and $attributes_data)
  94. {
  95. $current[$tag][$repeated_tag_index[$tag . '_' . $level] . '_attr'] = $attributes_data;
  96. }
  97. $repeated_tag_index[$tag . '_' . $level]++;
  98. }
  99. else
  100. {
  101. $current[$tag] = array (
  102. $current[$tag],
  103. $result
  104. );
  105. $repeated_tag_index[$tag . '_' . $level] = 1;
  106. if ($priority == 'tag' and $get_attributes)
  107. {
  108. if (isset ($current[$tag . '_attr']))
  109. {
  110. $current[$tag]['0_attr'] = $current[$tag . '_attr'];
  111. unset ($current[$tag . '_attr']);
  112. }
  113. if ($attributes_data)
  114. {
  115. $current[$tag][$repeated_tag_index[$tag . '_' . $level] . '_attr'] = $attributes_data;
  116. }
  117. }
  118. $repeated_tag_index[$tag . '_' . $level]++; //0 and 1 index is already taken
  119. }
  120. }
  121. }
  122. elseif ($type == 'close')
  123. {
  124. $current = & $parent[$level -1];
  125. }
  126. }
  127. return ($xml_array);
  128. }

So now lets change the above XML to look like this

  1. $xml= '<persons>
  2. <person n="2">
  3. <name>Jaspreet Chahal</name>
  4. <age id="1">33</age>
  5. <city>Melbourne</city>
  6. </person>
  7. <person>
  8. <name>Yuvraaj Chahal</name>
  9. <age>2</age>
  10. <city>Adelaide</city>
  11. </person>
  12. </persons>';

and then pass the above XML to xml2array() shown below

  1. print_r(xml2array($xml));
  The output will look like this
  1. (
  2. [persons] => Array
  3. (
  4. [person] => Array
  5. (
  6. [0] => Array
  7. (
  8. [name] => Jaspreet Chahal
  9. [age] => 33
  10. [age_attr] => Array
  11. (
  12. [id] => 1
  13. )
  14.  
  15. [city] => Melbourne
  16. )
  17.  
  18. [1] => Array
  19. (
  20. [name] => Yuvraaj Chahal
  21. [age] => 2
  22. [city] => Adelaide
  23. )
  24.  
  25. [0_attr] => Array
  26. (
  27. [n] => 2
  28. )
  29.  
  30. )
  31.  
  32. )
  33.  
  34. )

 

I hope this helps because it helped me immensely.

Cheers

VN:F [1.9.22_1171]
Rating: 0.0/5 (0 votes cast)
VN:F [1.9.22_1171]
Rating: +1 (from 1 vote)

Comments

  1. James Murray says:

    You’re still setting $contents to an empty value at the beginning of the function

    remove the $contents = “”;

  2. James Murray says:

    I just wanted to point out that your modifications to the xml2array function is busted.

    It’s impossible that your modified code will work. Upon running the function, you immediately empty the $contents variable (so the XML to parse is now completely gone) and you never actually create the parser.

    Currently your code has the following:
    $contents = “”;
    if (!function_exists(‘xml_parser_create’))
    {
    return array ();
    }
    xml_parser_set_option($parser, XML_OPTION_TARGET_ENCODING, “UTF-8″);

    What you need is this:
    if (!function_exists(‘xml_parser_create’))
    {
    return array ();
    }
    $parser = xml_parser_create();
    xml_parser_set_option($parser, XML_OPTION_TARGET_ENCODING, “UTF-8″);

    • Thanks James,
      What I was using was a little bit different to what I posted. So thanks for revising it.
      I have made the modifications and I think it should work fine.
      The code was taken from PHP.net and I think I should just have copy pasted the code I am using in my project here :)
      Thanks once again.
      Cheers.

Speak Your Mind

*

CommentLuv badge