XML parsing only some nodes - PHP - php

I have the following example XML:
<PRODUCTRATINGLIST>
<PRODUCT>
<VENDORREF>AC308A~</VENDORREF>
<RATING>100%</RATING>
<REVIEWCOUNT>7</REVIEWCOUNT>
</PRODUCT>
<PRODUCT>
<VENDORREF>AC308C~</VENDORREF>
<RATING>98%</RATING>
<REVIEWCOUNT>89</REVIEWCOUNT>
</PRODUCT>
</PRODUCTRATINGLIST>
I'm simply trying to extract each node under PRODUCT:
$ratings = simplexml_load_file("test.xml");
foreach ($ratings->PRODUCT as $rating){
$part = $rating->VENDORREF;
$rating = str_replace('%','',$rating->RATING);
$numReviews = $rating->REVIEWCOUNT;
}
If I then try to print each element e.g.
echo $part.' '.$rating.' '.$numReviews;
$numReviews is always blank and I have no idea why.

You are replacing the $rating array with a variable, fix it like this:
$part = $rating->VENDORREF;
$rating_string = str_replace('%','',$rating->RATING);
$numReviews = $rating->REVIEWCOUNT;

Check below code. You change the variable names.
$ratings = simplexml_load_file("test.xml");
foreach ($ratings->PRODUCT as $rating){
$part = $rating->VENDORREF;
$ratingVal = str_replace('%','',$rating->RATING);
$numReviews = $rating->REVIEWCOUNT;
}
echo $part.' '.$ratingVal.' '.$numReviews;

Related

parsing nested xml using php

here's the XML which I'm trying to parse for a while but I'm stuck on nested elements.
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:course="https://www.example.org/api/course/elements/1.0/" xmlns:staff="https://www.example.org/api/staff/elements/1.0/" version="2.0">
<channel>
<item>
<title>example.org course feed</title>
<link>https://www.example.org/api/v2/report/course-feed/rss</link>
<description>.org - course catalog feed</description>
<language>en</language>
<course:instructors>
<course:staff>
<staff:name>Mark Moran</staff:name>
</course:staff>
</course:instructors>
</item>
</channel>
how to parse course: instructors, my PHP code is
$rss = simplexml_load_file('https://www.edx.org/api/v2/report/course-feed/rss');
$namespaces = $rss->getNamespaces(true);
foreach ($rss->channel->item as $item) {
$title = $item->title ;
}
EDIT:2
$rss = simplexml_load_file('https://www.example.org/api/v2/report/course-feed/rss');
$namespaces = $rss->getNamespaces(true);//Add this line
foreach ($rss->channel->item as $item) {
$course_title = $item->title ;
$course_description = $item->description;
$course_url = $item->link;
$course = $item->children($namespaces['course']);
$course_thumbnail_url = $course->{'image-thumbnail'};
$course_banner_url = $course->{'image-banner'};
$course_teaser_url = $course->{'video-youtube'};
$course_start_date = $course->start;
$course_duration = $course->length;
$instructors = $item->children('course',true)->instructors;
$staff = $instructors->children('course',true)->staff;
$instructor_name = $staff->children('staff',true)->name;
$instructor_image = $staff->children('staff',true)->image;
echo $instructor_name.' '.$instructor_image,"<br>";
$course_price = 0;
$course_provider_id = 3;
$course_affiliates = $course->school;
$categories = $course->subject;
$categories = explode(',', $categories);
$c = count($categories);
$i = 0;
while($i < $c)
{
$course_rating = mt_rand(3.5,5);
$course_category = $categories[$i];
if(mysqli_query($conn,"INSERT into course_catalog_table (course_title,course_description,course_url,course_thumbnail_url,course_banner_url,course_teaser_url,course_category,course_start_date,course_duration,course_rating,course_affiliates,course_instructor,course_instructor_image,course_price,course_provider_id) VALUES('$course_title','$course_description','$course_url','$course_thumbnail_url','course_banner_url','course_teaser_url','$course_category','$course_start_date','$course_duration','$course_rating','$course_affiliates','$instructor_name',$instructor_image','$course_price')"))
{
echo "successfull\r\n";
}
$i++;
}
}
When i print instructor_name and instructor_image sometimes its prints but sometimes it throws warning that main(): Node no longer exists ,how can i check that is empty or not
You can use the children() function to access the child tree of the xml structure.
Do like this:
$rss->channel->item->children('course',true)->instructors;
Read: http://php.net/manual/en/simplexmlelement.children.php
But since the XML have multiple nest, you need to use multiple children() function to access the deepest nest.
Here is the modified code to parse the XML you give:
foreach ($rss->channel->item as $item)
{
$title = $item->title;
// access course:instructors nest
$instructors = $item->children('course',true)->instructors;
// then access the course:staff nest
$staff = $instructors->children('course',true)->staff;
// finally access the staff:name nest value
$name = $staff->children('staff',true)->name;
// print the value
echo "Staff Name: ". $name . "<br>";
}
Test run: https://eval.in/735810

XML data getting with php (just images not product_id)

Hi i have an xml data like this
<Product>
<ProductID>13078</ProductID>
<image1>
image_url
</image1>
<image2>
image_url
</image2>
<image3>
image_url
</image3>
</Product>
i want to access images
please help!!!
You can do it using SimpleXMLElement
$xml = simplexml_load_string($xmlString, "SimpleXMLElement");
$json = json_encode($xml);
$array = json_decode($json,TRUE);
unset($array['ProductID']); // You don't want 'ProductID' then You can remove it using unset().
$i=1;
foreach($array as $key=>$val){
echo $array['image'.$i]; // Here you can get all images in one echo
$i++;
}
if (file_exists('test.xml')) {
$xml = simplexml_load_file('test.xml');
print_r($xml);
}
you will get a result array
or else if you have XML string use this function
$xml = simplexml_load_string($string);
print_r($xml);
hope this will help you
Your Solution:
$string = '<Product>
<ProductID>13078</ProductID>
<image1>
image_url
</image1>
<image2>
image_url
</image2>
<image3>
image_url
</image3>
</Product>';
$xml = simplexml_load_string($string);
echo $xml->image1;

Searching XML tags with regex - PHP XPatch

I have a XML document:
<product>
<item>
<item00>
<name>DVD</name>
</item00>
</item>
</product>
<product>
<item>
<item11>
<name>CD</name>
</item11>
</item>
</product>
And I would like to show the names of these products, but there are products with item as "item00" and "item11".
I tried adding the path regular expressions in XPath, but without success.
There is a possibility I display the name of these products (DVD and CD) using XPath?
<?php
$xml = 'file.xml';
$content = '';
$f = fopen($xml, 'r');
while($data = fread($f, filesize($xml))) {
$content.= $data;
}
fclose($f);
preg_match_all('/\<product\>(.*?)\<\/product\>/s', $content, $product);
$product = $product[1];
$doc = new SimpleXMLElement($content);
for($i = 0; $i <= count($product) - 1; $i++) {
// So far, no problems. Seriously.
// The issue starts here.
$query = $doc->xpath('/product/item/???');
foreach($query as $item) {
echo $item->name . '<br>';
}
}
?>
Where "???" is the problem with "item00" and "item11".
If anyone knows and can help me, I'll be very grateful!
Here is the total working code
<?php
$xml = 'file.xml';
$content = '';
$f = fopen($xml, 'r');
while($data = fread($f, filesize($xml))) {
$content.= $data;
}
fclose($f);
$content = "<root>$conten</root>";
$doc = new SimpleXmlElement($content);
$query = $doc->xpath('//item/child::*');
foreach($query as $item) {
echo $item->name . '<br>';
}
i dont think you can use regex in that context, that's the very reason to use attributes
<item num="00">
however check this, i believe it is what you are looking for
those 00 11 things really should be attributes

passing xml in php function and getting common xml with condition [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Best XML Parser for PHP
-----First XML-----str1
<HOME>
<USER_DETAIL>
<LOCATION><![CDATA[MUMBAI]]></LOCATION>
<NAME><![CDATA[RAVI]]></NAME>
<ID><![CDATA[101]]></ID>
</USER_DETAIL>
<USER_DETAIL>
<LOCATION><![CDATA[PUNE]]></LOCATION>
<NAME><![CDATA[MANISH]]></NAME>
<ID><![CDATA[102]]></ID>
</USER_DETAIL>
</HOME>
---Second XML----str2
<USER_DATA>
<DATA>
<DOB><![CDATA[2/11/1959]]></DOB>
<STATUS><![CDATA[single]]></STATUS>
<PROFILE_PIC><![CDATA[101.JPG]]></PROFILE_PIC>
<ID><![CDATA[101]]></ID>
</DATA>
<DATA>
<DOB><![CDATA[6/8/1987]]></DOB>
<STATUS><![CDATA[married]]></STATUS>
<PROFILE_PIC><![CDATA[102.JPG]]></PROFILE_PIC>
<ID><![CDATA[102]]></ID>
</DATA>
</USER_DATA>
I am new to XML.
I have two xml as above I want common xml with all the data of user. In two XML common thing is ID of user. so is there any way to pass xml into function and compare the id in second xml and get the detais of that perticular user and forms a required(Common with all detais) xml.
str1 and str2 is the php variable which contains the above xml respectively.
use below codes to generate a new XML, you can change the nodes based on your requirements. in case you have both XMLs in a file you can use simplexml_load_file($filename); to load the XML and assign it to $str1 and $str2
$str1 = "<HOME>
<USER_DETAIL>
<LOCATION><![CDATA[MUMBAI]]></LOCATION>
<NAME><![CDATA[RAVI]]></NAME>
<ID><![CDATA[101]]></ID>
</USER_DETAIL>
<USER_DETAIL>
<LOCATION><![CDATA[PUNE]]></LOCATION>
<NAME><![CDATA[MANISH]]></NAME>
<ID><![CDATA[102]]></ID>
</USER_DETAIL>
</HOME>";
$str2 = "<USER_DATA>
<DATA>
<DOB><![CDATA[2/11/1959]]></DOB>
<STATUS><![CDATA[single]]></STATUS>
<PROFILE_PIC><![CDATA[101.JPG]]></PROFILE_PIC>
<ID><![CDATA[101]]></ID>
</DATA>
<DATA>
<DOB><![CDATA[6/8/1987]]></DOB>
<STATUS><![CDATA[married]]></STATUS>
<PROFILE_PIC><![CDATA[102.JPG]]></PROFILE_PIC>
<ID><![CDATA[102]]></ID>
</DATA>
</USER_DATA>";
$xml1 = simplexml_load_string($str1);
$xml2 = simplexml_load_string($str1);
//print_r($xml);
$tempArr = array();
foreach( $xml1 as $obj) {
$id = $obj->ID;
$tempArr["$id"]['LOCATION'] = (string)$obj->LOCATION;
$tempArr["$id"]['NAME'] = (string)$obj->NAME;
}
foreach( $xml2 as $obj) {
$id = $obj->ID;
$tempArr["$id"]['DOB'] = (string)$obj->DOB;
$tempArr["$id"]['STATUS'] = (string)$obj->STATUS;
$tempArr["$id"]['PROFILE_PIC'] = (string)$obj->PROFILE_PIC;
}
//print_r($tempArr);
$xml = new DOMDocument('1.0', 'iso-8859-1');
$doc = $xml->createElement('DOCUMENT');
$doc = $xml->appendChild($doc);
foreach( $tempArr as $ky=>$val ) {
$rnod = $xml->createElement('USER_DETAIL');
$rnod = $doc->appendChild($rnod);
//$rnod = $xml->appendChild($rnod);
$dataN0 = $xml->createElement('ID');
$dataN0 = $rnod->appendChild($dataN0);
$nodV = $xml->createTextNode($ky);
$dataN0->appendChild($nodV);
foreach($val as $k=>$v) {
$dataN1 = $xml->createElement($k);
$dataN1 = $rnod->appendChild($dataN1);
$nodV1 = $xml->createTextNode($v);
$dataN1->appendChild($nodV1);
}
}
$newXml = $xml->saveXML();
echo htmlspecialchars($newXml);

How to use an object as a parameter for PHP's createElement

I'm using a variable to create an element. But I'm getting this error:
Warning: DOMDocument::createElement() expects parameter 1 to be string, object given
// load up your XML
$xml = new DOMDocument;
$xml->load('test.xml');
$parent_node = $xml->createElement('parent');
foreach ($xml->getElementsByTagName('product') as $product )
{
$append = array();
foreach($product->getElementsByTagName('name') as $name ) {
// Stick $name onto the array
$append[] = $name;
}
foreach ($append as $a) {
$parent_node->appendChild($xml->createElement($a, 'anothervalue'));
$product->appendChild($parent_node);
}
$product->removeChild($xml->getElementsByTagName('details')->item(0));
//$product->appendChild($element);
}
// final result:
$result = $xml->saveXML();
Original XML structure:
<products>
<product>
<name>text</name>
<name>text</name>
<name>text</name>
</product>
</products>
I'm trying to create a new element whose value is the text of itself. I know what it has to look like. Why can't I use an object to create an element?
The result I'm trying to obtain will look like this:
<products>
<product>
<text>text</text>
<text>text</text>
<text>text</text>
</product>
</products>
You can't pass an object, you must use the textContent or nodeValue properties:
$element = $xml->createElement(trim($a->textContent), 'anothervalue');
You may also want to strip it from illegal characters first:
$nodeName = preg_replace('/[^a-z0-9_-]/i', '', $a->textContent);
$element = $xml->createElement($nodeName, 'anothervalue');
declare the array befor the foreach loop otherwise it will become empty every time when one loop will complete
$append = array();
foreach ($xml->getElementsByTagName('product') as $product )
{
foreach($product->getElementsByTagName('name') as $name ) {
// Stick $name onto the array
$append[] = $name;
}
foreach ($append as $a) {
$parent_node->appendChild($xml->createElement($a, 'anothervalue'));
$product->appendChild($parent_node);
}
$product->removeChild($xml->getElementsByTagName('details')->item(0));
//$product->appendChild($element);
}
$parent_node->appendChild($xml->createElement($a->nodeValue, 'anothervalue'));
This get element value, if you wanna get the element name .. use '$a->nodeName'
Just change this one line
$append[] = $name;
to
$append[] = $name->tagName;
It should work then

Categories