I have an XML file which is something like this:
(fileName : abc.xml)
<Envelope>
<Body>
<SResponse>
<Body>
<SResponseDetails>
<SItem>...</SItem>
<SItem>...</SItem>
<SItem>...</SItem>
<SItem>...</SItem>
</SResponseDetails>
</Body>
</SResponse>
</Body>
</Envelope>
I want to store all <SItem> in a db table (1 record for each SItem). I am using PHP for it and using XmlStringStreamer.
Here is my code for reading this file and processing it.
$streamer = \Prewk\XmlStringStreamer::createStringWalkerParser(__DIR__ . "/tempFile.xml");
$stream = new Stream\File(__DIR__ . "/abc.xml", 1024);
$parser = new Parser\StringWalker();
$streamer = new XmlStringStreamer($parser, $stream);
while ($node = $streamer->getNode()) {
$simpleXmlNode = simplexml_load_string($node);
//-- code here for getting single node
}
I am using XmlStringStreamer and did not get any answer from any forum, I also tried but could not get what I want so, can anyone please help me.
Thanks Alot.
I have solved it, here is my answer for it.
For looping for specific item, we can directly use this in xmlStringSteamer:
$stream = new Stream\File(__DIR__ . "/abc.xml", 1024);
$options = array(
"uniqueNode" => "SItem"
);
$parser = new Parser\UniqueNode($options);
// Create the streamer
$streamer = new XmlStringStreamer($parser, $stream);
$countNodes = 0;
while ($node = $streamer->getNode())
{
print_r($node);
}
The only problem is that it converts xml tags to lowercase. like <SItem> becomes <sitem>. So, anyone have idea about this problem?
I didn't executed your code but i think you can use PHP logic. If anything doesn't work for you then last solution will be exploding $simpleXmlNode to get some array structure and then process it according to your need. By the way can you share what you got after $simpleXmlNode = simplexml_load_string($node)?
For others, i can't add comments so posting this as answer.
Related
I am attempting to only run a loop if xml results actually exist. I am getting the xml results via:
$albums = simplexml_load_string(curl_get($api_url . '/videos.xml'));
What I want to be able to do is that on the next line say:
if($albums = hasAValue())
// Loop
Any ideas? Or a way to check before I load the XML data?
Side note: This is using the Vimeo API.
No, you need to further go down with the resultant with the namespace, reach till body give the xpath and work on.
$albums->registerXPathNamespace('soap', 'http://schemas.xmlsoap.org/soap/envelope/');
To be specific, let me know the XML response you are getting i will let you the output.
UPDATED
$albums = simplexml_load_string("#your response#");
echo count($xml->children());
The dirty way:
$albums = #simplexml_load_string(curl_get($api_url . '/videos.xml'));
if ($albums)
{
...
}
This is dirty because of the Error Control Operator # which is used to "deal" with the error cases (e.g. problem fetching the remote location).
The alternative is to differentiate more here:
$xml = curl_get($api_url . '/videos.xml');
$albums = NULL;
if ($xml)
{
$albums = simplexml_load_string($xml);
}
if ($albums)
{
...
}
I'm trying to write a script that will update an RSS XML file. I want it to take the existing file and add a new item to the top of the items list. I've previous gotten it to add to the end of the file, but now it's currently not adding the new item at all. I've been checking around online, but I still can't get it to work. Here is what I have so far:
$rssDoc = new DOMDocument();
$rss_file = $_SERVER['DOCUMENT_ROOT'].'/test_site/feed.xml';
$rssDoc->load($rss_file);
$items = $rssDoc->getElementsByTagName('item');
$newItem = $rssDoc->createElement('item');
$rssTitle = $rssDoc->createElement('title');
$rssTitle->appendChild($rssDoc->createTextNode($title));
$newItem->appendChild($rssTitle);
$rssDesc = $rssDoc->createElement('description');
$rssDesc->appendChild($rssDoc->createTextNode($string));
$newItem->appendChild($rssDesc);
$rssLink = $rssDoc->createElement('link');
$rssLink->appendChild($rssDoc->createTextNode($link));
$newItem->appendChild($rssLink);
$rssDate = $rssDoc->createElement('pubDate');
$rssDate->appendChild($rssDoc->createTextNode($pubDate));
$newItem->appendChild($rssDate);
$firstItem = $items->item(0);
$firstItem->insertBefore($newItem,$firstItem->firstChild);
$rssDoc->formatOutput = true;
echo $rssDoc->saveXML();
What am I missing?
"What am I missing?"
The output: $rssDoc->save( 'filename.xml' ) http://php.net/domdocument.save.php
I got it working. I changed these lines:
$firstItem = $items->item(0);
$firstItem->insertBefore($newItem,$firstItem->firstChild);
To this line:
$items->item(0)->parentNode->insertBefore($newItem,$items->item(0));
I have a php file setup to pull through ONE XML data feed, What I would like to do is load up to 4 feeds into it and if possible make it select a random item too. Then parse that into an jQuery News Ticker.
My current PHP is as follows...
<?php
$feed = new DOMDocument();
$feed->load('/feed');
$json = array();
$json['title'] = $feed->getElementsByTagName('channel')->item(0)->getElementsByTagName('title')->item(0)->firstChild->nodeValue;
$json['description'] = $feed->getElementsByTagName('channel')->item(0)->getElementsByTagName('description')->item(0)->firstChild->nodeValue;
$json['link'] = $feed->getElementsByTagName('channel')->item(0)->getElementsByTagName('link')->item(0)->firstChild->nodeValue;
$items = $feed->getElementsByTagName('channel')->item(0)->getElementsByTagName('item');
$json['item'] = array();
$i = 0;
foreach($items as $item) {
$title = $item->getElementsByTagName('title')->item(0)->firstChild->nodeValue;
$description = $item->getElementsByTagName('description')->item(0)->firstChild->nodeValue;
$pubDate = $item->getElementsByTagName('pubDate')->item(0)->firstChild->nodeValue;
$guid = $item->getElementsByTagName('guid')->item(0)->firstChild->nodeValue;
$json['item'][$i++]['title'] = $title;
$json['item'][$i++]['description'] = $description;
$json['item'][$i++]['pubdate'] = $pubDate;
$json['item'][$i++]['guid'] = $guid;
echo '<li class="news-item">'.$title.'</li>';
}
//echo json_encode($json);
?>
How can I modify this to load more than one feed into the file?
Thanks in advance
The simplest approach to doing this is wrapping another loop around the code you have. It's not the cleanest way but will probably suffice for the purpose.
In general, IMO, it's always beneficial to learn the basics of the language first. E.g. PHP manual on foreach
This is roughly what the loop needs to look like:
$my_feeds = array("http://.....", "http://.....", "http://.....");
foreach ($my_feeds as $my_feed)
{
// This is where your code starts
$feed = new DOMDocument();
$feed->load($my_feed); <--------------- notice the variable
$json = array();
... and the rest of the code
}
this will walk through all the URLs in $my_feeds, open the RSS source, fetch all the items from it, and output them.
If I'm reading your question right, what you may want to do is turn your code into a function, which you would then run inside a foreach loop for each url (which you could store in an array or other data structure).
Edit: If you don't know much about functions, this tutorial section might help you. http://devzone.zend.com/9/php-101-part-6-functionally-yours/
I'm fairly new to php although I've been programming for a couple years.
I'm working on a project and the end goal is to load certain elements of an xml file into an oracle table on a nightly basis. I have a script which runs nightly and saves a the file on my local machine. I've searched endlessly for answers but have been unsuccessful.
Here is an aggregated example of the xml file.
<?xml version="1.0" encoding="UTF-8" ?>
<Report account="7869" start_time="2012-02-23T00:00:00+00:00" end_time="2012-02-23T15:27:59+00:00" user="twilson" more_sessions="false">
<Session id="ID742247692" realTimeID="4306650378">
<Visitor id="5390643113837">
<ip>128.XXX.XX.XX</ip>
<agent>MSIE 8.0</agent>
</Visitor>
</Session>
<Session id="ID742247695" realTimeID="4306650379">
<Visitor id="7110455516320">
<ip>173.XX.XX.XXX</ip>
<agent>Chrome 17.0.963.56</agent>
</Visitor>
</Session>
</Report>
One thing to note is that the xml file will contain several objects which I will need to load into my table and the above example would just be for two rows of data. I'm familiar with the whole process of connecting and loading data into oracle and have setup similar scripts which perform ETL of txt. and csv. files using php. Unfortunately for me in this case the data is stored in xml. The approach I've taken when loading a csv. file is to load the data into an array and proceed from there.
I'm pretty certain that I can use something similar and perhaps create variable for each or something similar but am not really too sure how to do that with an xml. file.
$xml = simplexml_load_file('C:/Dev/report.xml');
echo $xml->Report->Session->Visitor->agent;
In the above code i'm trying to just return the agent associated with each visitor. This returns an error 'Trying to get property of non-object in C:\PHP\chatTest.php on line 11'
The end result would be for me to load the data into a table similar to the example I provided would be to load two rows into my table which would look similar to below however I think I can handle that if i'm able to get the data into an array or something similar.
IP|AGENT
128.XXX.XX.XX MSIE 8.0
173.XX.XX.XXX Chrome 17.0.963.56
Any help would be greatly appreciated.
Revised Code:
$doc = new DOMDocument();
$doc->load( 'C:/Dev/report.xml' );
$sessions = $doc->getElementsByTagName( "Session" );
foreach( $sessions as $session )
{
$visitors = $session->getElementsByTagName( "Visitor" );
foreach( $visitors as $visitor )
$sessionid = $session->getAttribute( 'realTimeID' );
{
$ips = $visitor->getElementsByTagName( "ip" );
$ip = $ips->item(0)->nodeValue;
$agents = $visitor->getElementsByTagName( "agent" );
$agent = $ips->item(0)->nodeValue;
echo "$sessionid- $ip- $agent\n";
}}
?>
The -> operator in PHP means that you are trying to invoke a field or method on an object. Since Report is not a method within $xml, you are receiving the error that you are trying to invoke a property on a non-object.
You can try something like this (don't know if it works, didn't test it and haven't written PHP for a long time, but you can google it):
$doc = new DOMDocument();
$doc->loadXML($content);
foreach ($doc->getElementsByTagName('Session') as $node)
{
$agent = $node->getElementsByTagName('Visitor')->item(0)->getElementsByTagName('agent')->item(0)->nodeValue;
}
edit:
Adding stuff to an array in PHP is easy as this:
$arr = array();
$arr[] = "some data";
$arr[] = "some more data";
The PHP arrays should be seen as a list, since they can be resized on the fly.
I was able to figure this out using simplexml_load_file rather than the DOM approach. Although DOM works after modifying the Leon's suggestion the approach below is what I would suggest.
$xml_object = simplexml_load_file('C:/Dev/report.xml');
foreach($xml_object->Session as $session) {
foreach($session->Visitor as $visitor) {
$ip = $visitor->ip;
$agent = $visitor->agent;
}
echo $ip.','.$agent."\n";
}
I have an XML file. I want to save all the data from the XML file to the database
The file structure of XML is like
<STORY>
<BYLINE>abc</BYLINE>
<STORYID>123456</STORYID>
</STORY>
The code for storing data to database that I am using is
$dom = new DOMDOcument();
$dom->loadXML(equitymarketnews/$zname);
$xpath = new DOMXpath($dom);
$res = $xpath->query("//STORY/");
$allres = array();
foreach($res as $node){
$result = array();
$byline = mysql_real_escape_string($node->getElementsByTagName("BYLINE")->item(0)->nodeValue);
$storyid = mysql_real_escape_string($node->getElementsByTagName("STORYID")->item(0)->nodeValue);
}
$sql12="insert into equitymarketnews values('$byline','$storyid')";
mysql_query($sql12);
I am getting nothing in my database. All values are blanks.
Where am I going wrong?
I think something is wrong with this line
$res = $xpath->query("//STORY/");
i want to story the data ie ABC and 12345 FROm XML File To Table in database
I don't really know what your question is but assuming that the code you posted does not work as you aspect, one thing i noticed is the insertion of the record:
$sql12="insert into equitymarketnews values('$byline','$storyid','$pubdate','$author','$cat','$subcat','$titleline','$subtitleline,'$storymain','$flag')";
mysql_query($sql12);
shouldn't it be inside your foreach loop? Otherwise you won't get anything into your database.
In my opinion it should look something like that:
foreach($res as $node){
$result = array();
$byline = mysql_real_escape_string($node->getElementsByTagName("BYLINE")->item(0)->nodeValue);
$storyid = mysql_real_escape_string($node->getElementsByTagName("STORYID")->item(0)->nodeValue);
$sql12="insert into equitymarketnews values('$byline','$storyid')";
mysql_query($sql12);
}
You can actually use mysql client directly for importing XML data. I do not have much experience to provide you with a code sample, but MySQL docs have quite a bit documentation on it.
Essentially, you can do something like this:
LOAD XML LOCAL INFILE 'address.xml' INTO TABLE quitymarketnews ROWS IDENTIFIED BY '<STORY>';