PHP - String could not be parsed as XML [duplicate] - php

This question already has answers here:
Reference - What does this error mean in PHP?
(38 answers)
Closed 8 years ago.
I am currently using the following code, but no result is returned:
<?php
$url = 'http://myknowledge.org.uk/xml';
$xml = new SimpleXMLElement(file_get_contents($url));
foreach ($xml->item as $item) {
$title = $item->title;
}
echo $title;
?>
The XML Code:
<?xml version="1.0" encoding="utf-8"?>
<item>
<title>Apple</title>
<notableFor>Fruit</notableFor>
<wikiid>Apple</wikiid>
<description>The apple is the pomaceous fruit of the apple tree, Malus domestica of the rose family. It is one of the most widely cultivated tree fruits, and the most widely known of the many members of genus Malus that are used by humans.</description>
<img></img>
<website></website>
<translate>
<de>Äpfel</de>
<fr>pomme</fr>
<it>mela</it>
<es>manzana</es>
<ru>яблоко</ru>
</translate>
<nutritionalInfomation name="Apple" quantity="100g">
<calories>52</calories>
<carb>14</carb>
<fibre>2.4</fibre>
<protein>0.3</protein>
<fat>0.2</fat>
</nutritionalInfomation>
</item>
If anybody has an idea how to fix this I would love to know. Thanks.

The XML appears to be invalid in lines 4 and 5:
<notableFor>Fruit</title>
<wikiid>Apple</title>
Which should be:
<notableFor>Fruit</notableFor>
<wikiid>Apple</wikiid>
I recommend using the XML validator at http://www.w3schools.com/xml/xml_validator.asp to debug errors with your XML code.
Also, as your root element is item, you may want to change your PHP code:
<?php
$url = 'http://myknowledge.org.uk/xml';
$item = new SimpleXMLElement(file_get_contents($url));
$title = $item->title;
$description = $item->description;
?>
(I don't have a copy of PHP on hand to test this, but according to http://php.net/manual/en/simplexml.examples-basic.php, this should work)

Xml can have only 1 root element, in your example the root is item
When loading to SimpleXML you can get the root name with $xml->getName()
$url = 'http://myknowledge.org.uk/xml';
$item = new SimpleXMLElement($url, null, true);
$title = $item->title;
$description = $item->description;
Or you should enclose you items in another root i.e items if you need multiple

Related

Check if child exists? - SimpleXML (PHP)

I have different XML files where I renamed for each XML file all individual tags, so that every XML file has the same tag name. That was easy because the function was customized for the XML file.
But instand of writing 7 new functions for each XML file now I want to check if a XML file has a specidifed child or not. Because if I want to say:
foreach ($items as $item) {
$node = dom_import_simplexml($item);
$title = $node->getElementsByTagName('title')->item(0)->textContent;
$price = $node->getElementsByTagName('price')->item(0)->textContent;
$url = $node->getElementsByTagName('url')->item(0)->textContent;
$publisher = $node->getElementsByTagName('publisher')->item(0)->textContent;
$category = $node->getElementsByTagName('category')->item(0)->textContent;
$platform = $node->getElementsByTagName('platform')->item(0)->textContent;
}
I get sometimes: PHP Notice: Trying to get property of non-object in ...
For example. Two different XML sheets. One contains publisher, category and platform, the other not:
XML 1:
<products>
<product>
<desc>This is a Test</desc>
<price>11.69</price>
<price_base>12.99</price_base>
<publisher>Stackoverflow</publisher>
<category>PHP</category>
</packshot>
<title>Check if child exists? - SimpleXML (PHP)</title>
<url>http://stackoverflow.com/questions/ask</url>
</product>
</products>
XML 2:
<products>
<product>
<image></image>
<title>Questions</title>
<price>23,90</price>
<url>google.de/url>
<platform>Stackoverflow</platform>
</product>
</products>
You see, sometimes one XML file contains publisher, category and platform but sometimes not. But it could also be that not every node of a XML file contains all attributes like in the first!
So I need to check for every node of a XML file individual if the node is containing publisher, category or/and platform.
How can I do that with SimpleXML?
I thought about switch case but at first I need to check which childs are contained in every node.
EDIT:
Maybe I found a solution. Is that a solution or not?
if($node->getElementsByTagName('platform')->item(0)){
echo $node->getElementsByTagName('platform')->item(0)->textContent . "\n";
}
Greetings and Thank You!
One way to rome... (working example)
$xml = "<products>
<product>
<desc>This is a Test</desc>
<price>11.69</price>
<price_base>12.99</price_base>
<publisher>Stackoverflow</publisher>
<category>PHP</category>
<title>Check if child exists? - SimpleXML (PHP)</title>
<url>http://stackoverflow.com/questions/ask</url>
</product>
</products>";
$xml = simplexml_load_string($xml);
#set fields to look for
foreach(['desc','title','price','publisher','category','platform','image','whatever'] as $path){
#get the first node
$result = $xml->xpath("product/{$path}[1]");
#validate and set
$coll[$path] = $result?(string)$result[0]:null;
#if you need here a local variable do (2 x $)
${$path} = $coll[$path];
}
#here i do array_filter() to remove all NULL entries
print_r(array_filter($coll));
#if local variables needed do
extract($coll);#this creates $desc, $price
Note </packshot> is an invalid node, removed here.
xpath syntax https://www.w3schools.com/xmL/xpath_syntax.asp
Firstly, you're over-complicating your code by switching from SimpleXML to DOM with dom_import_simplexml. The things you're doing with DOM can be done in much shorter code with SimpleXML.
Instead of this:
$node = dom_import_simplexml($item);
$title = $node->getElementsByTagName('title')->item(0)->textContent;
you can just use:
$title = (string)$item->title[0];
or even just:
$title = (string)$item->title;
To understand why this works, take a look at the SimpleXML examples in the manual.
Armed with that knowledge, you'll be amazed at how simple it is to see if a child exists or not:
if ( isset($item->title) ) {
$title = (string)$item->title;
} else {
echo "There is no title!";
}

parse and process HTML/XML/plain text page [duplicate]

This question already has answers here:
How do you parse and process HTML/XML in PHP?
(31 answers)
Closed 3 years ago.
I am creating a small php app that pulls data from a remote website its working great but i would like to make it more user friendly now.
I need to get a few specific items from the page and as far as I can tell the page looks like an xml file wen you look at sorce code but it has no style to it and appears as plain text so I don't really know what to do.
The page I am trying to get looks like this
<channel>
<name>data</name>
<id>data</id>
<img>data</img>
<auther>data</auther>
<mp3>data</mp3>
<bio>data</bio>
</channel>
<channel>
<name>data</name>
<id>data</id>
<img>data</img>
<auther>data</auther>
<mp3>data</mp3>
<bio>data</bio>
</channel>
<channel>
<name>data</name>
<id>data</id>
<img>data</img>
<auther>data</auther>
<mp3>data</mp3>
<bio>data</bio>
</channel>
<channel>
<name>data</name>
<id>data</id>
<img>data</img>
<auther>data</auther>
<mp3>data</mp3>
<bio>data</bio>
</channel>
I need to get all the data from each tag under the channel tag and keep it in the same order to echo it back out onto my own page in the same way.
How could i do this ? i tried using regex with the following patter
$pattern = '<channel>
<name>(.*)</name>
<id>(.*)</id>
<img>(.*)</img>
<auther>(.*)</auther>
<mp3>(.*)</mp3>
<bio>(.*)</bio>
</channel>';
but that doesn't work I really need the best and simplest way to do this.
$SimpleXMLElement = new SimpleXMLElement($str);
foreach ($SimpleXMLElement->children() as $Channel) {
foreach ($Channel->children() as $Child) {
echo $Child->getName() . ' = ' . (string) $Child;
}
}
this way you can use SimpleXMLElement, it's very easy
I would "sanitize" the incoming data and make an xml document out of it. This can be done by simply wrapping it into a surrounding tag. (I name it channels). Having this, you can parse the data using DOM:
// Sanitize input data. Make an xml out of it
$xml = '<channels>';
$xml .= file_get_contents($url);
$xml .= '</channels>';
// Create a document
$doc = new DOMDocument();
$doc->loadXML($xml);
// Iterate through channel elements
foreach($doc->getElementsByTagName('channel') as $channel) {
echo $channel->getElementsByTagName('name')->item(0)->nodeValue . PHP_EOL;
echo $channel->getElementsByTagName('id')->item(0)->nodeValue . PHP_EOL;
// And so on ...
}

parsing xml file in php [duplicate]

This question already has answers here:
How do you parse and process HTML/XML in PHP?
(31 answers)
Closed 9 years ago.
I have an xml file which consist of name of the country and its code.
<country>
<name>ALBANIA</name>
<code>AL</code>
</country>
<country>
<name>ALGERIA</name>
<code>DZ</code>
</country>
<country>
<name>AMERICAN SAMOA</name>
<code>AS</code>
</country>
now I am using following php code to store them in array and printing them(country.xml file is in the same folder as this php code.
$countries = array();
$file = new SimpleXMLElement(__DIR__ . '/country.xml', null, true);
foreach ($file->country as $country) {
$name = trim($country['name']);
$code = trim(strtoupper($country['code']));
$countries[$code] = $name;
echo $code;
}
but this php code shows blank page. Can anyone guide me where I am making mistake and help me to correct it or give some better method to parse xml file.
The simplexml_load_file() in PHP will do the job.
<?php
$xml = simplexml_load_file('country.xml');
$i=0;
$countryName=array();
$countryCode=array();
foreach($xml as $k=>$v)
{
$countryName[$i] = (string) $xml->country[$i]->name;
$countryCode[$i] = (string) $xml->country[$i]->code;
$i++;
}
print_r($countryName);
print_r($countryCode);
?>

simpleXML creating a foreach [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
foreach and simplexml
I have got my XML document loading correct but I am unsure how I can create a simple foreach were I can have [PictureHref] [Title] and [PriceDisplay] loaded for each item given in the feed.
I cannot find a clear example in the documentation.
XML Example
Currently my PHP code consists of the following:
$mainUrl = 'http://api.trademe.co.nz/v1/Member/{id}/Listings/All.xml';
$xmlFeed = simplexml_load_file($mainUrl);
XML
<Listings xmlns="http://api.trademe.co.nz/v1" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<TotalCount>1</TotalCount>
<Page>1</Page>
<PageSize>1</PageSize>
<List>
<Listing>
<ListingId>527496168</ListingId>
<Title>Clifftop Resort style Living with stunning aspect</Title>
<Category>0350-5748-3399-</Category>
<StartPrice>0</StartPrice>
<StartDate>2012-10-26T21:24:47.073Z</StartDate>
<EndDate>2012-12-21T21:24:47.073Z</EndDate>
<ListingLength i:nil="true" />
<HasGallery>true</HasGallery>
<AsAt>2012-10-28T22:48:47.409946Z</AsAt>
<CategoryPath>/Trade-me-property/Residential/For-sale</CategoryPath>
<PictureHref>http://images.trademe.co.nz/photoserver/thumb/10/239043710.jpg</PictureHref>
<RegionId>2</RegionId>
<Region>Auckland</Region>
<Suburb>North Shore</Suburb>
<NoteDate>1970-01-01T00:00:00Z</NoteDate>
<ReserveState>NotApplicable</ReserveState>
<IsClassified>true</IsClassified>
<GeographicLocation>
<Latitude>-36.5681333</Latitude>
<Longitude>174.6936265</Longitude>
<Northing>5951700</Northing>
<Easting>1751547</Easting>
<Accuracy>Address</Accuracy>
</GeographicLocation>
<PriceDisplay>To be auctioned</PriceDisplay>
</Listing>
</List>
</Listings>
All you need is
$url = simplexml_load_file("__YOUR__URL___");
$listing = $url->List->Listing;
echo "<pre>";
echo $listing->PictureHref, PHP_EOL;
echo $listing->Title, PHP_EOL;
echo $listing->PriceDisplay, PHP_EOL;
While I'd recommend the use of DOMDocument instead of SimpleXML, here's how you'd do that in SimpleXML:
$data = array();
foreach($xmlFeed->List as $item) {
$data[] = array(
(string) $item->Listing->PictureHref,
(string) $item->Listing->Title,
(string) $item->Listing->PriceDisplay
);
}
You can see it (sorta, I had to change some things) at CodePad

How to fix XML parsing error with PHP? [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
PHP library for parsing XML with a colons in tag names?
I have the xml shown below and I want to parse out the product title. When I use the php code below, I get "Parse error: syntax error, unexpected ':' in /home/content/c/a/s/cashme/html/buylooper/xml.php on line 5" because of the ":" located in the tag. How do I resolve this?
*update: I've got the answer to the first part, but am having trouble in how to parse out an attribute of an xml tag. The tag I am having trouble with is the "s:image" tag (link attribute) inside the "s:images" tag.
<?php
$url = 'xml-file.xml';
$xml = simplexml_load_file($url);
$title = $xml->entry[0]->s:product->s:title;
//print
echo '<br/>';
echo $title;
?>
<entry gd:kind="shopping#product">
<s:product>
<s:googleId>9400569674928563633</s:googleId>
<s:author>
<s:name>Amazon.com</s:name>
<s:accountId>2860562</s:accountId>
</s:author>
<s:creationTime>2010-08-19T05:50:21.000Z</s:creationTime>
<s:modificationTime>2012-01-26T23:54:26.000Z</s:modificationTime>
<s:country>US</s:country>
<s:language>en</s:language>
<s:title>Canon powershot s95 10 mp digital camera with 3.8x wide angle optical image stabilized zoom and 3.0-inch lcd</s:title>
<s:description>desc</s:description>
<s:link>http://www.amazon.com/Canon-PowerShot-S95-Stabilized-3-0-Inch/dp/B003ZSHNGS</s:link>
<s:brand>Canon</s:brand>
<s:condition>new</s:condition>
<s:gtin>00013803126556</s:gtin>
<s:gtins>
<s:gtin>00013803126556</s:gtin>
</s:gtins>
<s:inventories>
<s:inventory channel="online" availability="inStock">
<s:price shipping="0.0" currency="USD">340.41</s:price>
</s:inventory>
</s:inventories>
<s:images>
<s:image link="http://ecx.images-amazon.com/images/I/519z3AjKzHL._SL500_AA300_.jpg"/>
</s:images>
</s:product>
</entry>
Parse the namespaces first.
$namespaces = $xml->getNameSpaces(true);
$s = $xml->children($namespaces['s']);
echo (string)$s->product->title. "\n";
echo (string)$s->product->images->image->attributes()->link;
You need to get the correct namespace with . This is untested, but might do the trick:
$url = 'xml-file.xml';
$xml = simplexml_load_file($url);
$namespaces = $xml->entry->getNameSpaces(true);
// Get children of the correct namespace
$s = $xml->entry[0]->children($namespaces['s']);
$title = $s->product->title;
//print
echo '<br/>';
echo $title;

Categories