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

?>
3
  • stackoverflow.com/questions/486757/… Commented Aug 3, 2014 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) ;) Commented Aug 3, 2014 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. Commented Aug 4, 2014 at 14:17

1 Answer 1

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>
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.