SimpleXml foreach : ignore element - php

<?php
$xml = "<articles>
<article id=\"18357302\">
<articleCategories>
<articleCategory id=\"default\"/>
<articleCategory id=\"66607\"/>
</articleCategories>
</article>
</articles>";
$feed = simplexml_load_string($xml);
$items = $feed->article;
foreach ($items as $article) {
// $categorie = $article->articleCategories->articleCategory[id];
$categories = $article->articleCategories;
print_r($categories);
echo "<br>print_r indeed returns an array, but impossible to echo it using foreach!!!<br>";
foreach ($categories->id as $category) {
if ($category != "default") {
echo $category;
}
}
}
?>
not sure what i am doing wrong, i am just trying to find a way to remove the part with the default value inside articlesCategories
<articleCategory id=\"default\"/>
The script needs to ignore this part and just use the next articleCategory from the XML file, and i would prefer to avoid removing it with regex

The script iterates over articleCategories tag.
But it needs to iterate over articleCategory tag.
The following changes will be enough.
foreach ($categories->articleCategory as $category) {
if ($category["id"] != "default") {
echo $category["id"];
}
}

Related

How to convert resultset to nested unordered list and hide sublist items with a value of 0?

I am trying to display the below table value in list and sub-list.
and here is my for loop to display
$sql ="SELECT *FROM objectives";
$result = $conn->query($sql);
$categories = array();
foreach ($result as $result) {
$category = $result['content'];
$categories[$category][] = $result['sub_content'];
}
?>
<ul>
<?php foreach ($categories as $category => $subcategories): ?>
<li>
<?php echo $category; ?>
<ul>
<?php foreach ($subcategories as $subcategory):?>
<li><?php echo $subcategory; ?></li>
<?php endforeach; ?>
</ul>
</li>
<?php endforeach; ?>
</ul>
The data is displayed in list and with sub list. I don't want to display the 0 value in the sub-list.
Everything is fine except the display of 0 in sub-list. Please advise.
try this if you just don't want to display 0
<?php echo ($subcategory != '0')? '<li>'.$test.'</li>' : ''; ?>
and if you don't want to store in array then put this if condition
foreach ($result as $result) {
$category = $result['content'];
if($result['sub_content'] != '0'){
$categories[$category][] = $result['sub_content'];
}
}
Simply implementing echo ($subcategory != '0')? '<li>'.$test.'</li>' : ''; will result in needless markup in the dom. Specifically, you will have empty <ul></ul> tags as nested lists where only a single row containing $subcategory is 0. (Demonstration) These extra bits of markup may cause funky side-effects when css/styling is applied.
Further refinements are advisable as a matter of best practice:
When querying the database, only SELECT the columns that you specifically require for your task.
Add stability to your process by using an ORDER BY clause that will group the rows by content and possibly sort sub_content
Never use more loops than necessary. This task can be (and therefore, theoretically, should be) performed in a single loop.
Recommended Code: (Demo)
$result = $conn->query("SELECT content, sub_content FROM objectives");
$category = null;
$output = '';
foreach ($result as $row) {
if ($category !== $row['content']) { // new parent
if ($category !== null) { // not first iteration
$output .= "<li>$category"; // print parent
if ($sublist) {
$output .= "<ul>$sublist</ul>"; // print all children
}
$output .= "</li>";
}
$category = $row['content']; // overwrite $category
$sublist = ''; // reset sublist
}
if ($row['sub_content'] !== '0'){ // filter row
$sublist .= "<li>{$row['sub_content']}</li>";
}
}
if ($result) { // in case the resultset is empty
echo "<ul>";
echo $output; // print stored markup
echo "<li>$category"; // print last parent
if ($sublist) {
echo "<ul>$sublist</ul>"; // print all children from last parent
}
echo "</li>";
echo "</ul>";
}
Source Code Output:
<ul>
<li>Demonstrate where to find the following documentation:
<ul>
<li>Operating and Safety Strategy</li>
</ul>
</li>
<li>Explain the different turbine main operating states:
<ul>
<li>Power Production</li>
<li>Idle</li>
<li>Stop</li>
</ul>
</li>
<li>Explain how to recognise the current operating mode on the display of the operating panel</li>
<li>Explain the subsystem operating modes:
<ul>
<li>Stop</li>
<li>Manual</li>
</ul>
</li>
<li>Explain the difference between local and remote point of operation</li>
<li>Explain that only one point of operation can be active at a time</li>
</ul>
Rendered Output: (courtesy of phptester.net)

Foreach in foreach [PHP]

Actually I work with PHP framework Codeigniter and I want to compare value from first foreach to second one, but I'm getting an error. Example here:
<?php foreach($posts->result() as $post): ?>
(html content)
<?php foreach($tags->result() as $tag) {
if($tag->id_users == $post->id_users) echo $tag->tag_name;
} ?>
(html content)
<?php endforeach; ?>
When I compare $post->id_users inner second foreach I'm getting error, how can I get around this?
Its better to avoid loop inside a loop
$tag_ids = array();
foreach($tags->result() as $tag) {
$tag_ids[] = $tag->id_users;
}
foreach ($posts->result() as $key => $post) {
if(in_array($post->id_users, $tag_ids)) {
}
}
You don't close the second foreach. For eg
<?php foreach($posts->result() as $post): ?> foreach1
(...some html)
<?php foreach($tags->result() as $tag) { if($tag->id_users == $post->id_users) echo $tag->tag_name; } ?> //foreach2
(...some html)
<?php endforeach; ?>
<?php endforeach; ?>
You should not use $posts->result() and $tags->result() inside foreach loop. Because it will go to check for every time while foreach is live.
Overall it decrease the performance of script.
<?php
$posts = $posts->result();
$tags = $tags->result();
foreach($posts as $post) {
?>
<< Other HTML code goes here >>
<?php
foreach($tags as $tag) {
if($tag->id_users == $post->id_users) {
echo $tag->tag_name;
}
?>
<< Other HTML code >>
<?php
}
}

How to highlight current link in foreach loop

I have a script that lists all the directories as links.
<?php
$dirs = array_filter(glob('../*'), 'is_dir');
?>
<ul style="float:left;">
<?php
foreach ($dirs as $nav) {
echo "<li><a href='$nav'>".basename($nav)."</a></li>";
}
?>
</ul>
I want to highlight the current directory, or give the current link a class or id. I understand that i need if statement to accomplish this like if(currentLink=thisLink) { // add span class somehow} else {// continue looping} , but I am not completely sure how to do this.
What would be the correct way to implement this ?
Yes you are right you need if condition in your loop.
Save your current link in a variable before loop.
<?php
$dirs = array_filter(glob('../*'), 'is_dir');
?>
<ul style="float:left;">
<?php
$currentlink='abc';
foreach ($dirs as $nav) {
if($nav==$currentlink)
$class='current';
else
$class='';
echo "<li><a class='$class' href='$nav'>".basename($nav)."</a></li>";
}
Without knowing the variables to compair, syntax wise you want to do something like this
<?php
foreach ($dirs as $nav){
$class = '';
if( $currentLink == $thisLink ) {
$class = 'class="highlight"';
}
echo '<li><a href="'.$nav.'" '.$class.' >'.basename($nav).'</a></li>';
}
?>
You can look in $_SERVER to get the current url in the browser and use some of that and the basename to fill those variables in.
http://php.net/manual/en/reserved.variables.server.php
to find out the current directory name you need:
basename(getcwd())
in foreach loop use this:
if(basename($nav) == basename(getcwd()))
{
// add span class
}
First you have to get current link. Store as $current_link
<?php
$dirs = array_filter(glob('../*'), 'is_dir');
$current_dir = 'store current directory here';
?>
<ul style="float:left;">
<?php
foreach ($dirs as $nav) {
if($nav == $current_dir) {
$class_name = 'active';
}
else {
$class = '';
}
echo "<li class='$class'><a href='$nav'>".basename($nav)."</a></li>";
}
?>
</ul>
Hope it will works.

XPATH Get Attribute of Current Node

Having trouble getting the attribute of the current node in PHP and making a condition based on that attribute...
Example XML
<div class='parent'>
<div class='title'>A Title</div>
<div class='child'>some text</div>
<div class='child'>some text</div>
<div class='title'>A Title</div>
<div class='child'>some text</div>
<div class='child'>some text</div>
</div>
What I am trying to do is traverse the XML in PHP and do different things based on the class of the element/node
Eg.
$doc->loadHTML($xml_string);
$xpath = new DOMXpath($doc);
$nodeLIST = $xpath->query("//div[#class='parent']/div");
foreach ($nodeLIST as $node) {
if (CURRENT DIV NODE ATTRIBUTE EQUALS TITLE) {
SET $TITLE VARIABLE TO THE TEXT() OF THE CURRENT NODE
}
ELSEIF(CURRENT DIV NODE ATTRIBUTE EQUALS CHILD){
SET $CHILD VARIABLE TO THE TEXT() OF THE CURRENT NODE
}
}
I've tried all kind of things like the following...
if ($xpath->query("./[#class='title']/text()",$node)->length > 0) { }
But all i keep getting is PHP errors saying that my XPATH syntax is not valid. Can anyone help me?
You can achieve this by using getAttribute() method. Example:
foreach($nodeLIST as $node) {
$attribute = $node->getAttribute('class');
if($attribute == 'title') {
// do something
} elseif ($attribute == 'child') {
// do something
}
}
$node->getAttribute('class') gives you the attribute value, $node->textContent the string contents of the node. I wouldn't dive into XPath to read out the string value.
You can filter the 'title' and 'child' sets in different nodelists:
$titles = $xpath->query("//div[#class='parent']/div[#class='title']");
$children = $xpath->query("//div[#class='parent']/div[#class='child']");
And then process them separately:
foreach ($titles as $title) {
echo $title->textContent."\n";
}
foreach ($children as $child) {
echo $child->textContent."\n";
}
See: http://codepad.viper-7.com/x4LA50

PHP + RSS duplicate elements

Im using this PHP to get a list of Title's from an RSS feed:
<?php require_once('magpie/rss_fetch.inc');
$rss = fetch_rss('http://live.visitmix.com/Sessions/RSS');
foreach ($rss->items as $item) {
$cat = $item['category'];
$title = $item['title'];
echo '<li class="'.$cat.'">'.$title.'</li>';
}
?>
I want to use <category> and add it as the class, however the <category> element appears for each <item> 1,2,3,4 or more times depending on the Title. How can I take the category element and seperate each category with a space if there is more than 1?
what about accumulating the categories in an array and then implode the array?
$categoriesArray = array();
foreach ($rss->items as $item) {
array_push($categoriesArray, $item['category']);
}
$categories = implode(" ", $categoriesArray);
EDIT TO ADD
If the categories are cumulated, you can try something like this:
$categoriesByTitle = array();
foreach ($rss->items as $item) {
$currentTitle = $item['title'];
$categories = $categoriesByTitle[$currentTitle];
if ($categories == NULL) {
$categories = array();
$categoriesByTitle[$currentTitle] = $categories;
}
if (!in_array($item['category'], $categories)) {
array_push($categories, $item['category']);
}
}
foreach ($categoriesByTitle as $title=>$category) {
// use implode for each title
$categoryString = implode(" ", $category);
echo '<li class="'.$categoryString.'">'.$title.'</li>';
}
Check this reference for arrays, it could be very useful for dealing with this kind of problems

Categories