PHP Simple XML Parse Attributes - php

I have an XML file with data stored like this:
<myxml>
<item name="column18">88744544</item>
<item name="column11">47884994</item>
<item name="column3">44788894</item>
</myxml>
I need to first check (and be sure that) column11 is defined (there is no particular order), and then get its value.
Using simple XML is not seeming to work.
I have the following, but the value is missing.
<?php
if (count($xml->myxml->item) > 0)
{
foreach ($xml->myxml->item as $item)
{
var_dump($item->attributes());
}
}
?>
$item->attributes()->column11 doesn't work.

Dont include the opening tabs and attributes. For example:
<?php
if (count($xml->item) > 0)
{
foreach ($xml->item as $item)
{
var_dump($item); //For the info
echo $item['name']; //if you needed the name
}
}
?>

Try XPath.
if ($xml->xpath('//item[#name="column11"]'))
{
echo 'exists';
}

Related

How do I fix this PHP code?

I have to create a live search on a website. I have to use PHP, but I have never studied it and I am pretty much a beginner in programming.
I have an XML-file as a database and the aim is to get node values and display them as suggestions as a user types in something. The problem with this code is that it spits out all of the node values onto the web page.
Here is the PHP code:
<?php
$xmlDoc = new DOMDocument();
$xmlDoc->load("collection.xml");
$books = $xmlDoc->getElementsByTagName("book");
$q = $_GET["q"];
if (strlen($q) > 0) {
$hint = "";
foreach ($books as $book) {
$name = $book->getElementsByTagName("name")->item(0)->nodeValue;
echo "$name <br/>";
}
}
if ($hint == "")
{
$response="no suggestion";
}
else
{
$response=$hint;
}
//output the response
echo $response;
?>
Here is the XML-file:
<books>
<book>
<name>Harry Potter</name>
<quantity> 50 </quantity>
<price>19.90</price>
</book>
<book>
<name>Casino Royale</name>
<quantity> 50 </quantity>
<price>12.99</price>
</book>
<book>
<name>The Great Gatsby</name>
<quantity> 40 </quantity>
<price>14.90</price>
</book>
</books>
Can someone please help me fix this issue so that I can continue working on my project. Thank you in advance for your time and help! Aprreciate it a lot!
The issue is here:
$hint = "";
foreach ($books as $book) {
$name = $book->getElementsByTagName("name")->item(0)->nodeValue;
echo "$name <br/>";
}
Notice that you have a "foreach loop" here. The "$name=$book...." line simply reads the value of that particular XML node and assigns it to the $name variable. Then you are doing a call to echo $name. So in essence, all you're doing here is reading the value of the XML node and printing it. No part of your code compares the $name to your search query ($q). It seems that what you want to happen is only print out books that somehow match $q.
In order to do that we need to apply some logic to your foreach loop to only print out values that match $q.
Here is a suggestion:
$hint = "";
foreach ($books as $book) {
$name = $book->getElementsByTagName("name")->item(0)->nodeValue;
// Let's only show this book if $q appears somewhere in $name.
if (strpos($name, $q) !== false && strpos($name, $q) >= 0)
{
echo $name . "<br />";
}
}

PHP Invalid argument supplied for foreach() when getting RSS

I seem to be having trouble accessing a portion of an RSS feed. I have read this article: Accessing date as XML node in PHP and Problem getting author from a wordpress RSS feed using SimpleXmlElement article but I still cannot seem to get this to work.
<item>
<title>This is the title</title>
<dc:creator>!an (#myHandle)</dc:creator>
<description><![CDATA[<p class="TweetTextSize js-tweet-text tweet-text" lang="en">What is this tweeet</p>]]></description>
<pubDate>Tue, 03 Jan 2017 22:01:54 +0000</pubDate>
<guid>1234567</guid>
<link>1234567</link>
<twitter:source/>
<twitter:place/>
</item>
here is the portion of the rss I am getting. Here is the full RSS: https://twitrss.me/twitter_search_to_rss/?term=test+this+feed
I am trying to access this with PHP code like so:
$feed = new DOMDocument();
$feed->load('https://twitrss.me/twitter_search_to_rss/?term=test+this+feed');
foreach ($feed->getElementsByTagName('channel')->item(0) as $item) {
$ns_dc = $item->children('http://purl.org/dc/elements/1.1/');
echo $ns_dc->creator;
}
but I keep getting this error:
Invalid argument supplied for foreach()
I have tried changing it to:
$feed->getElementsByTagName('channel')->item(0)
but then nothing outputs.
I also tried:
$feed->getElementsByTagName('channel')
but then get the error:
Call to undefined method DOMElement::children()
Question
Please can someone tell me, using PHP how to access the dc:creator tag and assign that value to a variable?
Edit
$i = 1;
foreach ($feed->channel as $row) {
echo $i;
foreach ($row->children() as $key => $val) {
if ($key == "item") {
if ($i == 1) {
$ns_dc = $val->children('http://purl.org/dc/elements/1.1/');
echo $ns_dc->creator;
}
}
}
$i = $i + 1;
}
Since you are dealing with XML content, I found it easier to use SimpleXML instead of DOMDocument. Since each <item> is in the same block as channel you can do a foreach looking for a key of item.
$feed = simplexml_load_file('https://twitrss.me/twitter_search_to_rss/?term=test+this+feed');
foreach ($feed->channel as $row) {
foreach ($row->children() as $key => $val) {
if ($key == "item") {
$ns_dc = $val->children('http://purl.org/dc/elements/1.1/');
echo $ns_dc->creator;
}
}
}
This code outputs the "creator" string you expect.

simplexml_load_file with <m:properties> [duplicate]

The xml data looks like this:
<feed>
<entry>
<abc:rank scheme="http://foo.bar">45</abc:rank>
<abc:rank scheme="http://foo2.bar">88</abc:rank>
</entry>
<entry>
<abc:rank scheme="http://foo.bar">125</abc:rank>
<abc:rank scheme="http://foo2.bar">32</abc:rank>
</entry>
</feed>
I am able to output all of these entries with this code:
foreach($xml->entry[$i]->children('abc', true) as $a) {
echo $a;
}
However, if I want to get the one with the content "88" in the first entry, something like
foreach($xml->entry[$i]->children('abc', true) as $a) {
if($a["scheme"] == "http://foo2.bar")
echo $a;
}
does not work.
How can I select these children depending on their attribute?
Ok I got it by now. For those interested in the correct solution:
$namespaces = $xml->entry[$i]->getNameSpaces('true');
$abc= $xml->entry[$i]->children($namespaces['abc']);
foreach($abc->rank as $a) {
$scheme = $a->attributes();
echo $scheme['scheme'];
echo " - ";
}

Not displaying array elements by index

I wrote a php code for retrieving some data from a XML file into a variable.
This is the XML file:
<Server>
<Server1>
<ipaddress>10.3.2.0</ipaddress>
<rootpassword>abcd</rootpassword>
<port>22</port>
<autousername>abcd</autousername>
<autopassword>abcd</autopassword>
</Server1>
<Server1>
<ipaddress>10.3.2.1</ipaddress>
<rootpassword>abcd</rootpassword>
<port>22</port>
<autousername>abcd</autousername>
<autopassword>abcd</autopassword>
</Server1>
<Server1>
<ipaddress>10.3.2.2</ipaddress>
<rootpassword>abcd</rootpassword>
<port>22</port>
<autousername>abcd</autousername>
<autopassword>abcd</autopassword>
</Server1>
<Server1>
<ipaddress>10.3.2.3</ipaddress>
<rootpassword>abcd</rootpassword>
<port>22</port>
<autousername>abcd</autousername>
<autopassword>abcd</autopassword>
</Server1>
</Server>
This is the PHP code:
$x = $xmlDoc->getElementsByTagName("ipaddress");
Here i want to display the content of $x by index value, something like
echo $x[0]->nodeValue;
How could I do that?
I assume you used DOMDocument for the XML parsing. When invoking getElementsByTagName you will receive a DOMNodeList not an array.
DOMNodeList implements Traversable so it can be used in foreach loops.
foreach ($x as $item) {
var_dump($item->nodeValue);
}
If you just want a specific item use the item method.
$x->item(0)->nodeValue;
You can access ipaddress like below.
$xml = simplexml_load_file("yourxml.xml");
$result = $xml->xpath('//Server1');
foreach($result as $item){
echo "IP Address:".$item->ipaddress
echo "<br/>";
}
The demo.
$xml = simplexml_load_file($path_to_your_xml_file);
foreach($xml->Server1 as $server) {
echo $server->ipaddress . '<br>';
}
Or you could just do:
echo $xml->Server1[0]->ipaddress;

Select some but not all child nodes

I have the following XML structure:
<?xml version="1.0" encoding="ISO-8859-1"?>
<articles>
<article id="1">
<title>Article title 001</title>
<short>Short text</short>
<long>Long text</long>
</article>
<article id="2">
<title>Article title 002</title>
<short>Short text</short>
<long>Long text</long>
</article>
</articles>
I want to select only <title> and <short>.
Currently using this to display everything:
$queryResult = $xpathvar->query('//articles/article'); // works fine grabs all articles
foreach($queryResult as $result){
echo $result->textContent;
}
The expected output would be:
Article title 001
Short text
Any assistance would be greatly appreciated.
Working solution!
if ($artId == "") {
$queryResult = $xpathvar->query('//articles/article/*'); // grab all children
foreach($queryResult as $result){
if($result->nodeName === 'title' || $result->nodeName === 'short') {
echo $result->textContent;
}
}
}else{
$queryResult = $xpathvar->query(sprintf('//articles/article[#id="%s"]/*', $artId)); // Show requested article
foreach($queryResult as $result){
if($result->nodeName === 'title' || $result->nodeName === 'long') {
echo $result->textContent;
}
}
}
You can use
/articles/article/*[name()="title" or name()="short"]
which would only return children of any "articles/article" with an element name of "title" or "short".
As an alternative, change the XPath to /articles/article/* to fetch all childNodes of article and when iterating $results check if DOMNode::nodeName is "title" or "short", e.g.
$queryResult = $xpathvar->query('/articles/article/*'); // grab all children
foreach($queryResult as $result){
if($result->nodeName === 'title' || $result->nodeName === 'short') {
echo $result->textContent;
}
}
If you dont want to change the XPath, you have to iterate the childNodes of the article, e.g.
$queryResult = $xpathvar->query('/articles/article');
foreach($queryResult as $result) {
foreach($result->childNodes as $child) {
if($child->nodeName === 'title' || $child->nodeName === 'short') {
echo $child->textContent;
}
}
Use:
/*/*/*[self::title or self::short]
or if the title and short children of a specific article with known #id (say '2') should be displayed:
/*/article[#id='2']/*[self::title or self::short]
Always try to avoid using the // abbreviation when this is possible (when the structure of the XML document is known).
Using // very often results in grossly-inefficient evaluation, because // causes the whole (sub) tree rooted in the current node to be searched.

Categories