I have two xml files that look like this:
First:
<numbers>
<line><value>a1</value></line>
<line><value>a2</value></line>
<line><value>a3</value></line>
</numbers>
Second:
<numbers>
<line><value>b1</value></line>
<line><value>b2</value></line>
<line><value>b3</value></line>
</numbers>
Right now I have double foreach loops (I know it should be something else, for loop maybe?)
$xmldata = simplexml_load_file('file.xml');
$xmldata2 = simplexml_load_file('file2.xml');
foreach($xmldata->line as $item){
foreach($xmldata2->line as $item2){
echo $item->value;
echo $item2->value. "</p>";
}
}
But the output is this:
a1b1
a1b2
a1b3
a2b1
a2b2
a2b3
a3b1
a3b2
a3b3
Should be:
a1b1
a2b2
a3b3
Not sure of the logic but this would achieve what you say you want to achieve.
$xmldata = simplexml_load_file('file.xml');
$xmldata2 = simplexml_load_file('file2.xml');
$key = 0;
foreach($xmldata->line as $item){
echo '<p>';
echo $item->value;
echo $xmldata2->line[$key]->value;
echo "</p>";
$key++;
}
RESULT
<p>a1b1</p>
<p>a2b2</p>
<p>a3b3</p>
But if it is possible that the 2 xml files may not be the same length this might be safer.
$xmldata = simplexml_load_file('file.xml');
$xmldata2 = simplexml_load_file('file2.xml');
// only loop for the number of occurances in the smallest xml file
$max = count($xmldata) >= count($xmldata2) ? count($xmldata2) : count($xmldata);
for ($key=0; $key < $max; $key++){
echo '<p>';
echo $xmldata->line[$key]->value;
echo $xmldata2->line[$key]->value;
echo "</p>";
}
Related
I am newer to PHP and I am able to get the desired output but I am doing it one index position at a time. I am returning data from a .txt file and I need to insert this data into an HTML table I am creating using PHP. BUT FIRST I need to be able to get the same output without typing out every index position. I tried to use a forloop but it kept outputting only one line.
I manually outputted the lines from the file and it works. What loop in PHP would be best to achieve the same results and output these elements? IMPORTANT, as is I am able to sort and rsort (I want to be able to do this so if it can be implemented in the loop that would be awesome) any help is more than I have right now.
PHP
$books = array();
if ($fp)
{
while(true)
{
$lines_in_file = count(file($filename));
$line = fgets($fp);
if (feof($fp))
{
break;
}
$line_ctr++;
list($title, $author, $pubdate, $isbn) = explode('*', $line);
$new_line = explode('*', $line);
for($ii= 1; $ii <= $lines_in_file; $ii++){
$lines = fgets($fp); //Read each line
$member = trim($lines);
array_push($books, $member);
}
//This foreach only brings back the first like in the txt file, why?
$cntr = 0;
foreach($books as $element){
$cntr++;
$table .= "<tr>";
$table .= "<td>".$title."</td>";
$table .= "<td>".$author."</td>";
$table .= "<td>".$pubdate."</td>";
$table .= "<td>".$pubdate."</td>";
$table .= "<td>".$isbn."</td>";
$table .= "</tr>\n"; //added newline
echo $element;
}
//sort($books);
// rsort($books);
echo $books[0];
echo "<br>";
echo $books[1];
echo "<br>";
echo $books[2];
echo "<br>";
echo $books[3];
echo "<br>";
echo $books[4];
echo "<br>";
echo $books[5];
echo "<br>";
echo $books[6];
echo "<br>";
echo $books[7];
echo "<br>";
echo $books[8];
echo "<br>";
echo $books[9];
echo "<br>";
echo $books[10];
echo "<br>";
echo $books[11];
echo "<br>";
echo $books[12];
echo "<br>";
echo $books[13];
echo "<br>";
echo $books[14];
echo "<br>";
echo $books[15];
echo "<br>";
echo $books[16];
echo "<br>";
echo $books[17];
}//END WHILE LOOP
fclose($fp ); //Close file
}
Having to make a few guesses here but i believe the file is going to look like:
title*author*pubdate*isbn
title*author*pubdate*isbn
title*author*pubdate*isb
if this is wrong, let me know
as long as the fie is not to large read it in to an array:
$book_array=file('book_file.txt');
//print_r($book_array); //is it an array of the books, one book per array key
now to separate each line:
foreach($book_array as $line){
$line_sep=explode('*',$line);
// with no sorting option you could just echo inside the loop
//if you want to keep sorting options we have to keep the separated lines
$new_book_array[]=$line_sep;
}
unset($book_array);//free up memory if needed
//print_r($new_book_array);//is it a multi-d array, book then the 4 elements
to sort our new multidimensoanl array:
usort($new_book_array, function($a, $b) {
return strcmp($a['0'], $b['0']);;
}); //this sorts on key 0 in your case title:
//print_r($new_book_array); // has it sorted properly
for display:
loop again
echo '<table><tr><th>Title</th><th>Author</th><th>Pub Date</th><th>ISBN</th></tr>';
foreach($new_book_array as $book){
//print_r($book); //is it each indervidual book array with 4 elements
echo '<tr><td>'.$book[0].'</td><td>'.$book[1].'</td><td>'.$book[2].'</td><td>'.$book[3].'</td></tr>';
}
echo '</table>';
I am having a hard time trying to understand why I can't compare the values of two arrays in PHP. If I echo both of these during the loop using "echo $description->ItemDesriptionName;" and "echo $item->ItemName;" the values seem to show as the same, but when I try to compare them using if, nothing works. What am I missing?
<?php
$xml=simplexml_load_file("test.xml") or die("Error: Cannot create object");
$categories = $xml->Menu->Categories;
$items = $xml->Menu->Categories->Items->ItemObject;
$itemdescription = $xml->Menu->Options->Description->DescriptionObject;
foreach($items as $item) {
echo $item->ItemName . ' - ' . $item->Price . '</br>';
foreach ($itemdescription as $description) {
if ($description->ItemDescriptionName == $item->ItemName) {
echo 'We have a match!';
//where I would echo $description->ItemDescription;
}
}
}
?>
Here is the XML file
<?xml version="1.0" encoding="utf-8"?>
<Root>
<Menu>
<Categories>
<Name>Category 1</Name>
<Items>
<ItemObject>
<ItemName>Item 1</ItemName>
<Price>1</Price>
</ItemObject>
<ItemObject>
<ItemName>Item 2</ItemName>
<Price>3</Price>
</ItemObject>
</Items>
</Categories>
<Options>
<Description>
<DescriptionObject>
<ItemDescriptionName>Item 1</ItemDescriptionName>
<ItemDescription>A Great item</ItemDescription>
</DescriptionObject>
<DescriptionObject>
<ItemDescriptionName>Item 2</ItemDescriptionName>
<ItemDescription>A Great item as well</ItemDescription>
</DescriptionObject>
</Description>
</Options>
</Menu>
</Root>
compare as string
and you have typo in ItemDescriptioName (ItemDescriptionName)
if ( (string)$description->ItemDescriptionName == (string)$item->ItemName) {
Convert to string and then compare
<?php
$xml=simplexml_load_file("test.xml") or die("Error: Cannot create object");
$menu = $xml->Menu;
$categories = $xml->Menu->Categories;
$items = $xml->Menu->Categories->Items->ItemObject;
$itemdescription = $xml->Menu->Options->Description->DescriptionObject;
foreach($items as $item) {
$itemname = $item->ItemName;
foreach ($itemdescription as $description) {
$descriptionname = $description->ItemDescriptionName ;
echo $itemname." ---- ".$descriptionname."<br/>";
if((string)$itemname === (string)$descriptionname){
echo "Yes its matched";
}
}
}
?>
Working fine for me
The properties like $description->ItemDescriptionName are SimpleXMLElement objects. So you do not compare strings but two objects.
SimpleXMLElement objects implement the magic method __toString(). They can be cast to string automatically, but a compare between to objects will not trigger that. You can force it:
if ((string)$description->ItemDescriptionName === (string)$item->ItemName) {
...
Can you access them directly instead using an accordant index?
...
$items = $xml->Menu->Categories->Items->ItemObject;
$itemdescription = $xml->Menu->Options->Description;
$i = 0;
foreach ($items as $item) {
echo $i.' '.$item->ItemName . ' - ' . $item->Price;
echo $itemdescription->DescriptionObject[$i]->ItemDescriptionName[0];
echo ' ';
echo $itemdescription->DescriptionObject[$i]->ItemDescription[0];
echo '</br>';
$i++;
}
Ive been trying make this display as html list items it just a string that i explode then loop over each item i cant get it to out put correctly. Could some one please show me where im going wrong or suggest an new approch.
this is what ive tried
$path = "1/2/3/4";
$expath = explode("/",$path);
$ret = '';
echo '<ul>';
foreach ($expath as $pitem) {
echo '<li><a href='.$ret .= $pitem. "/".'>'.$pitem.'</a></li>';
}
echo '</ul>';
.
Desired out put on hrefs
1
1/2
1/2/3
1/2/3/4
Desired visual out LIs
1
2
3
4
Output i get be warned
1
12/>212/>23/>312/>23/>34/>4
$path = "1/2/3/4";
$expath = explode("/", $path);
echo '<ul>';
foreach ($expath as $i => $pitem) {
$slice = array_slice($expath, 0, $i + 1);
$path = implode('/', $slice);
echo '<li>' . $pitem . '</li>';
}
echo '</ul>';
$list = explode("/", "1/2/3/4");
This will create an array $list as:
echo $list[0]; // 1
echo $list[1]; // 2
echo $list[2]; // 3
echo $list[3]; // 4
This line is the problem: echo '<li><a href='.$ret .= $pitem. "/".'>'.$pitem.'</a></li>';
Should be formatted like:
echo "<li><a href='{$ret}={$pitem}/'>{$pitem}</a></li>";
or echo '<li>'.$pitem.'</li>';
Its because your $ret. Place that inside the loop. In your code you concatenate $pitem with $ret all older $ret values also get concat.
Try
<?php
$path = "1/2/3/4";
$expath = explode("/",$path);
echo '<ul>';
foreach ($expath as $pitem) {
$ret = '';
echo '<li><a href='.$ret .= $pitem. "/".'>'.$pitem.'</a></li>';
}
echo '</ul>';
If you want = sign tobe there in the url then just change echo by following
echo "<li><a href='$ret=$pitem/'>$pitem</a></li>";
PHP echo with double quotes will print variable value.
I have this code:
foreach($html->find('ul.results') as $article) {
$item['date'] = $article->find('span.result_date', 0)->plaintext;
$item['title'] = $article->find('a.result_title', 0);
$item['text'] = $article->find('span.result_text', 0)->plaintext;
$item['read'] = $article->find('a.read_more', 0);
$articles[] = $item;
}
foreach ($articles as &$item) {
while ($i < 5) {
echo $item['date']." ";
echo $item['title'].'</br>';
echo $item['text']." ";
echo $item['read'].'</br></br>';
$i++;
}
}
And I am trying to echo the results. Right now the second foreach isn't doing anything. It is just displaying five of the same articles. The articles are in the format of: date, title, text, read more. I am trying to eco the first five $articles, but I can't find a proper way to do so that isn't print_r.
The whole loop inside the for each will just loop on the first element 5 times, move to the next element and loops 5 times, etc.
Try something like this:
$i = 0;
foreach ($articles as $item){
echo items stuff...
$i++;
if ($i == 5) break;
}
I have inherited some PHP code (but I've little PHP experience) and can't find how to count some elements in the object returned by simplexml_load_file()
The code is something like this
$xml = simplexml_load_file($feed);
for ($x=0; $x<6; $x++) {
$title = $xml->channel[0]->item[$x]->title[0];
echo "<li>" . $title . "</li>\n";
}
It assumes there will be at least 6 <item> elements but sometimes there are fewer so I get warning messages in the output on my development system (though not on live).
How do I extract a count of <item> elements in $xml->channel[0]?
Here are several options, from my most to least favourite (of the ones provided).
One option is to make use of the SimpleXMLIterator in conjunction with LimitIterator.
$xml = simplexml_load_file($feed, 'SimpleXMLIterator');
$items = new LimitIterator($xml->channel->item, 0, 6);
foreach ($items as $item) {
echo "<li>{$item->title}</li>\n";
}
If that looks too scary, or not scary enough, then another is to throw XPath into the mix.
$xml = simplexml_load_file($feed);
$items = $xml->xpath('/rss/channel/item[position() <= 6]');
foreach ($items as $item) {
echo "<li>{$item->title}</li>\n";
}
Finally, with little change to your existing code, there is also.
$xml = simplexml_load_file($feed);
for ($x=0; $x<6; $x++) {
// Break out of loop if no more items
if (!isset($xml->channel[0]->item[$x])) {
break;
}
$title = $xml->channel[0]->item[$x]->title[0];
echo "<li>" . $title . "</li>\n";
}
The easiest way is to use SimpleXMLElement::count() as:
$xml = simplexml_load_file($feed);
$num = $xml->channel[0]->count();
for ($x=0; $x<$num; $x++) {
$title = $xml->channel[0]->item[$x]->title[0];
echo "<li>" . $title . "</li>\n";
}
Also note that the return of $xml->channel[0] is a SimpleXMLElement object. This class implements the Traversable interface so we can use it directly in a foreach loop:
$xml = simplexml_load_file($feed);
foreach($xml->channel[0] as $item {
$title = $item->title[0];
echo "<li>" . $title . "</li>\n";
}
You get count by count($xml).
I always do it like this:
$xml = simplexml_load_file($feed);
foreach($xml as $key => $one_row) {
echo $one_row->some_xml_chield;
}