-
Notifications
You must be signed in to change notification settings - Fork 15
/
Copy pathrea_xml.class.php
354 lines (298 loc) · 10.5 KB
/
rea_xml.class.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
<?php
/**
*
* Author: Ben Dougherty
* URL: http://www.devblog.com.au,
* http://www.mandurahweb.com.au
*
* This code was written for a project by mandurahweb.com. Please give credit if you
* use this code in any of your projects. You can see a write-up of this code been
* used to create posts in WordPress here: http://www.devblog.com.au/rea-xml-parser-and-wordpress
*
* This code is licensed under with the GPL and may be used and distributed freely.
* You may fork the code make changes add extra features etc.
*
* Any changes to this code should be released to the open source community.
*
*
* REA_XML allows you to easily retrieve an associative arary of properties
* indexed by propertyList. Properties types as specified in the REAXML documentation
* include:
* residential
* rental
* land
* rural
* commercial
* commercialLand
* business
*
* USAGE:
* $rea = new REA_XML($debug=true); //uses default fields
* $properties = $rea->parse_dir($xml_file_dir, $processed_dir, $failed_dir, $excluded_files=array());
*
* or $property = $rea->parse_file();
*
* For a full list of fields please see. http://reaxml.realestate.com.au/ and click 'Mandatory Fields'
*
*
*/
class REA_XML {
/* Default Fields we return. You can specify any
* fields int the REA XML standard
*/
private $fields = array (
'priceView',
'description',
'features' => array(
'bedrooms',
'bathrooms',
'garages',
'carports',
'airConditioning',
'pool',
'alarmSystem',
'otherFeatures',
),
'address' => array(
'streetNumber',
'street',
'suburb',
'state',
'postcode',
),
'images',
'status',
);
/* default files exluded when parsing a directory */
private $default_excluded_files = array(".", "..");
/* Keeps track of excluded files */
private $excluded_files;
function REA_XML($debug=false, $fields=array()) {
/* Use requested fields if set */
if(!empty($fields)) {
$this->fields = $fields;
}
$this->debug = $debug; /* Set debug flag */
}
/*
* xml_string $xml_string
*
* Returns an associative array of properties keyed by property type
* for the XML string. XML string must be valid.
*/
function parse_xml($xml_string) {
$properties = array();
$properties_array = array();
$xml = false;
try {
/* Create XML document. */
/* Some of the xml files I received were invalid. This could be due to a number
* of reasons. SimpleXMLElement still spits out some ugly errors even with the try
* catch so we supress them when not in debug mode
*/
if($this->debug) {
$xml = new SimpleXMLElement($xml_string);
}
else {
@$xml = new SimpleXMLElement($xml_string);
}
}
catch(Exception $e) {
$this->feedback($e->getMessage());
}
// Loaded the file
if($xml === false) {
return array();
}
// Get property type.
$all_properties = $xml->xpath("/propertyList/*");
if(is_array($all_properties) && count($all_properties) > 0) {
foreach ($all_properties as $property) {
$property_type = $property->getName();
$prop = array();//reset property
/* For every property we select all
* the requested fields
*/
foreach($this->fields as $key => $field) {
if(is_array($field)) {
foreach($field as $sub_field) {
$prop[$key][$sub_field] = trim((string)$property->{$key}->{$sub_field});
}
}
else {
// Different handling for multi fields.
if (isset($this->multi_fields[$field])) {
// Pull out the field key and attribute we want.
$field_key = $this->multi_fields[$field]['key'];
$field_attribute = $this->multi_fields[$field]['attribute'];
// Make sure the field exists.
if(!is_null($property->$field->$field_key)) {
// Get a value for every field.
foreach ($property->$field->$field_key as $f) {
$attr = $f->attributes();
if ($attr) {
$prop[$field][(string)$attr->$field_attribute] = (string)$f;
}
}
}
}
elseif($field == "objects" || $field == "images") {
// Parse all the floorplans.
if(!is_null($property->$field->floorplan)) {
foreach($property->$field->floorplan as $floorplan) {
$attr = $floorplan->attributes();
if($attr) {;
$prop['floorplan_'.(string)$attr->id] = (string)$attr->url;
}
}
}
if(!is_null($property->$field->img)) {
foreach($property->$field->img as $img) {
$attr = $img->attributes();
if($attr) {
$prop['img_' . (string)$attr->id] = (string)$attr->url;
}
}
}
}
else {
$prop[$field] = trim((string)$property->{$field});
}
}
}
if(in_array("status", $this->fields)) {
$attr = $property->attributes();
//save status
$prop['status'] = (string)$attr->status;
}
// Save the property
if(!empty($property_type)) {
$properties_array[$property_type][] = $prop;
}
else {
$properties_array['INVALID_PROPERTY_TYPE'][] = $prop;
}
}
}
return $properties_array;
}
/**
* string $xml_file_dir
* string $processed_dir
* string $failed_dir
* string[] $excluded_files
*
* Returns an associative array of properties keyed by property type
*/
function parse_directory($xml_file_dir, $processed_dir=false, $failed_dir=false, $excluded_files=array()) {
$properties = array();
if(file_exists($xml_file_dir)) {
if($handle = opendir($xml_file_dir)) {
/* Merged default excluded files with user specified files */
$this->excluded_files = array_merge($excluded_files, $this->default_excluded_files);
/* Loop through all the files. */
while(false !== ($xml_file = readdir($handle))) {
/* Ensure it's not exlcuded. */
if(!in_array($xml_file, $this->excluded_files)) {
/* Get the full path */
$xml_full_path = $xml_file_dir . "/" . $xml_file;
/* retrieve the properties from this file. */
$prop = $this->parse_file($xml_full_path, $xml_file, $processed_dir, $failed_dir);
if(is_array($prop) && count($prop) > 0) {
/* We have to get the array key which is the property
* type so we can do a merge with $property[$property_type]
* otherwise our properties get overwritten when we try to merge
* properties of the same type which already exist.
*/
$array_key = array_keys($prop);
$property_type = $array_key[0];
if(!isset($properties[$property_type])) {
//initialise
$properties[$property_type] = array();
}
/* We need the array prop because it includes the property type */
$properties[$property_type] = array_merge($prop[$property_type], $properties[$property_type]);
//file loaded
$file_loaded = true;
}
else {
$this->feedback("no properties returned from file");
}
}
}
closedir($handle);
}
else {
$this->feedback("Could not open directory");
}
}
else {
throw new Exception("Directory could not be found");
}
return $properties;
}
/* Parse a REA XML File. */
function parse_file($xml_full_path, $xml_file, $processed_dir=false, $failed_dir=false) {
$properties = array();
if(file_exists($xml_full_path)) {
$this->feedback("parsing XML file $xml_file");
/* Parse the XML file */
$properties = $this->parse_xml(file_get_contents($xml_full_path));
if(is_array($properties) && count($properties > 0)) {
/* If a processed/removed directory was supplied then we move
* the xml files accordingly after they've been processed
*/
if($processed_dir !== false) {
if(file_exists($processed_dir)) {
$this->xml_processed($xml_file, $xml_full_path, $processed_dir);
}
else {
$this->feedback("Processed dir: $processed_dir does not exist");
}
}
}
else {
if($failed_dir !== false) {
if(file_exists($failed_dir)) {
$this->xml_load_failed($xml_file, $xml_full_path, $failed_dir);
}
else {
$this->feedback("Failed dir: $failed_dir does not exist");
}
}
}
}
else {
throw new Exception("File could not be found");
}
return $properties;
}
/* Called if the xml file was processed */
function xml_processed($xml_file, $xml_full_path, $processed_dir) {
//do anything specific to xml_processed
//move file
$this->move_file($xml_file, $xml_full_path, $processed_dir);
}
/* Called if the xml file was not correctly processed */
private function xml_load_failed($xml_file, $xml_full_path, $failed_dir) {
//do anything specific to xml_failed
//move file
$this->move_file($xml_file, $xml_full_path, $failed_dir);
}
/* Moves a file to a new location */
private function move_file($file, $file_full_path, $new_dir) {
if(copy($file_full_path, $new_dir . "/$file")) {
unlink($file_full_path);
}
}
/* Reset excluded files */
public function reset_excluded_files() {
$this->excluded_files = $this->default_excluded_files;
}
/* Display Feedback if in debug mode */
private function feedback($string) {
if($this->debug) {
print $string . "<br/>";
}
}
}