Merge pull request #15878 from civicrm/5.20
[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 $xml = simplexml_load_file($file,
40 'SimpleXMLElement', LIBXML_NOCDATA
41 );
42 if ($xml === FALSE) {
43 $error = self::formatErrors(libxml_get_errors());
44 }
45
46 libxml_use_internal_errors($oldLibXMLErrors);
47 }
48
49 return [$xml, $error];
50 }
51
52 /**
53 * Read a well-formed XML file
54 *
55 * @param $string
56 *
57 * @return array
58 * (0 => SimpleXMLElement|FALSE, 1 => errorMessage|FALSE)
59 */
60 public static function parseString($string) {
61 // SimpleXMLElement
62 $xml = FALSE;
63 // string
64 $error = FALSE;
65
66 $oldLibXMLErrors = libxml_use_internal_errors();
67 libxml_use_internal_errors(TRUE);
68
69 $xml = simplexml_load_string($string,
70 'SimpleXMLElement', LIBXML_NOCDATA
71 );
72 if ($xml === FALSE) {
73 $error = self::formatErrors(libxml_get_errors());
74 }
75
76 libxml_use_internal_errors($oldLibXMLErrors);
77
78 return [$xml, $error];
79 }
80
81 /**
82 * @param $errors
83 *
84 * @return string
85 */
86 protected static function formatErrors($errors) {
87 $messages = [];
88
89 foreach ($errors as $error) {
90 if ($error->level != LIBXML_ERR_ERROR && $error->level != LIBXML_ERR_FATAL) {
91 continue;
92 }
93
94 $parts = [];
95 if ($error->file) {
96 $parts[] = "File=$error->file";
97 }
98 $parts[] = "Line=$error->line";
99 $parts[] = "Column=$error->column";
100 $parts[] = "Code=$error->code";
101
102 $messages[] = implode(" ", $parts) . ": " . trim($error->message);
103 }
104
105 return implode("\n", $messages);
106 }
107
108 /**
109 * Convert an XML element to an array.
110 *
111 * @param $obj
112 * SimpleXMLElement.
113 *
114 * @return array
115 */
116 public static function xmlObjToArray($obj) {
117 $arr = [];
118 if (is_object($obj)) {
119 $obj = get_object_vars($obj);
120 }
121 if (is_array($obj)) {
122 foreach ($obj as $i => $v) {
123 if (is_object($v) || is_array($v)) {
124 $v = self::xmlObjToArray($v);
125 }
126 if (empty($v)) {
127 $arr[$i] = NULL;
128 }
129 else {
130 $arr[$i] = $v;
131 }
132 }
133 }
134 return $arr;
135 }
136
137 }