Load XML file and load content - php

Hi I am trying to load content from an XML file called articles.xml:
It has and as the elements.
<?xml version="1.0"?>
<RecentArticles>
<Article author="The Reddest">
<Title>Silverlight and the Netflix API</Title>
<Date>1/13/2009</Date>
<Description>Description</Description>
<Link></Link>
</Article>
<Article author="The Hairiest">
<Title>Cake PHP 4 - Saving and Validating Data</Title>
<Date>1/12/2009</Date>
<Description>Description</Description>
<Link></Link>
</Article>
<Article author="The Tallest">
<Title>Silverlight 2 - Using initParams</Title>
<Date>1/6/2009</Date>
<Description>Description</Description>
<Link></Link>
</Article>
<Article author="The Fattest">
<Title>Controlling iTunes with AutoHotkey</Title>
<Date>12/12/2008</Date>
<Description>Description</Description>
<Link></Link>
</Article>
</RecentArticles>
This is the following PHP code I am using to print the elements into the table:
<!--Make table and print each xml element into it-->
<center>
<table border="1">
<tr>
<th>Title</th>
<th>Date</th>
<th>Description</th>
<th>Link</th>
</tr>
<?php
//Load the xml file int a variable for use in the table below.
$xml = simplexml_load_file("articles.xml");
echo("<tr>");
foreach ($xml->RecentArticles->Article as $entry)
{
$title = $entry['Title']
$date = $entry['Date'];
$description = $entry['Description'];
$link = $entry['Link'];
echo("<td>$title</td>");
echo("<td>$date</td>");
echo("<td>$description</td>");
echo("<td>$link</td>");
}
echo("</tr>");
?>
</table>
</center>
However nothing is printing into the table.. does anyone have any idea why?

You are accessing a (non-existent) attribute value rather than the node value for your content.
Access "Title" attribute value on the "Article" node:
$title = $entry['Title']
Access "Title" node value:
$title = $entry->Title
Example XML:
<RecentArticles>
<Article author="The Reddest" Title="This is what you are accessing with $entry['Title']">
<Title>This is what you should be accessing with $entry->Title</Title>
<Date>1/13/2009</Date>
<Description>Description</Description>
<Link></Link>
</Article>
</RecentArticles>
See this documentation for more information on how to access XML elements.

Related

Using xpath to query XML in PHP

I am using xpath for the first time to query an xml document for a value and return the corresponding name value. I have been reading numerous different sources on the topic but I can't seem to get it to output correctly. Here is my XML:
<?xml version="1.0" encoding="utf-8"?>
<books>
<book>
<name>Genesis</name>
<abrv>GEN</abrv>
<title>The First Book of Moses</title>
</book>
<book>
<name>Exodus</name>
<abrv>EXO</abrv>
<title>The Second Book of Moses</title>
</book>
<book>
<name>Leviticus</name>
<abrv>LEV</abrv>
<title>The Third Book of Moses</title>
</book>
</books>
Here is my PHP/HTML:
<?php $root = $_SERVER['DOCUMENT_ROOT'] . "/";
$bookID = 'GEN';
$xml = simplexml_load_file( $root . 'assets/xml/books.xml' ) or die( "No Page Data Found" );
$bookName = $xml->xpath( '//book[abrv="'.$bookID.'"]/name' );
?>
<article id="verseOfDay">
<div class="container">
<h2>verse of the day</h2>
<h6><?php echo $bookName; ?></h6> // Line 19
<p></p>
</div>
</article>
Finally, here is the notice that I am receiving:
NOTICE: ARRAY TO STRING CONVERSION IN /HOME/#####/MYWEBSITE.COM/ASSETS/INCLUDES/VERSEOFTHEDAY.PHP ON LINE 19
ARRAY
What am I doing wrong? In this example I am expecting it to output Genesis in the tag.
The SimpleXML xpath function returns an array of results, which will be empty if no result is found. So you need to check for that, and if you get a result, it will be at $bookName[0]. Something like this will work:
$bookNames = $xml->xpath( '//book[abrv="'.$bookID.'"]/name' );
$bookName = empty($bookNames) ? 'Not Found' : $bookNames[0];
?>
<article id="verseOfDay">
<div class="container">
<h2>verse of the day</h2>
<h6><?php echo $bookName; ?></h6>
<p></p>
</div>
</article>
Demo on 3v4l.org

Looping through multiple images in xml file with php code

Below is my PHP code and XML file, I have been trying with so many different echos to loop through my images in my XML file to display each image to correct product but can only display the first image to all three products.
XML code:
<my_products>
<product>
<id>1</id>
<image> csuT.jpg</image>
<name>Champion T-Shirt</name>
<price>18.00</price>
<description>
Get the perfect look to let everyone know you are a stylish fan!
</description>
</product>
<product>
<id>2</id>
<image> webBook.jpg</image>
<name>C# Programming: Analysis to Program Design</name>
<price>192.00</price>
<description>
Your hands-on guide to Microsoft Visual C# fundamentals with Visual Studio 2017
</description>
</product>
<product>
<id>3</id>
<image> calcPic.jpg</image>
<name>Calculator TI-BAII Plus 10DIG/24CASH</name>
<price>39.00</price>
<description>
Performs common math as well as various financial functions
</description>
</product>
</my_products>
PHP code:
$xml = simplexml_load_file($file);
$script_images="";
$script_products="";
$script_product_prices="";
//Loop through the products defined in the products.xml file
foreach ($xml->product as $r)
{
$script_images.="products[".($r->id)."]=\"".($r->image)."\";\n";
$script_products.="products[".($r->id)."]=\"".($r->name)."\";\n";
$script_product_prices.="product_prices[".($r->id)."]=\"".($r->price)."\";\n";
?>
<div>
<p class="lead">
<h3 class="pull-right no-top-margin"><?php echo $currency_symbol;?><?php echo $r->price;?></h3>
<h3><?php echo "<image src='csuT.jpg' 'calcPic.jpg' 'webBook.jpg'/>";?></h3>
</p>
<h3><?php echo $r->name;?></h3>
</p>
<p>
<?php echo $r->description;?>
</p>
<br/>
<?php
//If there is details link set for the product, show a Details button
if(trim($r->details_link)!="")
{
?>
<a target="_blank" href="http://<?php echo str_replace("http://","",trim($r->details_link));?>"</a>
<?php
}
?>
<a class="btn btn-xs btn-info" href="javascript:AddToCart(<?php echo $r->id;?>)">Add to Cart</a>
</div>
<hr/>
<?php
}
?>
<script>
var currency_symbol="<?php echo $currency_symbol;?>";
var products=Array();
<?php echo $script_images;?>
var product_images=Array();
<?php echo $script_products;?>
var product_prices=Array();
<?php echo $script_product_prices;?>
</script>
You just need to extract the image from the XML (the same way as done for the Javascript) and I've added a trim() to remove any spaces round the field...
<h3><?php $image = trim($r->image);
echo "<image src='$image'/>";?></h3>
Also add trim to...
$script_products.="products[".($r->id)."]=\"".($r->name)."\";\n";
What is this? :
<h3><?php echo "<image src='csuT.jpg' 'calcPic.jpg' 'webBook.jpg'/>";?></h3>
your src attribute is static and you must change it

How to read all nodes of a XML file with more than three nodes levels using PHP?

I am currently writing a PHP script to read all nodes of a XML file with more than three node levels (depth > 2). However I only could read accurately upto first level child.
I would highly appreciate, if you could let me know the error I have made while I am trying to read second level child nodes.
My xml file
<?xml version="1.0" encoding="utf-8"?>
<document nipperstudio="2.3.10.3500" xmlversion="2" xmlrevision="3">
<report>
<part index="1" title="Your Report" ref="YOURREPORT">
<section index="1.1" title="Introduction" ref="INTRODUCTION">
<text>Inside the section 1.1.:</text>
<list type="bullet">
<listitem>detailed description of list item 01;</listitem>
<listitem>detailed description of list item 02;</listitem>
</list>
</section>
<section index="1.2" title="Report Conventions" ref="REPORTCONVENTIONS">
<text>This report makes use of the text conventions.</text>
<table index="3" title="Report text conventions" ref="REPORTTEXTCONVENTIONS">
<headings>
<heading>Convention</heading>
<heading>Description</heading>
</headings>
</table>
</section>
</part>
<part index="2" title="Security Audit" ref="SECURITYAUDIT">
<section index="2.1" title="Introduction" ref="INTRODUCTION">
<text>Inside the section 2.1.:</text>
<list type="bullet">
<listitem>detailed description of list item 01;</listitem>
<listitem>detailed description of list item 02;</listitem>
</list>
<section index="2.1.1" title="Issue Overview" ref="ISSUEOVERVIEW">
<text>Inside the section 2.1.1</text>
<text title="Issue Finding">The is the body text of 2.1.1.</text>
</section>
<section index="2.1.2" title="Rating Overview" ref="RATINGSYSTEM">
<text>Inside the section 2.1.1</text>
<text title="Issue Finding">The is the body text of 2.1.1.</text>
</section>
</section>
<section index="2.2" title="section title" ref="SECTION2.2">
<section index="2.2.1" title="Finding" ref="FINDING">
<text>Inside the section 2.2.1</text>
<text title="Issue Finding">The is the body text of 2.2.1.</text>
</section>
</section>
</part>
</report>
</document>
My PHP Script is given below.
Test XML Reader
<html>
<title>Test XML Reader</title>
<body>
<p>Output from xmlreader</p>
<?php
readXmlFiles();
?>
</body>
</html>
<?php
function readXmlFiles(){
// create the reader object
$reader = new XMLReader();
// reader the XML file.
$reader->open("./fwxml/03.xml"); //open the xml file to read.
while($reader->read()) {
switch($reader->nodeType) {
case (XMLREADER::ELEMENT):
if ($reader->localName == 'report') { //read the local name of the node
$node = $reader->expand();
$dom = new DomDocument();
$n = $dom->importNode($node,true);
$dom->appendChild($n);
foreach(($dom->getElementsByTagName('part')) as $fwpart) {
$parttitle = $fwpart->getAttribute('title');
echo "=====".$parttitle."=====<br>";
foreach(($fwpart->childNodes) as $cnode){
if($cnode->nodeName == 'section'){
$index = $cnode->getAttribute('index');
$title = $cnode->getAttribute('title');
$ref = $cnode->getAttribute('ref');
echo "Index = " .$index."<br>";
echo "Title = " .$title."<br>";
echo "Ref = " .$ref."<br>";
$fwsec = $dom->getElementsByTagName('section');
echo $fwsec->item(0)->nodeValue."<br>";
echo "<br><br><br>";
}//end of if
}//end of foreach
}
}
break; //end of XMLREADER::ELEMENT
case (XMLREADER::END_ELEMENT):
// do something based on when the element closes.
break;
}
}
} //end of function
?>

how can i retrieve data from nested xml node using php?

I am new in xml and data retrieve and i have problem with this code.
XML code:
<?xml version="1.0" encoding="UTF-8"?>
<site>
<page>
<content>
<P>
<FONT size="2" face="Tahoma">
<STRONG>text...</STRONG>
</FONT>
</P>
<P>
<FONT size="2" face="Tahoma">text....</FONT>
</P>
<P align="center">
<IMG style="WIDTH: 530px" border="1" alt="" src="http://www.alkul.com/online/2014/5/6/child%20disorder.jpg">
</P>
<P>
<STRONG>
<FONT size="2" face="Tahoma">text3</FONT>
</STRONG>
</P>
<P>
<STRONG>
<FONT size="2" face="Tahoma">text1</FONT>
</STRONG>
</P>
</content>
</page>
</site>
php code:
<?php
$html = "";
$url = "Data.xml";
$xml = simplexml_load_file($url);
for ($i = 0; $i<10; $i++) {
$title = $xml->page[$i]->content->P->FONT;
$html .= "<p>$title</p>";
}
echo $html;
I just need to display the content of content node but the output is empty
First of all, the provided XML is not valid as you should receive the following error:
Warning: simplexml_load_string(): Entity: line 8: parser error : Opening and ending tag mismatch: IMG line 8 and P
In XML the IMG element needs to be closed like this:
<IMG style="WIDTH: 530px" border="1" alt="" src="http://www.alkul.com/online/2014/5/6/child%20disorder.jpg"/>
Note the forward slash at the end of the element.
If you do not see that error, please look in your error log or enable error reporting in PHP.
Now the XML can be parsed by SimpleXML. I ended up with this:
$pList = $xml->xpath('./page/content/P');
foreach ($pList as $pElement) {
$text = strip_tags($pElement->asXML());
echo $text . "<br>";
}
It selects all the P elements into $pList and iterates over the list. For each element it takes the XML and strips all tags from it, leaving you with just the "inner text" for each element.
Lastly, I'd suggest you use the PHP Simple HTML DOM Parser as it is quite easy to use and more tailored towards scraping data from HTML.
If you only want to display what is in the content node so here is your code
<?php
$html = "";
$url = "data.xml";
$xml = simplexml_load_file($url);
$title = $xml->page->content->asXML();
$html .= "<p>$title</p>";
echo $html;
You have HTML inside an XML node. This needs XML encoding, normally done with a CDATA block. You then can just use the $xml->page->content element with echo or by casting it to string.
XML (take note of the <![CDATA[ ... ]]> part):
<?xml version="1.0" encoding="UTF-8"?>
<site>
<page>
<content><![CDATA[
<P>
<FONT size="2" face="Tahoma">
<STRONG>text...</STRONG>
</FONT>
</P>
<P>
<FONT size="2" face="Tahoma">text....</FONT>
</P>
<P align="center">
<IMG style="WIDTH: 530px" border="1" alt="" src="http://www.alkul.com/online/2014/5/6/child%20disorder.jpg">
</P>
<P>
<STRONG>
<FONT size="2" face="Tahoma">text3</FONT>
</STRONG>
</P>
<P>
<STRONG>
<FONT size="2" face="Tahoma">text1</FONT>
</STRONG>
</P>
]]></content>
</page>
</site>
PHP:
$xml = simplexml_load_file($url);
$firstTenPages = new LimitIterator(new IteratorIterator($xml->page), 0, 10);
foreach ($firstTenPages as $page)
{
echo $page->content;
}

Why is my recursive loop creating too many children?

I'm using a PHP recursive loop to parse through an XML document to create a nested list, however for some reason the loop is broken and creating duplicates of elements within the list, as well as blank elements.
The XML (a list of family tree data) is structured as follows:
<?xml version="1.0" encoding="UTF-8"?>
<family>
<indi>
<id>id1</id>
<fn>Thomas</fn>
<bday></bday>
<dday></dday>
<spouse></spouse>
<family>
<indi>
<id>id1</id>
<fn>Alexander</fn>
<bday></bday>
<dday></dday>
<spouse></spouse>
<family>
</family>
</indi>
<indi>
<id>id1</id>
<fn>John</fn>
<bday></bday>
<dday></dday>
<spouse></spouse>
<family>
<indi>
<id>id1</id>
<fn>George</fn>
<bday></bday>
<dday></dday>
<spouse></spouse>
<family>
</family>
</indi>
</family>
</indi>
</family>
</indi>
</family>
And here's my PHP loop, which loads the XML file then loops through it to create a nested ul:
<?php
function outputIndi($indi) {
echo '<li>';
$id = $indi->getElementsByTagName('id')->item(0)->nodeValue;
echo '<span class="vcard person" id="' . $id . '">';
$fn = $indi->getElementsByTagName('fn')->item(0)->nodeValue;
$bday = $indi->getElementsByTagName('bday')->item(0)->nodeValue;
echo '<span class="edit fn">' . $fn . '</span>';
echo '<span class="edit bday">' . $bday . '</span>';
// ...
echo '</span>';
echo '<ul>';
$family = $indi->getElementsByTagName('family');
foreach ($family as $subIndi) {
outputIndi($subIndi);
}
echo '</ul></li>';
}
$doc = new DOMDocument();
$doc->load('armstrong.xml');
outputIndi($doc);
?>
EDIT here's the desired outcome (nested lists, with ul's signifying families and li's signifying individuals)
<ul>
<li>
<span class="vcard">
<span class="fn">Thomas</span>
<span class="bday"></span>
<span class="dday"></span>
<ul>
... repeat for all ancestors ...
</ul>
<li>
<ul>
You can see the output at http://chris-armstrong.com/gortin . Any ideas where I'm going wrong? I think it's something to do with the $subIndi value, but anytime I try and change it I get an error. Would really appreciate any help!
Sounds perfect! Could you give me an
example? Does this mean I can save the
data as XML, then load it in as nested
ul's?
Yes, you can do exactly that. Here's an XSL which renders nested UL's:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<h2>Family tree</h2>
<ul>
<li><xsl:value-of select="indi/fn" /></li>
<!-- apply-templates will select all the indi/family nodes -->
<xsl:apply-templates select="indi/family" />
</ul>
</body>
</html>
</xsl:template>
<xsl:template match="family">
<ul>
<li>
<div>
<xsl:value-of select="id" />: <xsl:value-of select="fn" />
(<xsl:variable name="bday" select="bday" />
to
<xsl:variable name="dday" select="dday" />)
</div>
</li>
<!-- This node matches the 'family' nodes, and we're going to apply-templates on the inner 'family' node,
so this is the same thing as recursion. -->
<xsl:apply-templates select="family" />
</ul>
</xsl:template>
</xsl:stylesheet>
I don't know php, but this article will show you how to transform XML using the style sheet above.
You can also link your style sheet by adding a stylesheet directive at the top of your XML file (see for an example).
getElementsByTagName will give you all nodes, not just immediate children:
$family = $indi->getElementsByTagName('family');
foreach ($family as $subIndi) {
outputIndi($subIndi);
}
You will call outputIndi() for grand children, etc repeatedly.
Here is an example (from another stackoverflow question):
for ($n = $indi->firstChild; $n !== null; $n = $n->nextSibling) {
if ($n instanceof DOMElement && $n->tagName == "family") {
outputIndi($n);
}
}
Replace this
$family = $indi->getElementsByTagName('family');
foreach ($family as $subIndi) {
outputIndi($subIndi);
}
by this
if(!empty($indi))
foreach($indi as $subIndi){
outputIndi($subIndi);
}
I realize
if($indi->hasChildNodes())
is better than
if(!empty($indi))

Categories