function smd_xml($atts, $thing=NULL) { extract(lAtts(array( 'data' => '', 'record' => '', 'fields' => '', 'skip' => '', 'uppercase' => '0', 'convert' => '', // search:replace, search:replace, ... 'target_enc' => 'UTF-8', 'form' => '', 'wraptag' => '', 'break' => '', 'class' => '', 'delim' => ',', 'param_delim' => ':', 'concat_delim' => ' ', 'concat' => '1', 'debug' => '0', ), $atts)); $src = ''; $thing = (empty($form)) ? $thing : fetch_form($form); if (empty($data)) { trigger_error("smd_xml requires a data source"); } if (empty($record)) { trigger_error("smd_xml requires a record name within your data stream"); } if (empty($fields)) { trigger_error("smd_xml requires a list of fields to extract from within your records"); } $target_enc = (in_array($target_enc, array('ISO-8859-1', 'US-ASCII', 'UTF-8'))) ? $target_enc : 'UTF-8'; if ((strpos($data, 'http:') === 0) || (strpos($data, 'https:') === 0)) { // The data is to be fetched from a URL if( is_callable('fsockopen') ) $transport = 'fsock'; elseif( is_callable('curl_init') ) { $transport = 'curl'; } else { $transport = ''; } switch ($transport) { case 'curl': $c = curl_init(); curl_setopt($c, CURLOPT_URL, $data); curl_setopt($c, CURLOPT_REFERER, hu); curl_setopt($c, CURLOPT_RETURNTRANSFER, true); curl_setopt($c, CURLOPT_VERBOSE, false); curl_setopt($c, CURLOPT_TIMEOUT, 10); $src = curl_exec($c); break; case 'fsock': $url = parse_url($data); $fp = fsockopen ($url['host'], 80, $errno, $errstr, 10); $qry = 'GET '.$url['path']; $qry .= " HTTP/1.0\r\n"; $qry .= "Host: ".$url['host']."\r\n"; $qry .= "User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6\r\n\r\n"; // *shrug* fputs($fp, $qry); stream_set_timeout($fp, 10); $info = stream_get_meta_data($fp); $hdrs = true; while ((!feof($fp)) && (!$info['timed_out'])) { $line = fgets($fp, 8192); $line = preg_replace("[\r\n]", "", $line); if ($hdrs == false) { $src .= $line."\n"; } if (strlen($line) == 0) $hdrs = false; } if ($info['timed_out']) { $src = ''; } fclose($fp); break; default: $src = ''; } } else { // Assume data is presented in raw XML $src = $data; } // Make up a replacement array for decoded entities... $conversions = array(); $convert = do_list($convert, $delim); foreach ($convert as $pair) { if (empty($pair)) continue; $pair = do_list($pair, $param_delim); $conversions[$pair[0]] = $pair[1]; } if ($debug > 1) { echo "++ CONVERSIONS ++"; dmp($conversions); } // ... and replace them $src = strtr($src, $conversions); if ($debug > 2) { echo "++ FILTERED SOURCE DATA ++"; dmp($src); } if (!empty($src)) { $ref = new smd_xml_parser($src, $fields, $record, $skip, $uppercase, $target_enc, $thing, $delim, $param_delim, $concat, $concat_delim, $debug); $result = $ref->getResults(); return doWrap($result, $wraptag, $break, $class); } else { return ''; } } class smd_xml_parser { private $data; private $fields; private $rec; private $skip; private $cf; private $outenc; private $intag; private $indata; private $skiptag; private $xmltag; private $xmlatts; private $xmldata; private $thing; private $out; private $pdelim; private $cdelim; private $concat; private $debug; /** * constructor */ function smd_xml_parser($data, $fields, $rec, $skip, $cf, $outenc, $thing, $delim, $pdelim, $concat, $cdelim, $debug=0) { $this->data = $data; $this->fields = do_list($fields, $delim); $this->skip = do_list($skip, $delim); $this->rec = $rec; $this->cf = $cf; // Case folding $this->outenc = $outenc; // Target encoding $this->thing = $thing; $this->pdelim = $pdelim; $this->cdelim = $cdelim; $this->concat = $concat; $this->debug = $debug; $this->intag = false; $this->exists = false; $this->skiptag = ''; $this->xmltag = ''; $this->xmltatts = ''; $this->xmldata = array(); $this->out = array(); $this->parse(); } public function getResults() { if ($this->out) { return $this->out; } else { return ''; } } private function parse() { $this->data = preg_replace("/>"."[[:space:]]+"."<", $this->data); // Kill whitespace in data $xmlparser = xml_parser_create(); xml_set_object($xmlparser, &$this); xml_parser_set_option($xmlparser, XML_OPTION_CASE_FOLDING, $this->cf); xml_parser_set_option($xmlparser, XML_OPTION_TARGET_ENCODING, $this->outenc); xml_set_element_handler($xmlparser, "smd_xml_start_tag", "smd_xml_end_tag"); xml_set_character_data_handler($xmlparser, "smd_xml_tag_contents"); xml_parse($xmlparser, $this->data); xml_parser_free($xmlparser); } private function smd_xml_start_tag($parser, $name, $attribs) { if ($name == $this->rec) { $this->intag = true; } if ($this->intag) { if (in_array($name, $this->skip)) { $this->xmltag = ''; $this->xmlatts = array(); $this->skiptag = $name; } else { $this->xmltag = $name; $this->xmlatts = $attribs; if ($this->concat && isset($this->xmldata['{'.$this->xmltag.'}'])) { $this->exists = true; } else { $this->exists = false; } } } $this->indata = false; } private function smd_xml_end_tag($parser, $name) { if ($name == $this->rec && $name != $this->skiptag) { $this->intag = false; if ($this->debug > 0) { echo "++ REPLACEMENTS ++"; dmp($this->xmldata); } $this->out[] = parse(strtr($this->thing, $this->xmldata)); $this->xmldata = array(); // Clear for next iteration $this->indata = false; } if ($name == $this->skiptag) { $this->skiptag = ''; } } private function smd_xml_tag_contents($parser, $data) { if ($this->intag && !$this->skiptag) { if ($this->debug > 1) { dmp($this->xmltag . " : ". $data); } if (in_array($this->xmltag, $this->fields)) { if ($this->indata) { if ($this->exists) { $this->xmldata['{'.$this->xmltag.'}'] .= $this->cdelim.$data; } else { $this->xmldata['{'.$this->xmltag.'}'] .= $data; } } else { if ($this->exists) { $this->xmldata['{'.$this->xmltag.'}'] .= $this->cdelim.$data; } else { $this->xmldata['{'.$this->xmltag.'}'] = $data; } } if ($this->xmlatts) { foreach ($this->xmlatts as $xkey => $xval) { $this->xmldata['{'.$this->xmltag.$this->pdelim.$xkey.'}'] = $xval; } } $this->indata = true; } } } }