0

I'm following this example in XMLWiter functions, but I'm looking for a way to write the output to a file (sample.xml), I walked through many threads, with no luck. I know that the solution could be easy, but I'm working on PHP only from one month. Can anyone help?

<?php

class XmlConstruct extends XMLWriter
{

/**
 * Constructor.
 * @param string $prm_rootElementName A root element's name of a current xml document
 * @param string $prm_xsltFilePath Path of a XSLT file.
 * @access public
 * @param null
 */
public function __construct($prm_rootElementName, $prm_xsltFilePath=''){
    $this->openMemory(); // change this with $this->openURI('your_file.xml');
    $this->setIndent(true);
    $this->setIndentString(' ');
    $this->startDocument('1.0', 'UTF-8');

    if($prm_xsltFilePath){
        $this->writePi('xml-stylesheet', 'type="text/xsl" href="'.$prm_xsltFilePath.'"');
    }

    $this->startElement($prm_rootElementName);
}

/**
 * Set an element with a text to a current xml document.
 * @access public
 * @param string $prm_elementName An element's name
 * @param string $prm_ElementText An element's text
 * @return null
 */
public function setElement($prm_elementName, $prm_ElementText){
    $this->startElement($prm_elementName);
    $this->text($prm_ElementText);
    $this->endElement();
}

/**
 * Construct elements and texts from an array.
 * The array should contain an attribute's name in index part
 * and a attribute's text in value part.
 * @access public
 * @param array $prm_array Contains attributes and texts
 * @return null
 */
public function fromArray($prm_array){
  if(is_array($prm_array)){
    foreach ($prm_array as $index => $element){
      if(is_array($element)){
        $this->startElement($index);
        $this->fromArray($element);
        $this->endElement();
      }
      else
        $this->setElement($index, $element);

    }
  }
}

/**
 * Return the content of a current xml document.
 * @access public
 * @param null
 * @return string Xml document
 */
public function getDocument(){     //comment this function
    $this->endElement();
    $this->endDocument();
    return $this->outputMemory();
}

/**
 * Output the content of a current xml document.
 * @access public
 * @param null
 */
public function output(){               //comment this function
    header('Content-type: text/xml');
    echo $this->getDocument();
}


}

//Example:

$contents = array(
  'page_title' => 'Generate a XHTML page from XML+XSLT files',
  'welcome_msg' => 'Simple XHTML document from XML+XSLT files!',
  'prova' => array(
    "gino" => array(
      "innergino" => "gino inner value"
     ),
   "filo" => "filodata"
),
);

$XmlConstruct = new XmlConstruct('root');
$XmlConstruct->fromArray($contents);
$XmlConstruct->output();              // comment this line

?>
uomopalese
  • 471
  • 1
  • 5
  • 21
  • http://stackoverflow.com/questions/486757/how-to-generate-xml-file-dynamically-using-php – Qarib Haider Aug 03 '14 at 14:04
  • Hi, many thanks for your answer, I tried that, but the output is pretty different from this... I got one single long line in the file, and also in the browser i see only text, whilst this is recognized as XML (try) ;) – uomopalese Aug 03 '14 at 14:28
  • I figured out how to save the content into a file: basically i need to change the line: `$this->openMemory();` in the `public function __construct`, with: `$this->openURI('_test_0010.xml');` and so I have to comment both the `public function getDocument()` and `public function output()` and the last line: `$XmlConstruct->output();`. Hope this can help someone else, i find this way to write nested xml elements very handy. – uomopalese Aug 04 '14 at 14:17

1 Answers1

0

Finally, (after reading lot of pages and tried a lot of examples), I followed my way to find a solution. First of all, as explained in this post, XMLWriter is the best choice for big xml files (as in my case), this is why, after a deep look, i didn't follow the solution based on the DOM as proposed by @Seyed Quarib, although has been very instructive to read that thread. Another problem was that all my xml content needed to be wrapped in a tag with a namespace like <p:TagName>. I found out i needed to use XMLWriter::startElementNS and also XMLWriter::writeAttribute. As I said, i find this way tho output nested xml tag very handy for my purpose (that was very specific). Here is the code, hope someone else can find it usefull:

<?php header('Content-Type: text/html; charset=utf-8') ?>
    <div class="save" style="width:100%; height:100px;">File saved</div>
    <?php

    class XmlConstruct extends XMLWriter
    {

    /**
    * Constructor.
    * @param string $prm_rootElementName A root element's name of a current xml document
    * @param string $prm_xsltFilePath Path of a XSLT file.
    * @access public
    * @param null
    */
    public function __construct($prm_rootElementName, $prm_xsltFilePath=''){
      $this->openURI('save-to-file.xml'); // changed
      $this->setIndent(true);
      $this->setIndentString(' ');
      $this->startDocument('1.0', 'UTF-8');

    if($prm_xsltFilePath){
      $this->writePi('xml-stylesheet', 'type="text/xsl" href="'.$prm_xsltFilePath.'"');
    }

      //$this->startElement($prm_rootElementName); // changed
      $this->startElementNS("p", "TagName", null);
      $this->writeAttribute ("version", "1.0");
      $this->writeAttribute ("xmlns:ds", "http://www.w3.org/2000/09/xmldsig#");
      $this->writeAttribute ("xmlns:p", "http://www.xxxxx.gov.it/sdi/xxxxx/v1.0");
      $this->writeAttribute ("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
    }

    /**
    * Set an element with a text to a current xml document.
    * @access public
    * @param string $prm_elementName An element's name
    * @param string $prm_ElementText An element's text
    * @return null
    */
    public function setElement($prm_elementName, $prm_ElementText){
      $this->startElement($prm_elementName);
      $this->text($prm_ElementText);
      $this->endElement();
    }

    /**
    * Construct elements and texts from an array.
    * The array should contain an attribute's name in index part
    * and a attribute's text in value part.
    * @access public
    * @param array $prm_array Contains attributes and texts
    * @return null
    */
    public function fromArray($prm_array){
      if(is_array($prm_array)){
        foreach ($prm_array as $index => $element){
          if(is_array($element)){
            $this->startElement($index);
            $this->fromArray($element);
            $this->endElement();
          }
          else
            $this->setElement($index, $element);

        }
      }
    }

    /**
    * Return the content of a current xml document.
    * @access public
    * @param null
    * @return string Xml document
    */

    public function getDocument(){     
      $this->endElement();
      $this->endDocument();
      return $this->outputMemory();
    }

    /**
    * Output the content of a current xml document.
    * @access public
    * @param null
    */

    public function output(){              
      header('Content-type: text/xml');
      echo $this->getDocument();
    }


    }

    //Example:

    $contents = array(
      'prova' => array(
        "gino" => array(
          "innergino" => "gino inner value",
          "innergino2" => "gino inner another value"
        ),
        "filo" => "filodata",
        "arrays" => array (
          "inner-arrays" => array (
            "one-inner-array" => array (
              "inner-content-one" => "one",
              "inner-content-two" => "two"
            ),
            "two-inner-array" => array (
              "inner-content-one" => "one",
              "inner-content-two" => "two"
            ),
            "three-inner-array" => array (
              "inner-content-one" => "one",
              "inner-content-two" => "two"
            ),
          )
        )
      )
    );

    $XmlConstruct = new XmlConstruct('root');
    $XmlConstruct->fromArray($contents);
    $XmlConstruct->getDocument();           // cahnged

    ?>

And the output is:

<?xml version="1.0" encoding="UTF-8"?>
<p:TagName version="1.0" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:p="http://www.xxxxx.gov.it/sdi/xxxxx/v1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <prova>
    <gino>
      <innergino>gino inner value</innergino>
      <innergino2>gino inner another value</innergino2>
    </gino>
    <filo>filodata</filo>
    <arrays>
       <inner-arrays>
         <one-inner-array>
           <inner-content-one>one</inner-content-one>
           <inner-content-two>two</inner-content-two>
        </one-inner-array>
        <two-inner-array>
          <inner-content-one>one</inner-content-one>
          <inner-content-two>two</inner-content-two>
        </two-inner-array>
        <three-inner-array>
          <inner-content-one>one</inner-content-one>
          <inner-content-two>two</inner-content-two>
        </three-inner-array>
      </inner-arrays>
    </arrays>
  </prova>
</p:TagName>
Community
  • 1
  • 1
uomopalese
  • 471
  • 1
  • 5
  • 21