Parse XML to HTML with PHP SimpleXMLElement - php

I am having some issues with SimpleXMLElement that I was hoping to get some help.
I was reading about SimpleXMLElement and I built a PHP page to parse this XML:
<?xml version='1.0'?>
<AdXML>
<Response>
<Campaign>
<Overview>
<Name>strip</Name>
<Description>category</Description>
<Status>L</Status>
</Overview>
<Pages>
<Url>page01</Url>
<Url>page02</Url>
<Url>page03</Url>
</Pages>
</Campaign>
</Response>
</AdXML>
Tag "Pages" can have any number of tags "Url" other tags might have only one value, like the tag "Name" for example.
Reading about SimpleXMLElement I ended up with the following code:
$xmlparsed = new SimpleXMLElement($xml); //my xml is being sent as variable
To display single values I am using the code below without a problem:
<?php echo $xmlparsed->Response[0]->Campaign[0]->Overview[0]->Name;?>
Everything works fine. But when I try to parse a tag with multiple lines I get only one line, and everytime I refresh the page it gives me a different "url" value. This is the code I am using:
<?php foreach ($xmlparsed->Response->Campaign->Pages as $Pages) {echo $Pages->Url, PHP_EOL;} ?>
According to PHP's site: http://php.net/manual/en/simplexml.examples-basic.php this should work, but it isn't.
Since I am not expert on PHP I am testing code on a trial-and-error basis.
What am I doing wrong here?
thanks in advance for any help.

You only have one Pages so you are only entering that foreach once. Try looping on the urls.
$xml = "<?xml version='1.0'?>
<AdXML>
<Response>
<Campaign>
<Overview>
<Name>strip</Name>
<Description>category</Description>
<Status>L</Status>
</Overview>
<Pages>
<Url>page01</Url>
<Url>page02</Url>
<Url>page03</Url>
</Pages>
</Campaign>
</Response>
</AdXML>";
$xmlparsed = new SimpleXMLElement($xml);
foreach ($xmlparsed->Response->Campaign->Pages->Url as $url) {
echo $url, PHP_EOL;
}
Output:
page01
page02
page03

You can also use XPath.
foreach( $xml->xpath( 'Response/Campaign/Pages/Url' ) as $url ) {
echo $url;
}

Related

I want to process a XML file In php

This is my XML file
<?xml version="1.0" encoding="UTF-8"?>
<searchresult>
<query>file</query>
<page-number>3</page-number>
<start>20</start>
<files-per-page>10</files-per-page>
<files-approx-count>6361998</files-approx-count>
<result-files>
<file>
<name>file 1</name>
<description>
descrp
</description>
<url>
http://www.example.com
</url>
</file>
<file>
<name>file 2</name>
<description>
descrp 2
</description>
<url>
http://www.example.com
</url>
</file>
</result-files>
</search-result>
i tried the following code
$xml = simplexml_load_file("file.xml");
foreach ($xml as $xmls):
$name =$xmls->name;
$url =$xmls->url;
echo $name.$url;
endforeach;
but no output please help.
First thing, your XML file is not well-formed. The root tag is <searchresult> while the last tag is </search-result>. This causes a parsing error.
Second thing, if your tags contain dashes, those tags cannot be used directly as variables with SimpleXML, in that case you should use a special syntax (see this: php simplexml_load_file with a dash ( - )). Other way to fix this is, if you control de XML syntax, change the way the XML is written and don't use dashes on tags.
Lastly, I think you want to print out the info of files within the result-files tag.
$xml = simplexml_load_file("file.xml");
foreach ($xml->{'result-files'}->file as $file) {
printFile($file);
}
function printFile($file) {
$name = trim($file->name);
$url = trim($file->url);
print "$name $url\n";
}
Output:
file 1 http://www.example.com
file 2 http://www.example.com
And you are done.
You're creating an object when you use the simplexml_load_file. The object isn't necessarily iterable - but it is indexable by tag names. try not doing the foreach(...) and instead just using echo $xml->name;. If that doesn't work, then perhaps you're looking in the wrong directory for your file. You likely need to do something like:
EDITED TO MATCH XML FILE PROVIDED
$path = $_SERVER['DOCUMENT_ROOT']."/file.xml";
$xml = simplexml_load_file($path);
echo $xml->start; //should output 20

Xml PHP Get attributes and its children value

XML:
<?xml version="1.0" encoding="ISO-8859-1"?>
<lessons>
<lesson level="1" course="2">
<name type="Dog" category="Animals">Dog name</name>
</lesson>
</lessons>
I want to get the values saved like this:
$type = "Dog";
$category = "Animals";
$name = "dog name";
This is what I've done:
foreach($xml->name as $name){
$type = $name['type'];
$category = $name['category'];
echo "Type: $type Category: $category<br>";
// AND TO get the text, haven't figuered it out yet.. <name ..="" ..="">text</name>
}
But it doesn't work. Don't get any errors neither any output. Any ideas?
EDIT:
OK. I changed foreach($xml->name as $name)
to foreach($xml->lesson->name as $name)
so I get the values of the attribute. But now I don't know how to get the value of the children.
I've tried this: $xml->lesson->children()
It prints children()
SOLVED: $text = $xml->lesson->children();
echo $text;
PROBLEM WAS: I'm using utf-8 in my other code but didn't change it.
Edit : this part related to a question typo. If you copied your xml directly from where you were editting it, then part of the problem might be that it is malformed. You have an opening <lessons> but you appear to wrongly try to close it with </lesson>.
Also, depending on your root node settings, ->name may or may not be a child of the $xml object. Can you post a var_dump() of it and get some clues?
I think, there is some problem in your xml.
-> You have to close lessons tag correctly.Because you have entered </lesson> (see last line) instead of </lessons>. If you start any tag, you should use the same tag name while closing..
you can use this code to extract values from your xml,
<?php
$xmlstring='<lessons>
<lesson level="1" course="2">
<name type="Dog" category="Animals">Dog name</name>
</lesson>
</lessons>';
$xml = simplexml_load_string($xmlstring);
$ATTRIBUTE=array();
$counter = 0;
foreach($xml->children() as $key=>$child)
{
$counter++;
$ATTRIBUTE[$counter]["type"]=$child->name->attributes()->type;
$ATTRIBUTE[$counter]["category"]=$child->name->attributes()->category;
$ATTRIBUTE[$counter]["value"]= $child->name;
}
echo "<pre>";
print_r($ATTRIBUTE);
?>
here you will get everything in array. So you can fetch based on your requirement.

Creating an image Tag with DOMDocument fails

I'm using DOMDocument to generate a XML and this XML has to have an image-Tag.
Somehow, when I do (simplified)
$response = new DOMDocument();
$actions = $response->createElement('actions');
$response->appendChild($actions);
$imageElement = $response->createElement('image');
$actions->appendChild($imageElement);
$anotherNode = $response->createElement('nodexy');
$imageElement->appendChild($anotherNode);
it results in
<actions>
<img>
<node></node>
</actions>
If I change 'image' to 'images' or even 'img' it works. It does work as well when I switch from PHP 5.3.10 to 5.3.8.
Is this a bug or a feature? My guess is that DOMDocuments assumes that I want to build an HTML img Element ... Can I prevent this somehow?
Weird thing on top: I'm not able to reproduce the error in another script on the same server. But I do not catch the pattern ...
Here's a complete pastebin of the class, that's causing the error: http://pastebin.com/KqidsssM
That costed me two hours.
DOMDocument renders the XML correctly. The XML is returned by an ajax call and somehow the browser/javascript changes it to img before displaying it ...
Is it possible that $imageAction->getAction() of line 44 returns 'img'? Have you var_dump()ed that? I don't see how DOM would convert "image" to "img" under any circumstances.
I think it is behaving as an "html doc"
try to add a version number, "1.0"
code
<?php
$response = new DOMDocument('1.0','UTF-8');
$actions = $response->createElement('actions');
$response->appendChild($actions);
$imageElement = $response->createElement('image');
$actions->appendChild($imageElement);
$anotherNode = $response->createElement('nodexy');
$imageElement->appendChild($anotherNode);
echo $response->saveXML();
output:
<?xml version="1.0" encoding="UTF-8" ?>
<actions>
<image>
<nodexy />
</image>
</actions>
and also you can use SimpleXML classes
Example :
<?php
$response = new SimpleXMLElement("<actions></actions>");
$imageElement = $response->addChild('image');
$imageElement->addChild("nodexy");
echo $response->asXML();
output :
<?xml version="1.0" ?>
<actions>
<image>
<nodexy />
</image>
</actions>

Hide XML declaration in files generated using PHP

I was tesing with a simple example of how to display XML in browser using PHP and found this example which works good
<?php
$xml = new DOMDocument("1.0");
$root = $xml->createElement("data");
$xml->appendChild($root);
$id = $xml->createElement("id");
$idText = $xml->createTextNode('1');
$id->appendChild($idText);
$title = $xml->createElement("title");
$titleText = $xml->createTextNode('Valid');
$title->appendChild($titleText);
$book = $xml->createElement("book");
$book->appendChild($id);
$book->appendChild($title);
$root->appendChild($book);
$xml->formatOutput = true;
echo "<xmp>". $xml->saveXML() ."</xmp>";
$xml->save("mybooks.xml") or die("Error");
?>
It produces the following output:
<?xml version="1.0"?>
<data>
<book>
<id>1</id>
<title>Valid</title>
</book>
</data>
Now I have got two questions regarding how the output should look like.
The first line in the xml file '', should not be displayed, that is it should be hidden
How can I display the TextNode in the next line. In total I am exepecting an output in this fashion
<data>
<book>
<id>1</id>
<title>
Valid
</title>
</book>
</data>
Is that possible to get the desired output, if so how can I accomplish that.
Thanks
To skip the XML declaration you can use the result of saveXML on the root node:
$xml_content = $xml->saveXML($root);
file_put_contents("mybooks.xml", $xml_content) or die("cannot save XML");
Please note that saveXML(node) has a different output from saveXML().
First question:
here is my post where all usable threads with answers are listed: How do you exclude the XML prolog from output?
Second question:
I don't know of any PHP function that outputs text nodes like that.
You could:
read xml using DomDocument and save each node as string
iterate trough nodes
detect text nodes and add new lines to xml string manually
At the end you would have the same XML with text node values in new line:
<node>
some text data
</node>

How to extract the content of <uri></uri> in a XML document?

I have a document that it's structure is like below.
There are a lot of <entry>. My question is how can I output the <uri> of each entry? And another question, how can I output only the USERNAME?
This is the file I want to get the usernames http://search.twitter.com/search.atom?q=yankees
<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns:google="http://base.google.com/ns/1.0" xml:lang="en-US" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns="http://www.w3.org/2005/Atom" xmlns:twitter="http://api.twitter.com/" xmlns:georss="http://www.georss.org/georss">
<entry>
<author>
<name></name>
<uri>http://twitter.com/USERNAME</uri>
</author>
</entry>
<?php
$xml = new DOMDocument;
// link to ur file
$xml->load('');
foreach ($xml->getElementsByTagName('entry') as $product )
{
$append = array();
foreach($product->getElementsByTagName('uri') as $name ) {
// Stick $name onto the array
$append[] = $name;
}
}
$result = $xml->saveXML();
print_r(str_replace('http://twitter.com/','',$result));
?>
You can use Xpath queries
http://www.php.net/manual/en/simplexmlelement.xpath.php
or
http://php.net/manual/en/domxpath.query.php
You should use SimpleXML some kind of a loop which goes trough all the s.
(foreach($xml->entry as $entry) loop should work fine, I think.)
And for the second: if it is always http://twitter.com/USERNAME, simply count the prefix's length than use a substr.
Resources to use: substr, SimpleXML, SimpleXML

Categories