PHP: Give An ID to File in XML - php

Im using this code for create a xml file which is listing files' url and descriptions in directory. but i need to add in this xml also number of file. so i want to give to files a number (or ID), like 1 for file 2....n , like counter for every row how i can do this ?
thank you
<?php
$myfeed = new RSSFeed();
// Open the current directory (or specify it)
$dir = opendir ("./");
while (false !== ($file = readdir($dir))) {
if (strpos($file, '.jpg',1)||strpos($file, '.gif',1) ) {
$myfeed->SetItem("http://host.com/images/$file", "$file", "");
}
}
// Output the XML File
$fp = fopen('rss.xml', 'w');
fwrite($fp, $myfeed->output());
fclose($fp);
echo $myfeed->output(); //lets see that
class RSSFeed {
// VARIABLES
// channel vars
var $channel_url;
var $channel_title;
// items
var $items = array();
var $nritems;
// FUNCTIONS
// constructor
function RSSFeed() {
$this->nritems=0;
$this->channel_url='';
$this->channel_title='';
}
// set channel vars
function SetChannel($url, $title, $description, $lang, $copyright, $creator, $subject) {
$this->channel_url=$url;
$this->channel_title=$title;
}
// set item
function SetItem($url, $title, $description) {
$this->items[$this->nritems]['url']=$url;
$this->items[$this->nritems]['title']=$title;
$this->nritems++;
}
// output feed
function Output() {
$output = '<?xml version="1.0" encoding="UTF-8"?>'."\n";
$output .= '<playlist version="0" xmlns = "http://xspf.org/ns/0/">'."\n";
$output .= '<trackList>'."\n";
for($k=0; $k<$this->nritems; $k++) {
$output .= '<track>'."\n";
$output .= '<location>'.$this->items[$k]['url'].'</location>'."\n";
$output .= '<image></image>'."\n";
$output .= '<annotation>'.$this->items[$k]['title'].'</annotation>'."\n";
$output .= '</track>'."\n";
};
$output .= '</trackList>'."\n";
$output .= '</playlist>'."\n";
return $output;
}
};
?>

First up, I don't think creating XML with string-functions is a good idea, rather use a parser like simplexmlor DOM.
Assigning an id to each entry, you could take your $k in function Output():
for($k=0; $k<$this->nritems; $k++) {
$output .= '<track>'."\n";
$output .= "<id>$k</id>\n";
// (...)
$output .= "</track>\n";
}
or add id as attribute to the <track>-node:
$output .= "<track id=\"$k\">\n";

Related

PHP synchronized file read write

i am using the function write_php_ini to write files
see the accepted answer with around 40 upvotes at:
create ini file, write values in PHP
originally i was copying from here:
How to read and write to an ini file with PHP
from the answer that is not accepted, because they looked so similar
the problem is, what if 2 process write to it at the same time? (that is, the second post seems to handle it, whereas the first one does not)
how to avoid this problem?
this is the code:
public static function write_ini_file($assoc_arr, $path, $has_sections=FALSE) {
$content = "";
if ($has_sections) {
foreach ($assoc_arr as $key=>$elem) {
$content .= "[".$key."]\n";
foreach ($elem as $key2=>$elem2) {
if(is_array($elem2))
{
for($i=0;$i<count($elem2);$i++)
{
$content .= $key2."[] = \"".$elem2[$i]."\"\n";
}
}
else if($elem2=="") $content .= $key2." = \n";
else $content .= $key2." = \"".$elem2."\"\n";
}
}
}
else {
foreach ($assoc_arr as $key=>$elem) {
if(is_array($elem))
{
for($i=0;$i<count($elem);$i++)
{
$content .= $key."[] = \"".$elem[$i]."\"\n";
}
}
else if($elem=="") $content .= $key." = \n";
else $content .= $key." = \"".$elem."\"\n";
}
}
if (!$handle = fopen($path, 'w')) {
return false;
}
$success = fwrite($handle, $content);
fclose($handle);
return $success;
}

How do i get the node-names from xml_parser()

I try to pre-sort and slice a big XML file for later processing via xml_parser
function CreateXMLParser($CHARSET, $bareXML = false) {
$CURRXML = xml_parser_create($CHARSET);
xml_parser_set_option( $CURRXML, XML_OPTION_CASE_FOLDING, false);
xml_parser_set_option( $CURRXML, XML_OPTION_TARGET_ENCODING, $CHARSET);
xml_set_element_handler($CURRXML, 'startElement', 'endElement');
xml_set_character_data_handler($CURRXML, 'dataHandler');
xml_set_default_handler($CURRXML, 'defaultHandler');
if ($bareXML) {
xml_parse($CURRXML, '<?xml version="1.0"?>', 0);
}
return $CURRXML;
}
function ChunkXMLBigFile($file, $tag = 'item', $howmany = 1000) {
global $CHUNKON, $CHUNKS, $ITEMLIMIT;
$CHUNKON = $tag;
$ITEMLIMIT = $howmany;
$xml = CreateXMLParser('UTF-8', false);
$fp = fopen($file, "r");
$CHUNKS = 0;
while(!feof($fp)) {
$chunk = fgets($fp, 10240);
xml_parse($xml, $chunk, feof($fp));
}
xml_parser_free($xml);
processChunk();
}
function processChunk() {
global $CHUNKS, $PAYLOAD, $ITEMCOUNT;
if ('' == $PAYLOAD) {
return;
}
$xp = fopen($file = "xmlTemp/slices/slice_".$CHUNKS.".xml", "w");
fwrite($xp, '<?xml version="1.0" ?>'."\n");
fwrite($xp, "<producten>");
fwrite($xp, $PAYLOAD);
fwrite($xp, "</producten>");
fclose($xp);
print "Written ".$file."<br>";
$CHUNKS++;
$PAYLOAD = '';
$ITEMCOUNT = 0;
}
function startElement($xml, $tag, $attrs = array()) {
global $PAYLOAD, $CHUNKS, $ITEMCOUNT, $CHUNKON;
if (!($CHUNKS||$ITEMCOUNT)) {
if ($CHUNKON == strtolower($tag)) {
$PAYLOAD = '';
}
} else {
$PAYLOAD .= "<".$tag;
}
foreach($attrs as $k => $v) {
$PAYLOAD .= " $k=".'"'.addslashes($v).'"';
}
$PAYLOAD .= '>';
}
function endElement($xml, $tag) {
global $CHUNKON, $ITEMCOUNT, $ITEMLIMIT;
dataHandler(null, "<$tag>");
if ($CHUNKON == strtolower($tag)) {
if (++$ITEMCOUNT >= $ITEMLIMIT) {
processChunk();
}
}
}
function dataHandler($xml, $data) {
global $PAYLOAD;
$PAYLOAD .= $data;
}
but how can I access the node-name??
.. I have to sort some items (with n nodes) out, before the slice-file is saved. the the XML is parsed line after line, right? so I have to save the nodes from a whole item temporarely and decide if the item is gonna be written to the file.. is there a way to do this?
Your code is effectively reading the entire source file every time you call the ChunkXMLBigFile function.
After your while loop you have all the elements, which you can then manipulate any way you like.
See the following questions about how to approach this:
How to sort a xml file using DOM
Sort XML nodes with PHP
If you parse the chunks after that in batches of $howmany you are where you want to be.
Tip: there are many examples online where this functionality is presented in an Object Orient Programming (OOP) approach where all the functions are inside a class. This would also eliminate the need of global variables which can cause some (read: a lot) of frustrations and confusion.

Why is this loop running indefinitely?

I have code like this, it reads XML document and copies it to a differently formatted XML.
$new = '<prestashop>';
while ($xml_reader->read() and $xml_reader->name !== 'product');
while ($xml_reader->name === 'product') // dla kazdego produktu
{
$node = new SimpleXMLElement($xml_reader->readOuterXML());
$new .= '<product>';
foreach ($this->columns as $out => $in) // dla kazdej kolumny xml
{
if ($node->$xml !== '') // jesli ma wartosc
{
$new .= "<{$out}>{$node->$in}</{$out}>";
}
else
{
$new .= "<{$out}/>";
}
}
$new .= '</product>';
}
$new .= '</prestashop>';
The XML has this stucture: <product>...</product><product>...</product>. I checked whatever I could and the error is probably in the while.
#edit: I use PHP's XML Reader to get a node one by one and then SimpleXML to deal with the node itself.
It was dumb. I forgot $xml_reader->next('product'); so while loop was always going around the same node all over again.

How to generate xml in codeigniter

I am trying to generate xml from database query.
Here is generated xml link: http://mydeal.ge/api/xml
But when I try to parse this xml, I get an error: http://wallsparade.com/test.php.
My code is:
public function xml()
{
$res = $this->db->query('custom query');
if($res->num_rows() > 0)
{$output = '<?xml version="1.0"?>'. "\n";
$output .= "<deals>";
foreach($res->result() as $item)
{
$output .= "<sale id = '".$item->id."'>";
$output .= "<link>".$item->link."</link>";
$output .= "<title>".urlencode($item->title)."</title>";
$output .= "<image>".$item->image."</image>";
$output .= "<text>".urlencode($item->text)."</text>";
$output .= "<time>".$item->time."</time>";
$output .= "<price>".$item->price."</price>";
$output .= "<parcent>".$item->parcent."</parcent>";
$output .= "</sale>";
}
$output .= '</deals>';
}
echo $output;
}
What is problem?
Looks like you are developing an API. Why don't you use the RESTServer plugin for CodeIgniter?
It's all handled for you and you don't have to worry about the format. You can choose to output in JSON or XML.
Plugin developed by Phil: https://github.com/philsturgeon/codeigniter-restserver
I believe the most practical, logical and error free way to generate an XML is to create a DOMDocument as suggested by Eineki in this answer, allowing the xmltree to be searched through an xpath query.
With this said, some years ago Dan Simmons created a single MY_xml_helper.php that you can just copy to your application/helpers folder directly. Here's the entire code without comments:
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
if ( ! function_exists('xml_dom'))
{
function xml_dom()
{
return new DOMDocument('1.0', 'UTF-8');
}
}
if ( ! function_exists('xml_add_child'))
{
function xml_add_child($parent, $name, $value = NULL, $cdata = FALSE)
{
if($parent->ownerDocument != "")
{
$dom = $parent->ownerDocument;
}
else
{
$dom = $parent;
}
$child = $dom->createElement($name);
$parent->appendChild($child);
if($value != NULL)
{
if ($cdata)
{
$child->appendChild($dom->createCdataSection($value));
}
else
{
$child->appendChild($dom->createTextNode($value));
}
}
return $child;
}
}
if ( ! function_exists('xml_add_attribute'))
{
function xml_add_attribute($node, $name, $value = NULL)
{
$dom = $node->ownerDocument;
$attribute = $dom->createAttribute($name);
$node->appendChild($attribute);
if($value != NULL)
{
$attribute_value = $dom->createTextNode($value);
$attribute->appendChild($attribute_value);
}
return $node;
}
}
if ( ! function_exists('xml_print'))
{
function xml_print($dom, $return = FALSE)
{
$dom->formatOutput = TRUE;
$xml = $dom->saveXML();
if ($return)
{
return $xml;
}
else
{
echo $xml;
}
}
}
Notice that you set the encoding like this: new DOMDocument('1.0', 'UTF-8');. Here's an example:
$this->load->helper('xml');
$dom = xml_dom();
$book = xml_add_child($dom, 'book');
xml_add_child($book, 'title', 'Hyperion');
$author = xml_add_child($book, 'author', 'Dan Simmons');
xml_add_attribute($author, 'birthdate', '1948-04-04');
xml_add_child($author, 'name', 'Dan Simmons');
xml_add_child($author, 'info', 'The man that wrote MY_xml_helper');
xml_print($dom);
Would simply output:
<?xml version="1.0" encoding="UTF-8"?>
<book>
<title>Hyperion</title>
<author birthdate="1948-04-04">
<name>Dan Simmons</name>
<info>The man that wrote MY_xml_helper</info>
</author>
</book>
The xml_print either echos or returns the $xml->saveXML().
Notice: you can still use the one and only function from the default XML helper from CodeIgniter: xml_convert("<title>'Tom' & \"Jerry\"") which just outputs: <title>&apos;Tom&apos; & "Jerry".
Your XML document have to start with:
<?xml version="1.0"?>
no white symbols no "spaces" no "enters". Your document starts with line-break as the error message says:
Warning: simplexml_load_file() [function.simplexml-load-file]: http://mydeal.ge/api/xml:2: parser error : XML declaration allowed only at the start of the document in /home1/stinky/public_html/test.php on line 2
and delete spaces from this line:
$output .= "<sale id = '".$item->id."'>";
$output .= "<sale id='".$item->id."'>";
You shouldn't write XML through string concatenation when you have built-in library such as SimpleXMLElement available.
Try to change your code to this. I couldn't test it myself but it should work as expected:
<?php
public function xml()
{
$res = $this->db->query('custom query');
if ($res->num_rows() > 0) {
$sxe = new SimpleXMLElement();
$deals = $sxe->addChild('deals');
foreach($res->result() as $item) {
$sale = $deals->addChild('sale');
$sale->addAttribute('id', $item->id);
$sale->addChild('link', $item->link);
$sale->addChild('title', urlencode($item->title));
$sale->addChild('image', $item->image);
$sale->addChild('text', urlencode($item->text));
$sale->addChild('time', $item->time);
$sale->addChild('price', $item->price);
$sale->addChild('parcent', $item->parcent);
}
}
echo $sxe->saveXML();
}

PHP - How to display the contents of an address that contains an array

How do you display the contents of an address that contains an array?
Example:
class ConferenceInfo {
var $confID;
var $confName;
var $divisons = array();
/* display an address in HTML */
function display() {
$output = '';
$output .= $this->confID;
$output .= $this->confName;
foreach($this->divisons as $value) { // I know this is incorrect
$output .= $value;
}
$output .= '<br/>';
return $output;
}
}
And the PHP code:
$conf = new ConferenceInfo;
$conf->confID = $someValue1;
$conf->confName = $someValue2;
$conf->divisons[] = $someValue3; // this will eventually loop and fill in multiple values
echo $conf->display();
Data examples would be:
confID = 1<br/>
confName = Eastern<br/>
dvisions = Atlantic, Central, Northeast
Expected output from display() would be:
1EasternAtlanticCentralNortheast
class ConferenceInfo {
var $confID;
var $confName;
var $divisons = array();
/* display an address in HTML */
function display() {
$output = '';
$output .= $this->confID;
$output .= $this->confName;
foreach($this->divisons as $value) {
$output .= $value;
}
$output .= '<br/>';
return $output;
}
}
$conf = new ConferenceInfo;
$conf->confID = 1;
$conf->confName = "Eastern";
$conf->divisons = array("Atlantic", "Central", "Northeast");
echo $conf->display();

Categories