/** * Submit REST Request * * @param string $method HTTP Method to use: GET or POST * @param array $params An array of parameters for the request * @param bool $process Should we convert the MARCXML? * * @return string|SimpleXMLElement The response from the XServer */ protected function call($method = 'GET', $params = null, $process = true) { if ($params) { $query = array('version=' . $this->sruVersion); foreach ($params as $function => $value) { if (is_array($value)) { foreach ($value as $additional) { $additional = urlencode($additional); $query[] = "{$function}={$additional}"; } } else { $value = urlencode($value); $query[] = "{$function}={$value}"; } } $queryString = implode('&', $query); } if ($this->debugNeeded()) { $this->debug('Connect: ' . print_r($this->host . '?' . $queryString, true)); } // Send Request $this->client->resetParameters(); $this->client->setUri($this->host . '?' . $queryString); $result = $this->client->setMethod($method)->send(); $this->checkForHttpError($result); // Return processed or unprocessed response, as appropriate: return $process ? $this->process($result->getBody()) : $result->getBody(); }
/** * Send an NCIP request. * * @param string $xml XML request document * * @return object SimpleXMLElement parsed from response */ protected function sendRequest($xml) { // Make the NCIP request: try { $client = new HttpClient(); $client->setUri($this->config['Catalog']['url']); $client->setRawBody($xml); $client->setEncType('application/xml; "charset=utf-8"'); $result = $client->setMethod('POST')->send(); } catch (\Exception $e) { throw new ILSException($e->getMessage()); } if (!$result->isSuccess()) { throw new ILSException('HTTP error'); } // Process the NCIP response: $response = $result->getBody(); $result = @simplexml_load_string($response); if (is_a($result, 'SimpleXMLElement')) { $result->registerXPathNamespace('ns1', 'http://www.niso.org/2008/ncip'); return $result; } else { throw new ILSException("Problem parsing XML"); } }
/** * Make an HTTP request * * @param string $url URL to request * * @return string */ protected function sendRequest($url) { // Make the NCIP request: try { $client = new HttpClient(); $client->setUri($url); $result = $client->setMethod('GET')->send(); } catch (\Exception $e) { throw new ILSException($e->getMessage()); } if (!$result->isSuccess()) { throw new ILSException('HTTP error'); } return $result->getBody(); }
/** * Send an NCIP request. * * @param string $xml XML request document * * @return object SimpleXMLElement parsed from response */ protected function sendRequest($xml) { // Make the NCIP request: try { $client = new HttpClient(); $client->setUri($this->config['Catalog']['url']); $client->setParameterPost(array('NCIP' => $xml)); $result = $client->setMethod('POST')->send(); } catch (\Exception $e) { throw new ILSException($e->getMessage()); } if (!$result->isSuccess()) { throw new ILSException('HTTP error'); } // Process the NCIP response: $response = $result->getBody(); if ($result = @simplexml_load_string($response)) { return $result; } else { throw new ILSException("Problem parsing XML"); } }
/** * Return the following array of values for each work: * title, cover_id, cover_id_type, key, ia, mainAuthor * * @param string $url URL to request * @param int $limit The number of works to return * @param bool $publicFullText Only return publically available, full-text * works * * @return array */ protected function processSubjectsApi($url, $limit, $publicFullText) { // empty array to hold the result $result = array(); //find out if there are any reviews $client = new HttpClient(); $client->setUri($url); $response = $client->setMethod('GET')->send(); // Was the request successful? if ($response->isSuccess()) { // grab the response: $json = $response->getBody(); // parse json $data = json_decode($json, true); if ($data) { $i = 1; foreach ($data['works'] as $work) { if ($i <= $limit) { if ($publicFullText && (!$work['public_scan'] || !$work['has_fulltext'])) { continue; } $result[$i]['title'] = $work['title']; if (isset($work['cover_id'])) { $result[$i]['cover_id_type'] = 'ID'; $result[$i]['cover_id'] = $work['cover_id']; } elseif (isset($work['cover_edition_key'])) { $result[$i]['cover_id_type'] = 'OLID'; $result[$i]['cover_id'] = $work['cover_edition_key']; } $result[$i]['key'] = $work['key']; $result[$i]['ia'] = $work['ia']; $result[$i]['mainAuthor'] = $work['authors'][0]['name']; $i++; } } } } return $result; }
/** * Make an OAI-PMH request. Die if there is an error; return a SimpleXML object * on success. * * @param string $verb OAI-PMH verb to execute. * @param array $params GET parameters for ListRecords method. * * @return object SimpleXML-formatted response. */ protected function sendRequest($verb, $params = array()) { // Debug: if ($this->verbose) { Console::write("Sending request: verb = {$verb}, params = " . print_r($params, true)); } // Set up retry loop: while (true) { // Set up the request: $request = new Client(null, array('timeout' => 60)); $request->setUri($this->baseURL); // Load request parameters: $query = $request->getRequest()->getQuery(); $query->set('verb', $verb); foreach ($params as $key => $value) { $query->set($key, $value); } // Perform request and die on error: $result = $request->setMethod('GET')->send(); if ($result->getStatusCode() == 503) { $delayHeader = $result->getHeaders()->get('Retry-After'); $delay = is_object($delayHeader) ? $delayHeader->getDeltaSeconds() : 0; if ($delay > 0) { if ($this->verbose) { Console::writeLine("Received 503 response; waiting {$delay} seconds..."); } sleep($delay); } } else { if (!$result->isSuccess()) { throw new \Exception('HTTP Error'); } else { // If we didn't get an error, we can leave the retry loop: break; } } } // If we got this far, there was no error -- send back response. return $this->processResponse($result->getBody()); }
/** * This method is responsible for connecting to Syndetics and abstracting * author notes. * * It first queries the master url for the ISBN entry seeking a note URL. * If a note URL is found, the script will then use HTTP request to * retrieve the script. The script will then parse the note according to * US MARC (I believe). It will provide a link to the URL master HTML page * for more information. * Configuration: Sources are processed in order - refer to $sourceList. * * @param string $id Client access key * @param bool $s_plus Are we operating in Syndetics Plus mode? * * @throws \Exception * @return array Returns array with author note data. * @author Joel Timothy Norman <*****@*****.**> * @author Andrew Nagy <*****@*****.**> */ protected function loadSyndetics($id, $s_plus = false) { $sourceList = array('ANOTES' => array('title' => 'Author Notes', 'file' => 'ANOTES.XML', 'div' => '<div id="syn_anotes"></div>')); //first request url $baseUrl = isset($this->config->Syndetics->url) ? $this->config->Syndetics->url : 'http://syndetics.com'; $url = $baseUrl . '/index.aspx?isbn=' . $this->getIsbn10() . '/index.xml&client=' . $id . '&type=rw12,hw7'; $anotes = array(); //find out if there are any notes $client = new HttpClient(); $client->setUri($url); $result = $client->setMethod('GET')->send(); if (!$result->isSuccess()) { return $anotes; } // Test XML Response if (!($xmldoc = DOMDocument::loadXML($result->getBody()))) { throw new \Exception('Invalid XML'); } $i = 0; foreach ($sourceList as $source => $sourceInfo) { $nodes = $xmldoc->getElementsByTagName($source); if ($nodes->length) { // Load notes $url = $baseUrl . '/index.aspx?isbn=' . $this->getIsbn10() . '/' . $sourceInfo['file'] . '&client=' . $id . '&type=rw12,hw7'; $client->setUri($url); $result2 = $client->send(); if (!$result2->isSuccess()) { continue; } // Test XML Response $xmldoc2 = DOMDocument::loadXML($result2->getBody()); if (!$xmldoc2) { throw new \Exception('Invalid XML'); } // If we have syndetics plus, we don't actually want the content // we'll just stick in the relevant div if ($s_plus) { $anotes[$i]['Content'] = $sourceInfo['div']; } else { // Get the marc field for author notes (980) $nodes = $xmldoc2->GetElementsbyTagName("Fld980"); if (!$nodes->length) { // Skip fields with missing text continue; } // Decode the content and strip unwanted <a> tags: $anotes[$i]['Content'] = preg_replace('/<a>|<a [^>]*>|<\\/a>/', '', html_entity_decode($xmldoc2->saveXML($nodes->item(0)))); /* // Get the marc field for copyright (997) $nodes = $xmldoc->GetElementsbyTagName("Fld997"); if ($nodes->length) { $anotes[$i]['Copyright'] = html_entity_decode( $xmldoc2->saveXML($nodes->item(0)) ); } else { $anotes[$i]['Copyright'] = null; } if ($anotes[$i]['Copyright']) { //stop duplicate copyrights $location = strripos( $anotes[0]['Content'], $anotes[0]['Copyright'] ); if ($location > 0) { $anotes[$i]['Content'] = substr($anotes[0]['Content'], 0, $location); } } */ } // change the xml to actual title: $anotes[$i]['Source'] = $sourceInfo['title']; $anotes[$i]['ISBN'] = $this->getIsbn10(); //show more link $anotes[$i]['username'] = $id; $i++; } } return $anotes; }
/** * Support method -- perform an HTTP request. This will be a GET request unless * either $postParams or $rawPost is set to a non-null value. * * @param string $url Target URL for request * @param array $postParams Associative array of POST parameters (null for * none). * @param string $rawPost String representing raw POST parameters (null for * none). * * @throws ILSException * @return string Response body */ protected function httpRequest($url, $postParams = null, $rawPost = null) { $method = is_null($postParams) && is_null($rawPost) ? 'GET' : 'POST'; try { $client = new HttpClient(); $client->setUri($url); if (is_array($postParams)) { $client->setParameterPost($postParams); } if (!is_null($rawPost)) { $client->setRawBody($rawPost); $client->setEncType('application/x-www-form-urlencoded'); } $result = $client->setMethod($method)->send(); } catch (\Exception $e) { throw new ILSException($e->getMessage()); } if (!$result->isSuccess()) { throw new ILSException('HTTP error'); } return $result->getBody(); }
/** * Guardian Reviews * * This method is responsible for connecting to the Guardian and abstracting * reviews for the specific ISBN. * * @param string $id Guardian API key * * @throws \Exception * @return array Returns array with review data * @author Eoghan Ó Carragáin <*****@*****.**> */ protected function loadGuardian($id) { //first request url $url = "http://content.guardianapis.com/search?order-by=newest&format=json" . "&show-fields=all&reference=isbn%2F" . $this->isbn->get13(); // Only add api-key if one has been provided in config.ini. If no key is // provided, a link to the Guardian can still be shown. if (strlen($id) > 0) { $url = $url . "&api-key=" . $id; } //find out if there are any reviews $client = new HttpClient(); $client->setUri($url); $result = $client->setMethod('GET')->send(); // Was the request successful? if ($result->isSuccess()) { // parse json from response $data = json_decode($result->getBody(), true); if ($data) { $result = array(); $i = 0; foreach ($data['response']['results'] as $review) { $result[$i]['Date'] = $review['webPublicationDate']; $result[$i]['Summary'] = $review['fields']['headline'] . ". " . preg_replace('/<p>|<p [^>]*>|<\\/p>/', '', html_entity_decode($review['fields']['trailText'])); $result[$i]['ReviewURL'] = $review['fields']['shortUrl']; // TODO: Make this configurable (or store it locally), so users // running VuFind behind SSL don't get warnings due to // inclusion of this non-SSL image URL: $poweredImage = 'http://image.guardian.co.uk/sys-images/Guardian/' . 'Pix/pictures/2010/03/01/poweredbyguardianBLACK.png'; $result[$i]['Copyright'] = "<a href=\"" . $review['fields']['shortUrl'] . "\" target=\"new\">" . "<img src=\"{$poweredImage}\" " . "alt=\"Powered by the Guardian\" /></a>"; $result[$i]['Source'] = $review['fields']['byline']; // Only return Content if the body tag contains a usable review $redist = "Redistribution rights for this field are unavailable"; if (strlen($review['fields']['body']) > 0 && !strstr($review['fields']['body'], $redist)) { $result[$i]['Content'] = $review['fields']['body']; } $i++; } return $result; } else { throw new \Exception('Could not parse Guardian response.'); } } else { return array(); } }
/** * Send a request to the SIRSI side API script and returns the response. * * @param array $params Associative array of query parameters to send. * * @return string */ protected function querySirsi($params) { // make sure null parameters are sent as empty strings instead or else the // driver.pl may choke on null parameter values foreach ($params as $key => $value) { if ($value == null) { $params[$key] = ''; } } $url = $this->url; if (empty($url)) { $url = $this->host; if ($this->port) { $url = "http://" . $url . ":" . $this->port . "/" . $this->search_prog; } else { $url = "http://" . $url . "/" . $this->search_prog; } } $httpClient = new HttpClient(); $httpClient->setMethod('POST'); $httpClient->setUri($url); $httpClient->setRawBody(http_build_query($params)); $httpClient->setEncType('application/x-www-form-urlencoded'); // use HTTP POST so parameters like user id and PIN are NOT logged by web // servers $result = $httpClient->send(); // Even if we get a response, make sure it's a 'good' one. if (!$result->isSuccess()) { throw new ILSException("Error response code received from {$url}"); } // get the response data $response = $result->getBody(); return rtrim($response); }
/** * Admin home. * * @return \Zend\View\Model\ViewModel */ public function homeAction() { $config = ConfigReader::getConfig(); $xml = false; if (isset($config->Index->url)) { $client = new HttpClient($config->Index->url . '/admin/multicore'); $response = $client->setMethod('GET')->send(); $xml = $response->isSuccess() ? $response->getBody() : false; } $view = $this->createViewModel(); $view->xml = $xml ? simplexml_load_string($xml) : false; return $view; }
/** * Make Request * * Makes a request to the Voyager Restful API * * @param array $hierarchy Array of key-value pairs to embed in the URL path of * the request (set value to false to inject a non-paired value). * @param array $params A keyed array of query data * @param string $mode The http request method to use (Default of GET) * @param string $xml An optional XML string to send to the API * * @throws ILSException * @return obj A Simple XML Object loaded with the xml data returned by the API */ protected function makeRequest($hierarchy, $params = false, $mode = "GET", $xml = false) { // Build Url Base $urlParams = "http://{$this->ws_host}:{$this->ws_port}/{$this->ws_app}"; // Add Hierarchy foreach ($hierarchy as $key => $value) { $hierarchyString[] = $value !== false ? urlencode($key) . "/" . urlencode($value) : urlencode($key); } // Add Params foreach ($params as $key => $param) { $queryString[] = urlencode($key) . "=" . urlencode($param); } // Build Hierarchy $urlParams .= "/" . implode("/", $hierarchyString); // Build Params $urlParams .= "?" . implode("&", $queryString); // Create Proxy Request $client = new HttpClient(); $client->setUri($urlParams); // Attach XML if necessary if ($xml !== false) { $client->setRawBody($xml); } // Send Request and Retrieve Response $result = $client->setMethod($mode)->send(); if (!$result->isSuccess()) { throw new ILSException('Problem with RESTful API.'); } $xmlResponse = $result->getBody(); $oldLibXML = libxml_use_internal_errors(); libxml_use_internal_errors(true); $simpleXML = simplexml_load_string($xmlResponse); libxml_use_internal_errors($oldLibXML); if ($simpleXML === false) { return false; } return $simpleXML; }
/** * This method is responsible for obtaining an image URL based on a name. * * @param string $imageName The image name to look up * * @return mixed URL on success, false on failure */ protected function getWikipediaImageURL($imageName) { $url = "http://{$this->lang}.wikipedia.org/w/api.php" . '?prop=imageinfo&action=query&iiprop=url&iiurlwidth=150&format=php' . '&titles=Image:' . urlencode($imageName); $client = new HttpClient(); try { $client->setUri($url); $result = $client->setMethod('GET')->send(); } catch (\Exception $e) { return false; } if (!$result->isSuccess()) { return false; } if ($response = $result->getBody()) { if ($imageinfo = unserialize($response)) { if (isset($imageinfo['query']['pages']['-1']['imageinfo'][0]['url'])) { $imageUrl = $imageinfo['query']['pages']['-1']['imageinfo'][0]['url']; } // Hack for wikipedia api, just in case we couldn't find it // above look for a http url inside the response. if (!isset($imageUrl)) { preg_match('/\\"http:\\/\\/(.*)\\"/', $response, $matches); if (isset($matches[1])) { $imageUrl = 'http://' . substr($matches[1], 0, strpos($matches[1], '"')); } } } } return isset($imageUrl) ? $imageUrl : false; }
/** * This method is responsible for connecting to Syndetics and abstracting * excerpts. * * It first queries the master url for the ISBN entry seeking an excerpt URL. * If an excerpt URL is found, the script will then use HTTP request to * retrieve the script. The script will then parse the excerpt according to * US MARC (I believe). It will provide a link to the URL master HTML page * for more information. * Configuration: Sources are processed in order - refer to $sourceList. * * @param string $id Client access key * @param bool $s_plus Are we operating in Syndetics Plus mode? * * @throws \Exception * @return array Returns array with excerpt data. * @author Joel Timothy Norman <*****@*****.**> * @author Andrew Nagy <*****@*****.**> */ protected function loadSyndetics($id, $s_plus = false) { //list of syndetic excerpts $sourceList = array('DBCHAPTER' => array('title' => 'First Chapter or Excerpt', 'file' => 'DBCHAPTER.XML', 'div' => '<div id="syn_dbchapter"></div>')); //first request url $baseUrl = isset($this->config->Syndetics->url) ? $this->config->Syndetics->url : 'http://syndetics.com'; $url = $baseUrl . '/index.aspx?isbn=' . $this->getIsbn10() . '/index.xml&client=' . $id . '&type=rw12,hw7'; $review = array(); //find out if there are any excerpts $client = new HttpClient(); $client->setUri($url); $result = $client->setMethod('GET')->send(); if (!$result->isSuccess()) { return $review; } // Test XML Response if (!($xmldoc = DOMDocument::loadXML($result->getBody()))) { throw new \Exception('Invalid XML'); } $i = 0; foreach ($sourceList as $source => $sourceInfo) { $nodes = $xmldoc->getElementsByTagName($source); if ($nodes->length) { // Load excerpts $url = $baseUrl . '/index.aspx?isbn=' . $this->getIsbn10() . '/' . $sourceInfo['file'] . '&client=' . $id . '&type=rw12,hw7'; $client->setUri($url); $result2 = $client->send(); if (!$result2->isSuccess()) { continue; } // Test XML Response $xmldoc2 = DOMDocument::loadXML($result2->getBody()); if (!$xmldoc2) { throw new \Exception('Invalid XML'); } // If we have syndetics plus, we don't actually want the content // we'll just stick in the relevant div if ($s_plus) { $review[$i]['Content'] = $sourceInfo['div']; } else { // Get the marc field for excerpts (520) $nodes = $xmldoc2->GetElementsbyTagName("Fld520"); if (!$nodes->length) { // Skip excerpts with missing text continue; } $review[$i]['Content'] = html_entity_decode($xmldoc2->saveXML($nodes->item(0))); // Get the marc field for copyright (997) $nodes = $xmldoc->GetElementsbyTagName("Fld997"); if ($nodes->length) { $review[$i]['Copyright'] = html_entity_decode($xmldoc2->saveXML($nodes->item(0))); } else { $review[$i]['Copyright'] = null; } if ($review[$i]['Copyright']) { //stop duplicate copyrights $location = strripos($review[0]['Content'], $review[0]['Copyright']); if ($location > 0) { $review[$i]['Content'] = substr($review[0]['Content'], 0, $location); } } } // change the xml to actual title: $review[$i]['Source'] = $sourceInfo['title']; $review[$i]['ISBN'] = $this->getIsbn10(); //show more link $review[$i]['username'] = $id; $i++; } } return $review; }
/** * Retrieve a Google Books cover. * * @return bool True if image displayed, false otherwise. */ protected function google() { // Don't bother trying if we can't read JSON: if (is_callable('json_decode')) { // Construct the request URL: $url = 'http://books.google.com/books?jscmd=viewapi&' . 'bibkeys=ISBN:' . $this->isn . '&callback=addTheCover'; // Make the HTTP request: $client = new HttpClient(); $client->setUri($url); $result = $client->setMethod('GET')->send(); // Was the request successful? if ($result->isSuccess()) { // grab the response: $json = $result->getBody(); // extract the useful JSON from the response: $count = preg_match('/^[^{]*({.*})[^}]*$/', $json, $matches); if ($count < 1) { return false; } $json = $matches[1]; // convert \x26 or \u0026 to & $json = str_replace(array("\\x26", "\\u0026"), "&", $json); // decode the object: $json = json_decode($json, true); // convert a flat object to an array -- probably unnecessary, but // retained just in case the response format changes: if (isset($json['thumbnail_url'])) { $json = array($json); } // find the first thumbnail URL and process it: foreach ($json as $current) { if (isset($current['thumbnail_url'])) { return $this->processImageURL($current['thumbnail_url'], false); } } } } return false; }
/** * Make Request * * Makes a request to the Horizon API * * @param array $params A keyed array of query data * @param string $mode The http request method to use (Default of GET) * * @return obj A Simple XML Object loaded with the xml data returned by the API */ protected function makeRequest($params = false, $mode = "GET") { // Build Url Base $urlParams = $this->wsURL; // Add Params foreach ($params as $key => $param) { if (is_array($param)) { foreach ($param as $sub) { $queryString[] = $key . "=" . urlencode($sub); } } else { // This is necessary as Horizon expects spaces to be represented by // "+" rather than the url_encode "%20" for Pick Up Locations $queryString[] = $key . "=" . str_replace("%20", "+", urlencode($param)); } } // Build Params $urlParams .= "?" . implode("&", $queryString); // Create Proxy Request $client = new HttpClient(); $client->setUri($urlParams); // Send Request and Retrieve Response $result = $client->setMethod($mode)->send(); if (!$result->isSuccess()) { throw new ILSException('Problem with XML API.'); } $xmlResponse = $result->getBody(); $oldLibXML = libxml_use_internal_errors(); libxml_use_internal_errors(true); $simpleXML = simplexml_load_string($xmlResponse); libxml_use_internal_errors($oldLibXML); if ($simpleXML === false) { return false; } return $simpleXML; }
/** * This method is responsible for connecting to Syndetics and abstracting * clips. * * It first queries the master url for the ISBN entry seeking a clip URL. * If a clip URL is found, the script will then use HTTP request to * retrieve the script. The script will then parse the clip according to * US MARC (I believe). It will provide a link to the URL master HTML page * for more information. * Configuration: Sources are processed in order - refer to $sourceList. * * @param string $id Client access key * @param bool $s_plus Are we operating in Syndetics Plus mode? * * @throws \Exception * @return array Returns array with video clip data. * @author Joel Timothy Norman <*****@*****.**> * @author Andrew Nagy <*****@*****.**> */ protected function loadSyndetics($id, $s_plus = false) { $sourceList = array('VIDEOCLIP' => array('title' => 'Video Clips', 'file' => 'VIDEOCLIP.XML', 'div' => '<div id="syn_video_clip"></div>')); //first request url $baseUrl = isset($this->config->Syndetics->url) ? $this->config->Syndetics->url : 'http://syndetics.com'; $url = $baseUrl . '/index.aspx?isbn=' . $this->getIsbn10() . '/index.xml&client=' . $id . '&type=rw12,hw7'; $vclips = array(); //find out if there are any clips $client = new HttpClient(); $client->setUri($url); $result = $client->setMethod('GET')->send(); if (!$result->isSuccess()) { return $vclips; } // Test XML Response if (!($xmldoc = DOMDocument::loadXML($result->getBody()))) { throw new \Exception('Invalid XML'); } $i = 0; foreach ($sourceList as $source => $sourceInfo) { $nodes = $xmldoc->getElementsByTagName($source); if ($nodes->length) { // Load clips $url = $baseUrl . '/index.aspx?isbn=' . $this->getIsbn10() . '/' . $sourceInfo['file'] . '&client=' . $id . '&type=rw12,hw7'; $client->setUri($url); $result2 = $client->send(); if (!$result2->isSuccess()) { continue; } // Test XML Response $xmldoc2 = DOMDocument::loadXML($result2->getBody()); if (!$xmldoc2) { throw new \Exception('Invalid XML'); } // If we have syndetics plus, we don't actually want the content // we'll just stick in the relevant div if ($s_plus) { $vclips[$i]['Content'] = $sourceInfo['div']; } else { // Get the field for video clips (VideoLink) $nodes = $xmldoc2->GetElementsbyTagName("VideoLink"); if (!$nodes->length) { // Skip clips with missing text continue; } // stick the link into an embed tag. $vclips[$i]['Content'] = '<embed width="400" height="300" type="' . 'application/x-shockwave-flash"' . 'allowfullscreen="true" src="' . html_entity_decode($nodes->item(0)->nodeValue) . '">'; // Get the marc field for copyright (997) $nodes = $xmldoc->GetElementsbyTagName("Fld997"); if ($nodes->length) { $vclips[$i]['Copyright'] = html_entity_decode($xmldoc2->saveXML($nodes->item(0))); } else { $vclips[$i]['Copyright'] = null; } } // change the xml to actual title: $vclips[$i]['Source'] = $sourceInfo['title']; $vclips[$i]['ISBN'] = $this->getIsbn10(); //show more link $vclips[$i]['username'] = $id; $i++; } } return $vclips; }