4

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?

tshepang
  • 12,111
  • 21
  • 91
  • 136
Gia Nebieridze
  • 161
  • 4
  • 5
  • 15

4 Answers4

2

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

Kong Jin Jie
  • 535
  • 5
  • 11
2

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: &lt;title&gt;&apos;Tom&apos; &amp; &quot;Jerry&quot;.

Community
  • 1
  • 1
Armfoot
  • 4,663
  • 5
  • 45
  • 60
1

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."'>";
Michal
  • 3,584
  • 9
  • 47
  • 74
0

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();
}
Rolando Isidoro
  • 4,983
  • 2
  • 31
  • 43