1+ <?php
2+
3+ namespace darkfriend \helpers ;
4+
5+ /**
6+ * Class Xml
7+ * @package darkfriend\helpers
8+ * @author darkfriend <hi@darkfriend.ru>
9+ * @version 1.0.0
10+ */
11+ class Xml
12+ {
13+ protected static $ root = '<root/> ' ;
14+
15+ /**
16+ * Convert array to xml
17+ * @param mixed $data
18+ * @param array $params = [
19+ * 'root' => '<root/>',
20+ * 'exception' => false,
21+ * ]
22+ * @return string
23+ * @throws XmlException
24+ */
25+ public static function encode ($ data , $ params = array ())
26+ {
27+ \libxml_use_internal_errors (true );
28+
29+ if (empty ($ params ['root ' ])) {
30+ $ params ['root ' ] = self ::$ root ;
31+ }
32+
33+ $ xml = new SimpleXMLElement ($ params ['root ' ]);
34+ $ xml = self ::generateXml ($ xml , $ data );
35+
36+ if (!static ::checkException ($ params )) {
37+ return '' ;
38+ }
39+
40+ return $ xml ->asXML ();
41+ }
42+
43+ /**
44+ * @param SimpleXMLElement $xml
45+ * @param mixed $data
46+ * @return SimpleXMLElement
47+ */
48+ public static function generateXml ($ xml , $ data )
49+ {
50+ /** @var $xml SimpleXMLElement */
51+ if (is_array ($ data )) {
52+ foreach ($ data as $ key =>$ item ) {
53+ self ::addChild ($ xml ,$ key ,$ item );
54+ }
55+ } else {
56+ self ::addChild ($ xml ,$ data );
57+ }
58+ return $ xml ;
59+ }
60+
61+ /**
62+ * Add child
63+ * @param SimpleXMLElement $xml
64+ * @param string $name
65+ * @param array|string $params
66+ * @return SimpleXMLElement
67+ */
68+ public static function addChild ($ xml , $ name , $ params = '' )
69+ {
70+ if (is_array ($ params )) {
71+ $ value = null ;
72+ if (key_exists ('@value ' ,$ params )) {
73+ $ value = $ params ['@value ' ];
74+ unset($ params ['@value ' ]);
75+ }
76+
77+ $ namespace = null ;
78+ if (key_exists ('@namespace ' ,$ params )) {
79+ $ namespace = $ params ['@namespace ' ];
80+ unset($ params ['@namespace ' ]);
81+ }
82+
83+ $ child = $ xml ->addChild ($ name ,$ value , $ namespace );
84+
85+ if (key_exists ('@attributes ' ,$ params )) {
86+ foreach ($ params ['@attributes ' ] as $ keyAttr =>$ attr ) {
87+ $ child ->addAttribute ($ keyAttr , $ attr );
88+ }
89+ unset($ params ['@attributes ' ]);
90+ }
91+
92+ if (key_exists ('@cdata ' ,$ params )) {
93+ $ child ->addCData ($ params ['@cdata ' ]);
94+ unset($ params ['@cdata ' ]);
95+ }
96+
97+ foreach ($ params as $ key => $ item ) {
98+ if (is_array ($ item )) {
99+ self ::addChild ($ child ,$ key ,$ item );
100+ } else {
101+ $ child ->addChild ($ key ,$ item );
102+ }
103+ }
104+ } else {
105+ $ child = $ xml ->addChild ($ name , $ params );
106+ }
107+
108+ return $ child ;
109+ }
110+
111+ /**
112+ * Decode XML string
113+ * @param string $data
114+ * @param array $params = [
115+ * 'convert' => true,
116+ * 'exception' => false,
117+ * ]
118+ * @return \darkfriend\helpers\SimpleXMLElement|array
119+ * @throws XmlException
120+ */
121+ public static function decode ($ data , $ params = array ())
122+ {
123+ \libxml_use_internal_errors (true );
124+
125+ $ xml = \simplexml_load_string (
126+ $ data ,
127+ '\darkfriend\helpers\SimpleXMLElement ' ,
128+ \LIBXML_NOCDATA
129+ );
130+
131+ if (!static ::checkException ($ params )) {
132+ return array ();
133+ }
134+
135+ if (!isset ($ params ['convert ' ])) {
136+ $ params ['convert ' ] = true ;
137+ }
138+
139+ if ($ params ['convert ' ]) {
140+ return self ::convertSimpleXml ($ xml );
141+ } else {
142+ return $ xml ;
143+ }
144+ }
145+
146+ /**
147+ * Convert tree SimpleXMLElement
148+ * @param SimpleXMLElement $xml
149+ * @return array
150+ */
151+ public static function convertSimpleXml ($ xml )
152+ {
153+ $ res = array ();
154+ /** @var SimpleXMLElement $item */
155+ foreach ($ xml as $ key =>$ item ) {
156+ if ($ item ->count ()>0 ) {
157+ $ res [$ key ] = self ::convertSimpleXml ($ item );
158+ } else {
159+ $ res [$ key ] = self ::convertSimpleXmlItem ($ item );
160+ }
161+ }
162+ return $ res ;
163+ }
164+
165+ /**
166+ * Convert item SimpleXMLElement
167+ * @param SimpleXMLElement $item
168+ * @return array|string
169+ */
170+ public static function convertSimpleXmlItem ($ item )
171+ {
172+ /** @var SimpleXMLElement $item */
173+ $ attr = $ item ->attributes ();
174+ if (!empty ($ attr )) {
175+ $ element = (array ) $ attr ;
176+ $ element ['@value ' ] = (string ) $ item ;
177+ } else {
178+ $ element = (string ) $ item ;
179+ }
180+ return $ element ;
181+ }
182+
183+ /**
184+ * Check error
185+ * @param array $params = [
186+ * 'exception' => true,
187+ * ]
188+ * @return bool if $params['exception'] === false
189+ * @throws XmlException if $params['exception'] === true
190+ */
191+ public static function checkException ($ params = array ())
192+ {
193+ $ e = \libxml_get_errors ();
194+
195+ if (!$ e ) {
196+ return true ;
197+ }
198+
199+ $ strError = '' ;
200+ foreach ($ e as $ key => $ xmlError ) {
201+ $ strError .= "$ key: " .$ xmlError ->message . "\n" ;
202+ }
203+
204+ if ($ params ['exception ' ]) {
205+ throw new XmlException ("XML error: $ strError " , 100 , __FILE__ , __LINE__ );
206+ }
207+
208+ return true ;
209+ }
210+
211+ /**
212+ * Set root element
213+ * @param string $root
214+ */
215+ public static function setRootElement ($ root = '<root/> ' )
216+ {
217+ self ::$ root = $ root ;
218+ }
219+
220+ /**
221+ * Get root element
222+ * @return string
223+ */
224+ public static function getRootElement ()
225+ {
226+ return self ::$ root ;
227+ }
228+ }
0 commit comments