Using simpleXML, how do you display the contents of a feed. I mean actually display the XML on a page so that I can see the schema?
In my example i will use XML file like:
<?xml version="1.0" encoding="UTF-8"?>
<module>
<name>Menus</name>
<folder>menus</folder>
<install>install.php</install>
</module>
You can use to load xml file in a variable:
$mod = simplexml_load_file($XMLfile);
and call fields:
echo $mod->module->name;
echo $mod->module->folder;
echo $mod->module->install;
Hope this helps.
$xml = simplexml_load_file("URL GOES HERE");
echo "<pre>";
print_r($xml);
echo "</pre>";
Will print a readable array of the object.
And a VALID RSS feed has this schema:
foreach($xml->channel->item as $items){
$title = $items->title;
$link = $items->link;
$description = $items->description;
$pubDate = strtotime($items->pubDate);
$pubDate = date('Y-m-d H:i:s', $pubDate);
}
Along with a few other attributes.
Related
I'm trying to get an RSS feed, change some text, and then serve it again as an RSS feed. However, the code I've written doesn't validate properly. I get these errors:
line 3, column 0: Missing rss attribute: version
line 14, column 6: Undefined item element: content (10 occurrences)
Here is my code:
<?php
header("Content-type: text/xml");
echo "<?xml version='1.0' encoding='UTF-8'?>
<?xml-stylesheet type='text/xsl'?>
<?xml-stylesheet type='text/xsl' media='screen'
href='/~d/styles/rss2full.xsl'?>
<rss xmlns:content='http://purl.org/rss/1.0/modules/content/'>
<channel>
<title>Blaakdeer</title>
<description>Blog RSS</description>
<language>en-us</language>
";
$html = "";
$url = "http://feeds.feedburner.com/vga4a/mPSm";
$xml = simplexml_load_file($url);
for ($i = 0; $i < 10; $i++){
$title = $xml->channel->item[$i]->title;
$description = $xml->channel->item[$i]->description;
$content = $xml->channel->item[$i]->children("content", true);
$content = preg_replace("/The post.*/","", $content);
echo "<item>
<title>$title</title>
<description>$description</description>
<content>$content</content>
</item>";
}
echo "</channel></rss>";
Just as you don't treat XML as a string when parsing it, you don't treat it as as string when you create it. Use the proper tools to create your XML; in this case, the DomDocument class.
You had a number of problems with your XML; biggest is that you were creating a <content> element, but the original RSS had a <content:encoded> element. That means the element name is encoded but it's in the content namespace. Big difference between that and an element named content. I've added comments to explain the other steps.
<?php
// create the XML document with version and encoding
$xml = new DomDocument("1.0", "UTF-8");
$xml->formatOutput = true;
// add the stylesheet PI
$xml->appendChild(
$xml->createProcessingInstruction(
'xml-stylesheet',
'type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"'
)
);
// create the root element
$root = $xml->appendChild($xml->createElement('rss'));
// add the version attribute
$v = $root->appendChild($xml->createAttribute('version'));
$v->appendChild($xml->createTextNode('2.0'));
// add the namespace
$root->setAttributeNS(
'http://www.w3.org/2000/xmlns/',
'xmlns:content',
'http://purl.org/rss/1.0/modules/content/'
);
// create some child elements
$ch = $root->appendChild($xml->createElement('channel'));
// specify the text directly as second argument to
// createElement because it doesn't need escaping
$ch->appendChild($xml->createElement('title', 'Blaakdeer'));
$ch->appendChild($xml->createElement('description', 'Blog RSS'));
$ch->appendChild($xml->createElement('language', 'en-us'));
$url = "http://feeds.feedburner.com/vga4a/mPSm";
$rss = simplexml_load_file($url);
for ($i = 0; $i < 10; $i++) {
if (empty($rss->channel->item[$i])) {
continue;
}
$title = $rss->channel->item[$i]->title;
$description = $rss->channel->item[$i]->description;
$content = $rss->channel->item[$i]->children("content", true);
$content = preg_replace("/The post.*/","", $content);
$item_el = $ch->appendChild($xml->createElement('item'));
$title_el = $item_el->appendChild($xml->createElement('title'));
// this stuff is unknown so it has to be escaped
// so have to create a separate text node
$title_el->appendChild($xml->createTextNode($title));
$desc_el = $item_el->appendChild($xml->createElement('description'));
// the other alternative is to create a cdata section
$desc_el->appendChild($xml->createCDataSection($description));
// the content:encoded element is not the same as a content element
// the element must be created with the proper namespace prefix
$cont_el = $item_el->appendChild(
$xml->createElementNS(
'http://purl.org/rss/1.0/modules/content/',
'content:encoded'
)
);
$cont_el->appendChild($xml->createCDataSection($content));
}
header("Content-type: text/xml");
echo $xml->saveXML();
The first error is just a missing attribute, easy enough:
<rss version="2.0" ...>
For the <p> and other HTML elements, you need to escape them. The file should look like this:
<p>...
There are other ways, but this is the easiest way. In PHP you can just call a function to encode entities.
$output .= htmlspecialchars(" <p>Paragraph</p> ");
As for the <content> tag problem, it should be <description> instead. The <content> tag currently generates two errors. Changing it to <description> in both places should fix both errors.
Otherwise it looks like you understand the basics. You <open> and </close> tags and those have to match. You can also use what is called empty tags: <empty/> which exist on their own but to not include content and no closing tag.
I have the following XML code:
<para>
<![CDATA[
<?php
$data = '<?xml version="1.0"?>
<root>content</root>';
$sxe = simplexml_load_string($data);
var_dump($sxe);
?>
]]>
</para>
I want to parse the CDATA section to take this result:
Content:
<?php
$data = '<?xml version="1.0"?>
<root>content</root>';
$sxe = simplexml_load_string($data);
var_dump($sxe);
?>
I use the following but it doesn't work.
$xml='sxml.xml';
$book = simplexml_load_file($xml, 'SimpleXMLElement', LIBXML_NOCDATA);
$para = $book->chapter->para[1];
print "Content: ".$para."<br>";
foreach($para AS $node) {
print "Iter Content: ".$node."<br>";
}
This results in:
Content:
content';
$sxe = simplexml_load_string($data);
var_dump($sxe);
?>
In phpinfo() it shows that libxml is enabled and active.
Any help? Thanks in advance
You should encode the special characters using htmlspecialchars
For example:
print "Content: ".htmlspecialchars($para)."<br>";
I am trying to assign the <all> / <avg> value in this XML code to a variable, so that I can use it for calculations. But when I do this, and try to print the value, I get a blank screen. Can someone please help?
<stats>
<type id="a">
<buy>
<volume>698299009</volume>
<avg>17.94</avg>
<max>18.45</max>
<min>1.00</min>
</buy>
<sell>
<volume>16375234</volume>
<avg>21.03</avg>
<max>24.99</max>
<min>20.78</min>
</sell>
<all>
<volume>714674243</volume>
<avg>18.01</avg>
<max>24.99</max>
<min>1.00</min>
</all>
</type>
</stats>
The php code I am using is as follows:
$xml = simplexml_load_file("values.xml");
$unit_value = $xml->xpath("/stats/type[#id='a']/buy/avg/")->nodeValue;
echo $unit_value;
Please refer documentation here, $xml->xpath should return you the array. The docs also shows an example of how to access text nodes. Below is an excerpt from the docs
<?php
$string = <<<XML
<a>
<b>
<c>text</c>
<c>stuff</c>
</b>
<d>
<c>code</c>
</d>
</a>
XML;
$xml = new SimpleXMLElement($string);
/* Search for <a><b><c> */
$result = $xml->xpath('/a/b/c');
while(list( , $node) = each($result)) {
echo '/a/b/c: ',$node,"\n";
}
/* Relative paths also work... */
$result = $xml->xpath('b/c');
while(list( , $node) = each($result)) {
echo 'b/c: ',$node,"\n";
}
?>
which produces output as
/a/b/c: text
/a/b/c: stuff
b/c: text
b/c: stuff
which is I suppose exactly what you need.
xpath returns an array of SimpleXMLElement objects .. so you can do this :
$unit_value = $xml->xpath("//stats//type[#id='a']//buy//avg");
echo (string)$unit_value[0]; // cast to string not required
Working example here
or if you are using PHP => 5.4 you can do this :
$unit_value = $xml->xpath("//stats//type[#id='a']//buy//avg")[0];
echo $unit_value;
Working example here
Hello i have this part of php code
$google_url = "http://uclassify.com/browse/uClassify/Sentiment/ClassifyText?readkey=jnsdnjdsnjnjsdnjsnjdsd&text=".$text."&version=1.01";
$result = file_get_contents($google_url);
$obj = simplexml_load_string($result);
$zaab = toArray($obj);
echo($zaab);
and the answer i get is
<?xml version="1.0" encoding="UTF-8" ?>
<uclassify xmlns="http://api.uclassify.com/1/ResponseSchema" version="1.01">
<status success="true" statusCode="2000"/>
<readCalls>
<classify id="cls1">
<classification textCoverage="0.6">
<class className="negative" p="0.999984"/> <-----p_value
<class className="positive" p="1.60692e-005"/> <-----p_value
</classification>
</classify>
</readCalls>
</uclassify>
how can i access p_values?
no after updating it gives me an error having to do with toArray()
You can get the all *p*s attribute values by looping through all *class*es like this:
$classes = $obj->readCalls->classify->classification->class;
foreach ($classes as $class) {
$p_val = $class->attributes()->p;
echo $p_val . "<br />";
}
I see you also tried to convert the xml string to array, probably the simplest way to do it is:
$json = json_encode($obj);
$xml_array = json_decode($json,TRUE);
To see the results use:
echo "<pre>";
print_r($xml_array);
echo "</pre>";
Use a xml parser.
http://php.net/manual/en/book.xml.php
I would like to create a new simplified xml based on an existing one:
(using "simpleXml")
<?xml version="1.0" encoding="UTF-8"?>
<xls:XLS>
<xls:RouteInstructionsList>
<xls:RouteInstruction>
<xls:Instruction>Start</xls:Instruction>
</xls:RouteInstruction>
</xls:RouteInstructionsList>
<xls:RouteInstructionsList>
<xls:RouteInstruction>
<xls:Instruction>End</xls:Instruction>
</xls:RouteInstruction>
</xls:RouteInstructionsList>
</xls:XLS>
Because there are always colons in the element-tags, it will mess with "simpleXml", I tried to use the following solution->link.
How can I create a new xml with this structure:
<main>
<instruction>Start</instruction>
<instruction>End</instruction>
</main>
the "instruction-element" gets its content from the former "xls:Instruction-element".
Here is the updated code:
But unfortunately it never loops through:
$source = "route.xml";
$xmlstr = file_get_contents($source);
$xml = #simplexml_load_string($xmlstr);
$new_xml = simplexml_load_string('<main/>');
foreach($xml->children() as $child){
print_r("xml_has_childs");
$new_xml->addChild('instruction', $child->RouteInstruction->Instruction);
}
echo $new_xml->asXML();
there is no error-message, if I leave the "#"…
/* the use of # is to suppress warning */
$xml = #simplexml_load_string($YOUR_RSS_XML);
$new_xml = simplexml_load_string('<main/>');
foreach ($xml->children() as $child)
{
$new_xml->addChild('instruction', $child->RouteInstruction->Instruction);
}
/* to print */
echo $new_xml->asXML();
You could use xpath to simplify things. Without knowing the full details, I don't know if it will work in all cases:
$source = "route.xml";
$xmlstr = file_get_contents($source);
$xml = #simplexml_load_string($xmlstr);
$new_xml = simplexml_load_string('<main/>');
foreach ($xml->xpath('//Instruction') as $instr) {
$new_xml->addChild('instruction', (string) $instr);
}
echo $new_xml->asXML();
Output:
<?xml version="1.0"?>
<main><instruction>Start</instruction><instruction>End</instruction></main>
Edit: The file at http://www.gps.alaingroeneweg.com/route.xml is not the same as the XML you have in your question. You need to use a namespace like:
$xml = #simplexml_load_string(file_get_contents('http://www.gps.alaingroeneweg.com/route.xml'));
$xml->registerXPathNamespace('xls', 'http://www.opengis.net/xls'); // probably not needed
$new_xml = simplexml_load_string('<main/>');
foreach ($xml->xpath('//xls:Instruction') as $instr) {
$new_xml->addChild('instruction', (string) $instr);
}
echo $new_xml->asXML();
Output:
<?xml version="1.0"?>
<main><instruction>Start (Southeast) auf Sihlquai</instruction><instruction>Fahre rechts</instruction><instruction>Fahre halb links - Ziel erreicht!</instruction></main>