Is it possible to change a sub-string of an object element
in the flow inside of a foreach loop? So what I try but it's not working.
$xml= '';
foreach ($objetcs as $object){
str_replace('searched','replacement', $object->link);
//then I would call a function to render my rss
$xml .=$object->renderRSS();
}
str_replace will return a string or an array, it won't change original variable, so you should do $object->link = str_replace('searched','replacement', $object->link); if $link is public
Try this:
$xml= '';
foreach ($objetcs as $object){
$object->link = str_replace('searched','replacement', $object->link);
//then I would call a function to render my rss
$xml .=$object->renderRSS();
}
Try:
$object->link = str_replace('searched','replacement', $object->link);
Related
I am somewhat new with PHP, but can't really wrap my head around what I am doing wrong here given my situation.
Problem: I am trying to get the href of a certain HTML element within a string of characters inside an XML object/element via Reddit (if you visit this page, it would be the actual link of the video - not the reddit link but the external youtube link or whatever - nothing else).
Here is my code so far (code updated):
Update: Loop-mania! Got all of the hrefs, but am now trying to store them inside a global array to access a random one outside of this function.
function getXMLFeed() {
echo "<h2>Reddit Items</h2><hr><br><br>";
//$feedURL = file_get_contents('https://www.reddit.com/r/videos/.xml?limit=200');
$feedURL = 'https://www.reddit.com/r/videos/.xml?limit=200';
$xml = simplexml_load_file($feedURL);
//define each xml entry from reddit as an item
foreach ($xml -> entry as $item ) {
foreach ($item -> content as $content) {
$newContent = (string)$content;
$html = str_get_html($newContent);
foreach($html->find('table') as $table) {
$links = $table->find('span', '0');
//echo $links;
foreach($links->find('a') as $link) {
echo $link->href;
}
}
}
}
}
XML Code:
http://pasted.co/0bcf49e8
I've also included JSON if it can be done this way; I just preferred XML:
http://pasted.co/f02180db
That is pretty much all of the code. Though, here is another piece I tried to use with DOMDocument (scrapped it).
foreach ($item -> content as $content) {
$dom = new DOMDocument();
$dom -> loadHTML($content);
$xpath = new DOMXPath($dom);
$classname = "/html/body/table[1]/tbody/tr/td[2]/span[1]/a";
foreach ($dom->getElementsByTagName('table') as $node) {
echo $dom->saveHtml($node), PHP_EOL;
//$originalURL = $node->getAttribute('href');
}
//$html = $dom->saveHTML();
}
I can parse the table fine, but when it comes to getting certain element's values (nothing has an ID or class), I can only seem to get ALL anchor tags or ALL table rows, etc.
Can anyone point me in the right direction? Let me know if there is anything else I can add here. Thanks!
Added HTML:
I am specifically trying to extract <span>[link]</span> from each table/item.
http://pastebin.com/QXa2i6qz
The following code can extract you all the youtube links from each content.
function extract_youtube_link($xml) {
$entries = $xml['entry'];
$videos = [];
foreach($entries as $entry) {
$content = html_entity_decode($entry['content']);
preg_match_all('/<span><a href="(.*)">\[link\]/', $content, $matches);
if(!empty($matches[1][0])) {
$videos[] = array(
'entry_title' => $entry['title'],
'author' => preg_replace('/\/(.*)\//', '', $entry['author']['name']),
'author_reddit_url' => $entry['author']['uri'],
'video_url' => $matches[1][0]
);
}
}
return $videos;
}
$xml = simplexml_load_file('reddit.xml');
$xml = json_decode(json_encode($xml), true);
$videos = extract_youtube_link($xml);
foreach($videos as $video) {
echo "<p>Entry Title: {$video['entry_title']}</p>";
echo "<p>Author: {$video['author']}</p>";
echo "<p>Author URL: {$video['author_reddit_url']}</p>";
echo "<p>Video URL: {$video['video_url']}</p>";
echo "<br><br>";
}
The code outputs in the multidimensional format of array with the elements inside are entry_title, author, author_reddit_url and video_url. Hope it helps you!
If you're looking for a specific element you don't need to parse the whole thing. One way of doing it could be to use the DOMXPath class and query directly the xml. The documentation should guide you through.
http://php.net/manual/es/class.domxpath.php .
I'm using a variable to create an element. But I'm getting this error:
Warning: DOMDocument::createElement() expects parameter 1 to be string, object given
// load up your XML
$xml = new DOMDocument;
$xml->load('test.xml');
$parent_node = $xml->createElement('parent');
foreach ($xml->getElementsByTagName('product') as $product )
{
$append = array();
foreach($product->getElementsByTagName('name') as $name ) {
// Stick $name onto the array
$append[] = $name;
}
foreach ($append as $a) {
$parent_node->appendChild($xml->createElement($a, 'anothervalue'));
$product->appendChild($parent_node);
}
$product->removeChild($xml->getElementsByTagName('details')->item(0));
//$product->appendChild($element);
}
// final result:
$result = $xml->saveXML();
Original XML structure:
<products>
<product>
<name>text</name>
<name>text</name>
<name>text</name>
</product>
</products>
I'm trying to create a new element whose value is the text of itself. I know what it has to look like. Why can't I use an object to create an element?
The result I'm trying to obtain will look like this:
<products>
<product>
<text>text</text>
<text>text</text>
<text>text</text>
</product>
</products>
You can't pass an object, you must use the textContent or nodeValue properties:
$element = $xml->createElement(trim($a->textContent), 'anothervalue');
You may also want to strip it from illegal characters first:
$nodeName = preg_replace('/[^a-z0-9_-]/i', '', $a->textContent);
$element = $xml->createElement($nodeName, 'anothervalue');
declare the array befor the foreach loop otherwise it will become empty every time when one loop will complete
$append = array();
foreach ($xml->getElementsByTagName('product') as $product )
{
foreach($product->getElementsByTagName('name') as $name ) {
// Stick $name onto the array
$append[] = $name;
}
foreach ($append as $a) {
$parent_node->appendChild($xml->createElement($a, 'anothervalue'));
$product->appendChild($parent_node);
}
$product->removeChild($xml->getElementsByTagName('details')->item(0));
//$product->appendChild($element);
}
$parent_node->appendChild($xml->createElement($a->nodeValue, 'anothervalue'));
This get element value, if you wanna get the element name .. use '$a->nodeName'
Just change this one line
$append[] = $name;
to
$append[] = $name->tagName;
It should work then
i need to access a simplexml object using a string. ie.
$x->a->b = 'obj';
$s = 'a->b';
echo $x->$s;
but it doesn't seem to work...
please help!
:)
You can do that like this, if my memory serves me:
echo $x->{$s};
you could use references:
$s =& $x->a->b;
or, if you want the string approach, build up the reference step by step:
function getRef($base, $str) {
$out = $base;
$parts = explode("->", $str);
foreach ($parts as $p) {
$out = $out->$p;
}
return $out;
}
getRef($x, "a->b");
That will not work. Are you trying to use xpath?
http://www.php.net/manual/en/simplexmlelement.xpath.php
I know how to use simplexml_load_file to get XML results if the XML format is
<bowlcontents>
<banana>yellow</banana>
<apple>red</apple>
</bowlcontents>
However, I have some code that is in the format
<bowlcontents>
<fruit type="banana" skin="yellow" />
<fruit type="apple" skin="red" />
</bowlcontents>
and I want to manipulate it in the same way as in the first example. How would I do this?
EDIT: This is precisely what I want to do, yet the code below doesn't work.
<?php
$url = "http://worldsfirstfruitAPI.com/fruit.xml";
$xml = (simplexml_load_file($url));
$results = array();
foreach ($xml->bowlcontents->fruit as $fruit) {
$results[] = array(
$fruit['type'] => $fruit['skin'],
);
}
return $results;
}
?>
So at the end of it I would like to have an array, key=value:
banana=yellow
apple=red
...
I hope this clarifies. Thanks!
As per PHP's manual, attributes are accessed using the array notation:
$bowlcontents->fruit['type'];
Come to think of it, you didn't say in your question what was your problem. If that's about iterating over nodes, you can do it using foreach.
/*
$bowlcontents = simplexml_load_string(
'<bowlcontents>
<fruit type="banana" skin="yellow" />
<fruit type="apple" skin="red" />
</bowlcontents>'
);
*/
$url = "http://worldsfirstfruitAPI.com/fruit.xml";
$bowlcontents = simplexml_load_file($url);
foreach ($bowlcontents->fruit as $fruit)
{
echo $fruit['type'], "'s skin is ", $fruit['skin'], "<br/>\n";
}
How do i convert an associate array to an XML string? I found this but get the error 'Call to a member function addChild() on a non-object' when running the line
$node = $xml->addChild($key);
Use the PHP Document Object Model:
$xml = new DOMDocument('1.0', 'utf-8');
$root = $xml->createElement('top');
$xml->appendChild($root);
foreach ($arr as $k => $v) {
$node = $xml->createelement($k);
$text = $xml->createTextNode($v);
$node->appendChild($text);
$root->appendChild($node);
}
echo $xml->saveXml();
Did you initialize the $xml object? That's probably your problem.
Its pretty similar to how you would do something like this:
while($row = mysql_fetch_assoc($result))
You can't use $result as an array, but you can foreach or while through the different entries.
PEAR's XML_Serialize is pretty good if you want a easy solution. Doing the DOM manually is arguably faster.