Using xpath to query XML in PHP - 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

Related

How can print node value XML in an orderly way PHP

I have a XML like this:
<description>
<heading id="01"> Math </heading>
<p id="01"> Text 1 </p>
<heading id="02"> History </heading>
<p id="02"> Text 2</p>
<p id="03"> Text 3</p>
<heading id="03"> Biology </heading>
<p id="04"> Text 4 </p>
</description>
I also have many xml files have structure like this one, they are only different from amount of <p> node of every <heading> node.
How can I print <heading> and some <p> node and the second heading....
I tried to use foreach, but it's not true.
my code:
<?php
$xml=simplexml_load_file("NWB2.xml") or die("Error: Cannot create object");
echo "<b>".$xml->{'description'}->{'heading'}."</b>";
echo "<p>".$xml->{'description'}->{'p'}."</p>";
?>
If it's just a case of having different style depending on the input tag, you can use a foreach() loop and output the value according to the tag type...
$xml=simplexml_load_file("NWB2.xml") or die("Error: Cannot create object");
foreach ( $xml as $type => $value ) {
if ($type == "p") {
echo $value;
}
else {
echo "<b>$value</b>";
}
}

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

Load XML file and load content

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.

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
?>

Regex - Replacing content - eZ Publish XML field

I have an Xml content that i want to modify before using the eZ Publish 5 API to create it.
I am trying to implement a Regex to modify the content.
Here is the Xml code that i have (with html entities) :
Print of Xml code http://img15.hostingpics.net/pics/453268xmlcode.jpg
I want to be able to catch empty.jpg in :
<img alt="" src="http://www.asite.org/empty.jpg" />
And replace the whole line for each occurrence by :
<custom name="my_checkbox"></custom>
Problem :
The img tag can sometimes contain other attributes like : height="15" width="12"
<img height="15" alt="" width="12" src="http://www.asite.org/empty.jpg" />
And sometimes the attributes are after the src attribute in a different order.
The aim would be :
Xml code - Aim http://img15.hostingpics.net/pics/318980xmlcodeaim.jpg
I've tried many things so far but nothing worked.
Thanks in advance for helping.
Cheers !
EDIT :
Here is an example of what i've tried so far :
/(<img [a-z = ""]* src="http:\/\/www\.asite\.org\/empty\.jpg" \/&gt)/g
Dealing with XML i've used an XML parser to reach the desired section.
Then we can apply a regex (~<img.*?>(?=</span)~) to select and replace the image tag with your custom tag (note that in the object received by the xml parser the html entities are replaces with their equivalent char).
This is a piece of code that emulates and handle your situation:
<?php
$xmlstr = <<<XML
<sections>
<section>
<paragraph>
<literal class="html">
<img alt="" src="http://asite.org/empty.png" /></span></span> Yes/no&nbsp;<br />
<img alt="" src="http://asite.org/empty.png" /></span></span> Other text/no&nbsp;<br />
</literal>
</paragraph>
</section>
</sections>
XML;
$sections = new SimpleXMLElement($xmlstr);
foreach ($sections->section->paragraph as $paragraph) {
$re = "~<img.*?>(?=</span)~";
$subst = "<custom name=\"my_checkbox\"></custom>";
$paragraph->literal = preg_replace($re, $subst, $paragraph->literal);
}
echo $sections->asXML();
?>
The output is:
<?xml version="1.0"?>
<sections>
<section>
<paragraph>
<literal class="html">
<custom name="my_checkbox"></custom></span></span> Yes/no&nbsp;<br />
<custom name="my_checkbox"></custom></span></span> Other text/no&nbsp;<br />
</literal>
</paragraph>
</section>
</sections>
An online demo can be found HERE

Categories