Read One Node of XML in PHP - php

I have been searching for how to read one node of XML in PHP. The PHP documentation wasn't helpful because I don't understand how to use PHP. All of the tutorials I found weren't useful beacause I only need PHP to read XML(I use CSHTML for Databases and other server-side things). I have working code that can read XML as a tree if it is in a RSS format. I am trying to get the google map geocode api information, from "http://maps.googleapis.com/maps/api/geocode/xml?latlng=38.7876639,-90.8455276&sensor=false." I only want the very first "Formatted_address" node. My current code is;
<?php
$xml=("http://maps.googleapis.com/maps/api/geocode/xml?latlng=38.7876639,-90.8455276&sensor=false");
$xmlDoc = new DOMDocument();
$xmlDoc->load($xml);
//get and output "<result>" elements
$x=$xmlDoc->getElementsByTagName('result');
for ($i=0; $i<=2; $i++)
{
$item=$x->result($i)->getElementsByTagName('formatted_address')
->result(0)->childNodes->result(0)->nodeValue;
echo ( $item);
}
?>
However this always returns a 500 error and I don't understand what i am doing wrong. Thank you all in advance.

Change result to item
$item = $x->item($i)->getElementsByTagName('formatted_address')
->item(0)->childNodes->result(0)->nodeValue;
As you can see DOMNodeList only has one method called item(int $index)

Related

How to create a XML File From Server Response (PHP)

I have a response that I got from a server using PHP, it is returned in XML format. Unfortunately I cannot disclose the code that is in question since it is for a client, but here is a shortened version of it:
// server request code here…
$result = $soap>__doRequest($xmltosend,URL,$action,1); //the final part of the request process…
// $result is the returned xml that is to be converted into a separate file
Is there any way that I could take the returned XML and make a new file? If you have any questions I will be more than happy to answer them!
Thanks in advance!
Try it with DOMDocument:
$doc = new DOMDocument();
$doc->loadXML($result);
$doc->save("/tmp/your-document.xml");
You can find more on this in the php documentation

Can't access XML node via xpath() (YT channel feed)

Very stumped by this one. In PHP, I'm fetching a YouTube user's vids feed and trying to access the nodes, like so:
$url = 'http://gdata.youtube.com/feeds/api/users/HCAFCOfficial/uploads';
$xml = simplexml_load_file($url);
So far, so fine. Really basic stuff. I can see the data comes back by running:
echo '<p>Found '.count($xml->xpath('*')).' nodes.</p>'; //41
echo '<textarea>';print_r($xml);echo '</textarea>';
Both print what I would expect, and the print_r replicates the XML structure.
However, I have no idea why this is returning zero:
echo '<p>Found '.count($xml->xpath('entry')).'"entry" nodes.</p>';
There blatantly are entry nodes in the XML. This is confirmed by running:
foreach($xml->xpath('*') as $node) echo '<p>['.$node->getName().']</p>';
...which duly outputs "[entry]" 25 times. So perhaps this is a bug in SimpleXML? This is part of a wider feed caching system and I'm not having any trouble with other, non-YT feeds, only YT ones.
[UPDATE]
This question shows that it works if you do
count($xml->entry)
But I'm curious as to why count($xml->xpath('entry')) doesn't also work...
[Update 2]
I can happily traverse YT's anternate feed format just fine:
http://gdata.youtube.com/feeds/base/users/{user id}/uploads?alt=rss&v=2
This is happening because the feed is an Atom document with a defined default namespace.
<feed xmlns="http://www.w3.org/2005/Atom" ...
Since a namespace is defined, you have to define it for your xpath call too. Doing something like this works:
$url = 'http://gdata.youtube.com/feeds/api/users/HCAFCOfficial/uploads';
$xml = simplexml_load_file($url);
$xml->registerXPathNamespace('ns', 'http://www.w3.org/2005/Atom');
$results = $xml->xpath('ns:entry');
echo count($results);
The main thing to know here is that SimpleXML respects any and all defined namespaces and you need to handle them accordingly, including the default namespace. You'll notice that the second feed you listed does not define a default namespace and so the xpath call works fine as is.

PHP Xpath Scrape Possible Namespace Issue

UPDATE: The source code is very much different from what Developer Tools shows.
Check out the source: view-source:http://www.machinerytrader.com/list/list.aspx?ETID=1&catid=1002
Is that javascript that needs to be rendered by a browser into html? If so, how can I have php do that process so that I have Html to parse? It's weird that you can use Xpath Checker to return the items I'm looking for (see below), but you cannot access the full html!
(Xpath: //table[contains(#id, 'ctl00_ContentPlaceHolder1') and (contains(#id,"tblContent") or contains(#id,"tblListingHeader"))])
END UPDATE
I need to scrape some information off of this site for work on a regular basis. I am attempting to write some PHP code to scrape this data. I think I have some namespace issues here, having read a number of other posts on SO. I have never encountered namespace problems before and used the approach shown on another SO post (to no avail :().
It appears the xpath query is just not happening for whatever reason. If you have any guesses or solutions as to how to handle this issue, I am open for suggestions.
Also here is the output from my code:
object(DOMXPath)#2 (0) {
}
Debug 1
array(0) {
}
array(0) {
}
I left out the bottom of the code where I var_dump testarray and create and var_dump otherarray. Their output is included above. Obviously the two arrays will be empty if the DOMXPath element has length 0 as well.
$string = 'http://www.machinerytrader.com/list/list.aspx?ETID=1&catid=1002';
$machine_trader = file_get_contents($string);
$xml = new DOMDocument();
$xml->loadHTML($machine_trader);
$xpath = new DOMXPath($xml);
$rootNamespace = $xml->lookupNamespaceUri($xml->namespaceURI);
$xpath->registerNamespace('x', $rootNamespace);
$tableRows = $xpath->query("//x:table[contains(#id, 'ctl00_ContentPlaceHolder1') and (contains(#id,'tblContent') or contains(#id,'tblListingHeader'))]");
var_dump($xpath);
$testarray = array();
$otherarray = array();
foreach ( $tableRows as $row )
{
echo "Debug 1"."\n";
$testarray[] = $row->nodeValue;
}
This is not an XPath issue insofar that the actual content is found from a form post, which you didn't reach yet. JS Source code here does nothing more than authenticate a proper 'user' for the information request, and then send the request via form submission.
At each request, the salt / encryption 'key' is randomized and changes, preventing simple scrapes.
You could rewrite that JavaScript to PHP and then issue two requests, battling the authentication process along the way.
Or, rather than diddle with reverse-engineering this, you could switch your scraping to NodeJS and use something like PhantomJS since it can evaluate javascript but give you programmatic access. Given the complexity of this task, it'd be much simpler to use the right tool.

Dynamic XML from a template and hash tree in PHP

Hello All!
I'm active in a fairly large project, but I have limited experience with XML. I am dynamically generating XML, data which may be customed to needs of individual customers. The current solution has been (please don't hurt me, I'm the new guy) to inline a php template by include(). This is not good practice and I want to move to a better solution.
Structure
<?xml version='1.0'?>
<Product id="">
<AswItem></AswItem>
<EanCode></EanCode>
<ImagePopup></ImagePopup>
<ImageInfo></ImageInfo>
<ImageThumbnail></ImageThumbnail>
<PriceCurrency></PriceCurrency>
<PriceValueNoTax></PriceValueNoTax>
<Manufacture></Manufacture>
<ProductDescriptions>
<ProductDescrition language="" id="">
<Name></Name>
<Description></Description>
<Color></Color>
<Size></Size>
<NavigationLevel1></NavigationLevel1>
<NavigationLevel2></NavigationLevel2>
<NavigationLevel3></NavigationLevel3>
<NavigationLevel4></NavigationLevel4>
</ProductDescrition>
</ProductDescriptions>
<MatrixProducts>
<AswItem></AswItem>
<EanCode></EanCode>
<ParentId></ParentId>
<PriceCurrency></PriceCurrency>
<PriceValueNoTax></PriceValueNoTax>
<ImagePopup></ImagePopup>
<ImageInfo></ImageInfo>
<ImageThumbnail></ImageThumbnail>
</MatrixProducts>
</Product>
This is our main structure. ProductDescriptions and MatrixProducts are basically list items, and may contain none to several children. Our object to be translated into XML is a PHP hash tree with a similar structure but with different keys.
Problem
The problem I have is that I get stuck in the thought process on how dynamically create a tree from an object. My current plan is to have a key conversion table (see Current Solution) but a voice in the back of my head is telling me that it's not best practice.
Previous solution
populate.php
foreach($products as $product) {
// too much black magic in here
include($chosenTemplate);
// $productXMLString is generated in the previous include
printToXML($productXMLString)
}
template.php
<?
echo "<Product id='{$product['id']}'>";
// etc...
echo "</product>";
As you can see, this is a pretty bad approach. Bad error handling, messy syntax and lot's of other quirks.
Current solution
$xmlProductTemplate = simplexml_load_file($currentTemplate);
foreach($products as $product) {
$xmlObj = clone $xmlProductTemplate;
foreach($product as $key => $productValue) {
// if value is a <$key>$string</$key>, just input
// it into the translated key for the $xmlObject
if(!is_array($productValue))
$xmlObj[translateKeyToXML($key)] = $productValue;
// elseway, we need to call the magic; traverse a child array
// and still hold true to templateing
else {
// what DO you do?
}
}
// save xml
fputs($xmlObj->asXML());
}
How would you go about this and what is best practice? I'm a bit hungry and dehydrated so please tell me if I'm missing something basic.
I am having a bit of trouble understanding what you're trying to do so excuse me if I'm off here. What it seems like you are trying to do is create an XML file based on a "template" with an ArrayObject containing the attributes and values of the XML elements.
Perhaps, instead of trying to do that, you just create a SimpleXML object. I think that would be much easier for what you're trying to do and it adds the value of error catching. See SimpleXML on PHP.net.
If I am not on the right track with an answer, can you post more source code like the class that contains the values? Thanks.

working with XML in PHP

I have an url return an XML page result. When I use this command:
print_r(file($url));
Its done, but when I use command:
$doc = load($url);
after that I :
print_r($doc);
it out. Its print_r out nothing. I'm quite new in work with XML in PHP someone give advise, please!
Thank you for your attention!
I am not really sure what you trying to do but for parsing an xml file in PHP there two main ways: DOM
$doc = new DOMDocument();
$doc->loadXML(file_get_contents($url));
SimpleXML
$xml = new SimpleXMLElement(file_get_contents($xmlstr));
file_get_contents Reads entire file into a string
#deceze and RageZ:
I'm using load() to get its attribute like this
$url = 'web address return an XML result';
$xml = load($url);
$node1 = $xml->getElmentsByTagName('tagname');
$value = $node1->getAttribute('attribute1');
But I have an error $xml is not an object and I check out by print_r and I get nothing but with print_r(file($url)) its print out an array as I expect!
#Franz: May be I get an error tag in XML file but I could not fixed this just work with the result!
You could also unserialize the xml into a php array and use print_r(array). Take a look here: http://articles.sitepoint.com/article/xml-php-pear-xml_serializer/3#
You will need a PEAR package for this

Categories