Merge pull request #19314 from mattwire/importnoignoreexception
[civicrm-core.git] / CRM / Utils / XML.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | Copyright CiviCRM LLC. All rights reserved. |
5 | |
6 | This work is published under the GNU AGPLv3 license with some |
7 | permitted exceptions and without any warranty. For full license |
8 | and copyright information, see https://civicrm.org/licensing |
9 +--------------------------------------------------------------------+
10 */
11
12 /**
13 * @package CRM
14 * @copyright CiviCRM LLC https://civicrm.org/licensing
15 */
16 class CRM_Utils_XML {
17
18 /**
19 * Read a well-formed XML file
20 *
21 * @param $file
22 *
23 * @return array
24 * (0 => SimpleXMLElement|FALSE, 1 => errorMessage|FALSE)
25 */
26 public static function parseFile($file) {
27 // SimpleXMLElement
28 $xml = FALSE;
29 // string
30 $error = FALSE;
31
32 if (!file_exists($file)) {
33 $error = 'File ' . $file . ' does not exist.';
34 }
35 else {
36 $oldLibXMLErrors = libxml_use_internal_errors();
37 libxml_use_internal_errors(TRUE);
38
39 // Note that under obscure circumstances calling simplexml_load_file
40 // hit https://bugs.php.net/bug.php?id=62577
41 $string = file_get_contents($file);
42 $xml = simplexml_load_string($string, 'SimpleXMLElement', LIBXML_NOCDATA);
43 if ($xml === FALSE) {
44 $error = self::formatErrors(libxml_get_errors());
45 }
46
47 libxml_use_internal_errors($oldLibXMLErrors);
48 }
49
50 return [$xml, $error];
51 }
52
53 /**
54 * Read a well-formed XML file
55 *
56 * @param $string
57 *
58 * @return array
59 * (0 => SimpleXMLElement|FALSE, 1 => errorMessage|FALSE)
60 */
61 public static function parseString($string) {
62 // SimpleXMLElement
63 $xml = FALSE;
64 // string
65 $error = FALSE;
66
67 $oldLibXMLErrors = libxml_use_internal_errors();
68 libxml_use_internal_errors(TRUE);
69
70 $xml = simplexml_load_string($string,
71 'SimpleXMLElement', LIBXML_NOCDATA
72 );
73 if ($xml === FALSE) {
74 $error = self::formatErrors(libxml_get_errors());
75 }
76
77 libxml_use_internal_errors($oldLibXMLErrors);
78
79 return [$xml, $error];
80 }
81
82 /**
83 * @param $errors
84 *
85 * @return string
86 */
87 protected static function formatErrors($errors) {
88 $messages = [];
89
90 foreach ($errors as $error) {
91 if ($error->level != LIBXML_ERR_ERROR && $error->level != LIBXML_ERR_FATAL) {
92 continue;
93 }
94
95 $parts = [];
96 if ($error->file) {
97 $parts[] = "File=$error->file";
98 }
99 $parts[] = "Line=$error->line";
100 $parts[] = "Column=$error->column";
101 $parts[] = "Code=$error->code";
102
103 $messages[] = implode(" ", $parts) . ": " . trim($error->message);
104 }
105
106 return implode("\n", $messages);
107 }
108
109 /**
110 * Convert an XML element to an array.
111 *
112 * @param $obj
113 * SimpleXMLElement.
114 *
115 * @return array
116 */
117 public static function xmlObjToArray($obj) {
118 $arr = [];
119 if (is_object($obj)) {
120 $obj = get_object_vars($obj);
121 }
122 if (is_array($obj)) {
123 foreach ($obj as $i => $v) {
124 if (is_object($v) || is_array($v)) {
125 $v = self::xmlObjToArray($v);
126 }
127 if (empty($v)) {
128 $arr[$i] = NULL;
129 }
130 else {
131 $arr[$i] = $v;
132 }
133 }
134 }
135 return $arr;
136 }
137
138 }