• 首页
  • vue
  • TypeScript
  • JavaScript
  • scss
  • css3
  • html5
  • php
  • MySQL
  • redis
  • jQuery
  • 位置: php 中文手册 -> php 外部扩展库

    XMLWriter类

    此扩展需要 libxml PHP 扩展。这表示需要使用--enable-libxml,尽管这将隐式完成因为 libxml 是缺省开启的。

    安装

    XMLWriter扩展最初是PHP 5的PECL扩展。它后来被添加到PHP 5.1.2的PHP源代码(捆绑)中。默认情况下启用此扩展。

    此扩展默认为启用,编译时可通过下列选项禁用: --disable-xmlwriter

    XMLWriter扩展的过程版本使用了一个资源:由XMLWriter_open_memory()或XMLWriter_open_uri()返回。

    创建简单的XML文档

    <?php
    $xw = xmlwriter_open_memory();
    xmlwriter_set_indent($xw, 1);
    $res = xmlwriter_set_indent_string($xw, ' ');
    xmlwriter_start_document($xw, '1.0', 'UTF-8');
    // A first element
    xmlwriter_start_element($xw, 'tag1');
    // Attribute 'att1' for element 'tag1'
    xmlwriter_start_attribute($xw, 'att1');
    xmlwriter_text($xw, 'valueofatt1');
    xmlwriter_end_attribute($xw);
    xmlwriter_write_comment($xw, 'this is a comment.');
    // Start a child element
    xmlwriter_start_element($xw, 'tag11');
    xmlwriter_text($xw, 'This is a sample text, ä');
    xmlwriter_end_element($xw); // tag11
    xmlwriter_end_element($xw); // tag1
    // CDATA
    xmlwriter_start_element($xw, 'testc');
    xmlwriter_write_cdata($xw, "This is cdata content");
    xmlwriter_end_element($xw); // testc
    xmlwriter_start_element($xw, 'testc');
    xmlwriter_start_cdata($xw);
    xmlwriter_text($xw, "test cdata2");
    xmlwriter_end_cdata($xw);
    xmlwriter_end_element($xw); // testc
    // A processing instruction
    xmlwriter_start_pi($xw, 'php');
    xmlwriter_text($xw, '$foo=2;echo $foo;');
    xmlwriter_end_pi($xw);
    xmlwriter_end_document($xw);
    echo xmlwriter_output_memory($xw);
    
    <?xml version="1.0" encoding="UTF-8"?>
    <tag1 att1="valueofatt1">
     <!--this is a comment.-->
     <tag11>This is a sample text, ä</tag11>
    </tag1>
    <testc><![CDATA[This is cdata content]]></testc>
    <testc><![CDATA[test cdata2]]></testc>
    <?php $foo=2;echo $foo;?>
    

    使用XML命名空间

    <?php
    $xw = xmlwriter_open_memory();
    xmlwriter_set_indent($xw, 1);
    $res = xmlwriter_set_indent_string($xw, ' ');
    xmlwriter_start_document($xw, '1.0', 'UTF-8');
    // A first element
    xmlwriter_start_element_ns($xw,'prefix', 'books', 'uri');
    xmlwriter_start_attribute($xw, 'isbn');
    xmlwriter_start_attribute_ns($xw, 'prefix', 'isbn', 'uri');
    xmlwriter_end_attribute($xw);
    xmlwriter_end_attribute($xw);
    xmlwriter_text($xw, 'book1');
    xmlwriter_end_element($xw);
    xmlwriter_end_document($xw);
    echo xmlwriter_output_memory($xw);
    
    <?xml version="1.0" encoding="UTF-8"?>
    <prefix:books isbn="" prefix:isbn="" xmlns:prefix="uri">book1</prefix:books>
    

    使用XMLWriter对象API

    <?php
    $xw = new XMLWriter();
    $xw->openMemory();
    $xw->startDocument("1.0");
    $xw->startElement("book");
    $xw->text("example");
    $xw->endElement();
    $xw->endDocument();
    echo $xw->outputMemory();
    
    <?xml version="1.0"?>
    <book>example</book>
    
    I had a feature to the XmlConstruct class by Alexandre Aprica. Now you can use nested array to generate nested xml elements.
    <?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();
        $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(){
        $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(
     '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();
    ?>
    
    Using XMLWriter to create a WAP page:
    <?php
    $memory = xmlwriter_open_memory();
    xmlwriter_start_document($memory,'1.0','UTF-8');
    xmlwriter_start_dtd($memory,'html','-//WAPFORUM//DTD XHTML Mobile 1.0//EN', 'http://www.wapforum.org/DTD/xhtml-mobile10.dtd');
    xmlwriter_end_dtd($memory);
    xmlwriter_start_element ($memory,'html'); // <html>
    xmlwriter_write_attribute( $memory, 'xmlns', 'http://www.wapforum.org/DTD/xhtml-mobile10.dtd');
    xmlwriter_write_attribute( $memory, 'xm:lang', 'en');
    xmlwriter_start_element($memory,'head'); // <head>
    xmlwriter_write_element ($memory,'title', 'Test WAP Document');
    xmlwriter_end_element($memory); // </head>
    xmlwriter_start_element($memory,'body'); // <body>
    xmlwriter_start_element($memory,'ol'); // <ol>
    xmlwriter_write_element ($memory,'li', 'One Item');
    xmlwriter_write_element ($memory,'li', 'Another Item');
    xmlwriter_write_element ($memory,'li', 'Another Item');
    xmlwriter_end_element($memory); // </ol>
    xmlwriter_end_element($memory); // </body>
    xmlwriter_end_element($memory); // </html>
    xmlwriter_end_dtd($memory);
    $xml = xmlwriter_output_memory($memory,true);
    ?>
    Output:
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.0//EN" "http://www.wapforum.org/DTD/xhtml-mobile10.dtd">
    <html xmlns="http://www.wapforum.org/DTD/xhtml-mobile10.dtd" xm:lang="en">
    <head>
    <title>Test WAP Document</title>
    </head>
    <body>
    <ol>
    <li>One Item</li>
    <li>Another Item</li>
    <li>Another Item</li>
    </ol>
    </body>
    </html>
    Inspired in the XmlConstruct.
    <?php
    class XLIFFConstruct 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
       */
       var $_phrase_id=1;
      public function __construct(){
        $this->openMemory();
        $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('xliff');
        $this->writeAttribute('version', '1.0');
        $this->startElement('file');
        $this->writeAttribute('original', 'global');
        $this->writeAttribute('source-language', 'es');
        $this->writeAttribute('datatype', 'plaintext');
        $this->writeAttribute('date', date('c'));
        $this->startElement('body');
      }
      public function addPhrase($source, $target){
        $this->startElement('trans-unit');
       $this->writeAttribute('id', $this->_phrase_id++);
        $this->startElement('source');
        $this->text($source);
       $this->endElement();
        $this->startElement('target');
       $this->text($target);
       $this->endElement();
       $this->endElement();
      }
      public function getDocument(){
        $this->endElement();
        $this->endElement();
        $this->endElement();
        $this->endDocument();
        return $this->outputMemory();
      }
      public function output(){
        header('Content-type: text/xml');
        echo $this->getDocument();
      }
    }
    ?>
    Example:
    <?php
    $xliff = new XLIFFConstruct();
    $xliff->addPhrase('source','target');
    $xliff->addPhrase('add','añadir');
    $xliff->addPhrase('open','abrir');
    $xliff->addPhrase('change','cambiar');
    $xliff->addPhrase('new','nuevo');
    $xliff->addPhrase('save','guardar');
    echo $xliff->getDocument();
    ?>
    
    XML allows for repeated nodes that an array does not support in its associative index. To account for this we can use numerically indexed arrays.
    $array = array(
      'element' => array(
        array('node' => 'some value'), 
        array('node' => 'some other value')
      ), 
      'key' => 'value'
    );
    This requires that we change the fromArray() method in the class below to check for numeric indexes and throw them away.
    public function fromArray(array $array)
     {
      foreach ($array as $key=>$val) {
        if (is_array($val)) {
          if (is_numeric($key)) {
            // numeric keys aren't allowed so we'll skip the key
            $this->fromArray($val);
          } else {
            $this->startElement($key);
            $this->fromArray($val);
            $this->endElement();
          }
        } else {
          $this->writeElement($key, $val);
        }
      }
    }
    setElement in the previous example does exactly the same thing as already existing writeElement.
    How to generate a simple XML document for a XSL-Transformation purpose.
    We have 3 files: 
    - 'index.php' : output a XML document
    - 'XmlConstruct.class.php' : allow to construct a XML document with 'xmlwriter'
    - 'index.xsl' : contains a XSLT document
    Contents of the file 'index.php' :
    <?php
    $contents = array('page_title' => 'Generate a XHTML page from XML+XSLT files',
              'welcome_msg' => 'Simple XHTML document from XML+XSLT files!');
    require('XmlConstruct.class.php');
    $XmlConstruct = new XmlConstruct('rootElement', 'index.xsl');
    $XmlConstruct->fromArray($contents);
    $XmlConstruct->output();
    ?>
    Contents of the file 'XmlConstruct.class.php' :
    <?php
    /**
     * Construct a simple XML document.
     * This class inherits from the (PHP) class 'xmlwriter'.
     * You will need at least PHP 5.1.2
     *
     * @author Alexandre Arica
     * @since 16 April 2006
     * @version 1.0 modified the 16 April 2006
     */
    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();
        $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 => $text){
            $this->setElement($index, $text);
          }
        }
      }
      /**
       * 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();
      }
      
    }
    ?>
    Contents of the file 'index.xsl' :
    <?xml version="1.0" encoding="utf-8"?>
    <xsl:stylesheet 
     version="1.0" 
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
     xmlns="http://www.w3.org/TR/xhtml1/strict">
    <xsl:output 
      method="html" 
      encoding="utf-8"
    />
    <xsl:template match="rootElement">
    <html xmlns="http://www.w3.org/1999/xhtml">
        <head>
          <title><xsl:value-of select="page_title" /></title>
        </head>
        
        <body>
          <xsl:value-of select="welcome_msg" />
        </body>
        
    </html>
    </xsl:template>
    </xsl:stylesheet>
    If you want your XML-output to be seen as XML by the browser, you need to modify your header. The XmlWriter does not do this for you! Therefore, the first line of your script should be:
    <?php header("Content-type: text/xml"); ?>