This version of the page http://ua.php.net/book.dom (0.0.0.0) stored by archive.org.ua. It represents a snapshot of the page as of 2009-04-05. The original page over time could change.
PHP: DOM - Manual
downloads | documentation | faq | getting help | mailing lists | licenses | wiki | reporting bugs | php.net sites | links | conferences | my php.net

search for in the

  • PHP Manual
  • Function Reference
  • XML Manipulation
  • DOM
  • DOM XML
  • libxml
  • qtdom
  • SDO
  • SDO-DAS-Relational
  • SDO DAS XML
  • SimpleXML
  • WDDX
  • XML Parser
  • XMLReader
  • XMLWriter
  • XSL
  • XSLT
Introduction XML Manipulation
Last updated: Fri, 03 Apr 2009

view this page in

Document Object Model

  • Introduction
  • Installing/Configuring
    • Requirements
    • Installation
    • Runtime Configuration
    • Resource Types
  • Predefined Constants
  • DOMAttr — The DOMAttr class
    • DOMAttr::__construct — Creates a new DOMAttr object
    • DOMAttr::isId — Checks if attribute is a defined ID
  • DOMCharacterData — The DOMCharacterData class
    • DOMCharacterData::appendData — Append the string to the end of the character data of the node
    • DOMCharacterData::deleteData — Remove a range of characters from the node
    • DOMCharacterData::insertData — Insert a string at the specified 16-bit unit offset
    • DOMCharacterData::replaceData — Replace a substring within the DOMCharacterData node
    • DOMCharacterData::substringData — Extracts a range of data from the node
  • DOMComment — The DOMComment class
    • DOMComment::__construct — Creates a new DOMComment object
  • DOMDocument — The DOMDocument class
    • DOMDocument::__construct — Creates a new DOMDocument object
    • DOMDocument::createAttribute — Create new attribute
    • DOMDocument::createAttributeNS — Create new attribute node with an associated namespace
    • DOMDocument::createCDATASection — Create new cdata node
    • DOMDocument::createComment — Create new comment node
    • DOMDocument::createDocumentFragment — Create new document fragment
    • DOMDocument::createElement — Create new element node
    • DOMDocument::createElementNS — Create new element node with an associated namespace
    • DOMDocument::createEntityReference — Create new entity reference node
    • DOMDocument::createProcessingInstruction — Creates new PI node
    • DOMDocument::createTextNode — Create new text node
    • DOMDocument::getElementById — Searches for an element with a certain id
    • DOMDocument::getElementsByTagName — Searches for all elements with given tag name
    • DOMDocument::getElementsByTagNameNS — Searches for all elements with given tag name in specified namespace
    • DOMDocument::importNode — Import node into current document
    • DOMDocument::load — Load XML from a file
    • DOMDocument::loadHTML — Load HTML from a string
    • DOMDocument::loadHTMLFile — Load HTML from a file
    • DOMDocument::loadXML — Load XML from a string
    • DOMDocument::normalizeDocument — Normalizes the document
    • DOMDocument::registerNodeClass — Register extended class used to create base node type
    • DOMDocument::relaxNGValidate — Performs relaxNG validation on the document
    • DOMDocument::relaxNGValidateSource — Performs relaxNG validation on the document
    • DOMDocument::save — Dumps the internal XML tree back into a file
    • DOMDocument::saveHTML — Dumps the internal document into a string using HTML formatting
    • DOMDocument::saveHTMLFile — Dumps the internal document into a file using HTML formatting
    • DOMDocument::saveXML — Dumps the internal XML tree back into a string
    • DOMDocument::schemaValidate — Validates a document based on a schema
    • DOMDocument::schemaValidateSource — Validates a document based on a schema
    • DOMDocument::validate — Validates the document based on its DTD
    • DOMDocument::xinclude — Substitutes XIncludes in a DOMDocument Object
  • DOMDocumentFragment — The DOMDocumentFragment class
    • DOMDocumentFragment::appendXML — Append raw XML data
  • DOMDocumentType — The DOMDocumentType class
  • DOMElement — The DOMElement class
    • DOMElement::__construct — Creates a new DOMElement object
    • DOMElement::getAttribute — Returns value of attribute
    • DOMElement::getAttributeNode — Returns attribute node
    • DOMElement::getAttributeNodeNS — Returns attribute node
    • DOMElement::getAttributeNS — Returns value of attribute
    • DOMElement::getElementsByTagName — Gets elements by tagname
    • DOMElement::getElementsByTagNameNS — Get elements by namespaceURI and localName
    • DOMElement::hasAttribute — Checks to see if attribute exists
    • DOMElement::hasAttributeNS — Checks to see if attribute exists
    • DOMElement::removeAttribute — Removes attribute
    • DOMElement::removeAttributeNode — Removes attribute
    • DOMElement::removeAttributeNS — Removes attribute
    • DOMElement::setAttribute — Adds new attribute
    • DOMElement::setAttributeNode — Adds new attribute node to element
    • DOMElement::setAttributeNodeNS — Adds new attribute node to element
    • DOMElement::setAttributeNS — Adds new attribute
    • DOMElement::setIdAttribute — Declares the attribute specified by name to be of type ID
    • DOMElement::setIdAttributeNode — Declares the attribute specified by node to be of type ID
    • DOMElement::setIdAttributeNS — Declares the attribute specified by local name and namespace URI to be of type ID
  • DOMEntity — The DOMEntity class
  • DOMEntityReference — The DOMEntityReference class
    • DOMEntityReference::__construct — Creates a new DOMEntityReference object
  • DOMException — The DOMException class
  • DOMImplementation — The DOMImplementation class
    • DOMImplementation::__construct — Creates a new DOMImplementation object
    • DOMImplementation::createDocument — Creates a DOMDocument object of the specified type with its document element
    • DOMImplementation::createDocumentType — Creates an empty DOMDocumentType object
    • DOMImplementation::hasFeature — Test if the DOM implementation implements a specific feature
  • DOMNamedNodeMap — The DOMNamedNodeMap class
    • DOMNamedNodeMap::getNamedItem — Retrieves a node specified by name
    • DOMNamedNodeMap::getNamedItemNS — Retrieves a node specified by local name and namespace URI
    • DOMNamedNodeMap::item — Retrieves a node specified by index
  • DOMNode — The DOMNode class
    • DOMNode::appendChild — Adds new child at the end of the children
    • DOMNode::cloneNode — Clones a node
    • DOMNode::hasAttributes — Checks if node has attributes
    • DOMNode::hasChildNodes — Checks if node has children
    • DOMNode::insertBefore — Adds a new child before a reference node
    • DOMNode::isDefaultNamespace — Checks if the specified namespaceURI is the default namespace or not
    • DOMNode::isSameNode — Indicates if two nodes are the same node
    • DOMNode::isSupported — Checks if feature is supported for specified version
    • DOMNode::lookupNamespaceURI — Gets the namespace URI of the node based on the prefix
    • DOMNode::lookupPrefix — Gets the namespace prefix of the node based on the namespace URI
    • DOMNode::normalize — Normalizes the node
    • DOMNode::removeChild — Removes child from list of children
    • DOMNode::replaceChild — Replaces a child
  • DOMNodeList — The DOMNodeList class
    • DOMNodelist::item — Retrieves a node specified by index
  • DOMNotation — The DOMNotation class
  • DOMProcessingInstruction — The DOMProcessingInstruction class
    • DOMProcessingInstruction::__construct — Creates a new DOMProcessingInstruction object
  • DOMText — The DOMText class
    • DOMText::__construct — Creates a new DOMText object
    • DOMText::isWhitespaceInElementContent — Indicates whether this text node contains whitespace
    • DOMText::splitText — Breaks this node into two nodes at the specified offset
  • DOMXPath — The DOMXPath class
    • DOMXPath::__construct — Creates a new DOMXPath object
    • DOMXPath::evaluate — Evaluates the given XPath expression and returns a typed result if possible.
    • DOMXPath::query — Evaluates the given XPath expression
    • DOMXPath::registerNamespace — Registers the namespace with the DOMXPath object
  • DOM Functions
    • dom_import_simplexml — Gets a DOMElement object from a SimpleXMLElement object


Introduction XML Manipulation
Last updated: Fri, 03 Apr 2009
 
add a note User Contributed Notes
DOM
xwisdom at yahoo dot com
24-Mar-2009 04:49
Hello,

Here's another way you can  get the inner and outer html content of a element:

<?php
// code taken from the Raxan PDI framework
// returns the html content of an element
protected function nodeContent($n, $outer=false) {
   
$d = new DOMDocument('1.0');
   
$b = $d->importNode($n->cloneNode(true),true);
   
$d->appendChild($b); $h = $d->saveHTML();
   
// remove outter tags
   
if (!$outer) $h = substr($h,strpos($h,'>')+1,-(strlen($n->nodeName)+4));
    return
$h;
}
?>

 There are lots of other PHP DOM manipulation and traversing APIs available at the website. See here http://raxanpdi.com/pdi-overview.html
Junior
20-Mar-2009 09:26
innerHTML in PHP DOM

<?php
function DOMinnerHTML($element)
{
   
$innerHTML = "";
   
$children = $element->childNodes;
    foreach (
$children as $child)
    {
       
$tmp_dom = new DOMDocument();
       
$tmp_dom->appendChild($tmp_dom->importNode($child, true));
       
$innerHTML.=trim($tmp_dom->saveHTML());
    }
    return
$innerHTML;
}
?>

Example:

<?php
$dom
= new DOMDocument();
$dom->load($html_string);
$dom->preserveWhiteSpace = false;

$domTable = $dom->getElementsByTagName("table");

foreach (
$domTable as $tables)
{
    echo
DOMinnerHTML($tables);
}
?>
nospam at ya dot ru
06-Jan-2009 06:18
<?PHP
function dom2array_full($node){
   
$result = array();
    if(
$node->nodeType == XML_TEXT_NODE) {
       
$result = $node->nodeValue;
    }
    else {
        if(
$node->hasAttributes()) {
           
$attributes = $node->attributes;
            if(!
is_null($attributes)) 
                foreach (
$attributes as $index=>$attr
                   
$result[$attr->name] = $attr->value;
        }
        if(
$node->hasChildNodes()){
           
$children = $node->childNodes;
            for(
$i=0;$i<$children->length;$i++) {
               
$child = $children->item($i);
                if(
$child->nodeName != '#text')
                if(!isset(
$result[$child->nodeName]))
                   
$result[$child->nodeName] = dom2array($child);
                else {
                   
$aux = $result[$child->nodeName];
                   
$result[$child->nodeName] = array( $aux );
                   
$result[$child->nodeName][] = dom2array($child);
                }
            }
        }
    }
    return
$result;
}
?>
fantasyman3000 at gmail dot com
06-Dec-2008 01:37
In response to "simlee at indiana dot edu",
- First of all thanks for sharing your funciton.
- It didn't work for me so i rewrite it from scratch using different method.

Here is the new version, hope it helps someone :

<?php
/**
* result sample : /html[1]/body[1]/span[1]/fieldset[1]/div[1]
* @return string
*/
function getNodeXPath( $node ) {   
   
$result='';
    while (
$parentNode = $node->parentNode) {
       
$nodeIndex=-1;
       
$nodeTagIndex=0;
        do {
           
$nodeIndex++;
           
$testNode = $parentNode->childNodes->item( $nodeIndex );
               
            if (
$testNode->nodeName==$node->nodeName and $testNode->parentNode->isSameNode($node->parentNode) and $testNode->childNodes->length>0) {
               
//echo "{$testNode->parentNode->nodeName}-{$testNode->nodeName}-{}<br/>";
               
$nodeTagIndex++;
            }
               
        } while (!
$node->isSameNode($testNode));

       
$result="/{$node->nodeName}[{$nodeTagIndex}]".$result;
       
$node=$parentNode;
    };
    return
$result;
}
?>

By Sina.Salek.ws
cgorbit spamless_at ya dot ru
18-Oct-2008 05:39
Show expandable DOM like in Firebug.

http://cgorbit.itkm.ru/temp/phpdotnet/common.js needed for script, sorry, but it's my framework.

<?php
   
function gaie( $node, &$arr, $attr )
    {
        if (
$value = $node->getAttribute( $attr ) )
           
$arr[ $attr ] = u2w( $value );
    }

    function
innerXML( $l, $collapse_all = true, $top_run = true )
    {
       
$atts4elements = array(
           
'a' => 'href',
           
'table' => 'border,cellpadding,cellspacing',
           
'td' => 'colspan,rowspan'
       
);
       
$s = '';

        if (
$top_run ) :
           
ob_start();
           
?><html>
            <head>
                <meta http-uquiv="Content-type" content="text/html; charset=windows-1251" />
                <script type="text/javascript" src="/common.js"></script>
            </head>
            <body>
            <style type="text/css">
                body {
                }

                .root-inner-xml-list {
                    list-style-type: none;

                    font-size: 1em;
                    font-family: monospace;
                }

                .root-inner-xml-list ul {
                    list-style-type: none;
                }

                .root-inner-xml-list li.text-node span.value {
                    color: black;
                    font-weight: bold;
                    background-color: lightgrey;

                    margin-right: 1em;
                    padding: 0em 0.2em;
                }

                .root-inner-xml-list li.text-node span.hex {
                    color: gray;
                    font-style: italic;
                }

                .root-inner-xml-list li.element-node {
                    color: blue;
                }

                .root-inner-xml-list .attribute-name {
                    color: green;
                }

                .root-inner-xml-list .attribute-value {
                    color: red;
                    color: rgb( 205, 0, 0 );
                }

                .root-inner-xml-list .node-with-childs {
                    cursor: pointer;
                    //cursor: hand;
                }

                .root-inner-xml-list .collapsed-node {
                    background-color: yellow;
                }

                .root-inner-xml-list .collapsed-node + ul {
                    display: none;
                }
            </style>

            <ul class="root-inner-xml-list">
            <?   
            $s
.= ob_get_clean();
        endif;

       
//if ( $top_run ) $l = $l->childNodes;

       
foreach ( $l as $i => $node )
        {
            if (
$node->nodeType == XML_ELEMENT_NODE )
            {
               
$atts = array();
               
$atts2get = array( 'id', 'class', 'style' );

                if ( @
$atts4elements[ $node->tagName ] )
                   
$atts2get = array_merge( $atts2get, explode( ',', $atts4elements[ $node->tagName ] ) );

                foreach (
$atts2get as $att2get )
                   
gaie( $node, $atts, $att2get );

               
$attr_arr = array();
                foreach (
$atts as $name => $value )
                   
$attr_arr[] = sprintf( '<span class="attribute-name">%s</span>="<span class="attribute-value">%s</span>"', $name, $value );

               
$atts_s = '';
                if (
$attr_arr )
                   
$atts_s = join( ' ', $attr_arr );

               
$span_class_name = array( 'node-name' );
                if (
$node->childNodes->length )
                   
$span_class_name[] = 'node-with-childs';
                if (
$collapse_all )
                   
$span_class_name[] = 'collapsed-node';
               
$span_class_name = join( ' ', $span_class_name );

               
$inner = '<span class="' . $span_class_name . '">&lt;'. $node->tagName . ' ' . $atts_s . '&gt;</span>';

                if (
$node->childNodes->length )
                   
$inner .= '<ul>' . innerXML( $node->childNodes, $collapse_all, false ) . '</ul>';
           

               
$className = 'element-node';
            }
            elseif (
$node->nodeType == XML_TEXT_NODE )
            {
               
$value = htmlspecialchars( u2w( $node->nodeValue ) );
               
$inner = '<span class="value">' . $value . '</span><span class="hex">' . string2hex( $value ) . '</span>';

               
$className = 'text-node';
            }
            else
                continue;

           
$s .= '<li class="' . $className . '">' . $inner . '</li>';

            if (
$top_run ) echo '<hr />';
        }

        if (
$top_run ):
       
ob_start();   
       
?></ul>
            <script type="text/javascript">
                onLoad( function(){
                    addEvent( $( '.root-inner-xml-list .node-with-childs', true ), 'click', function( e ){
                        var el = e.target;

                        ul = getNextSibling( el );

                        if ( !ul || ul.tagName != 'UL' ) return;

                        invertClass( el, 'collapsed-node' );
                    });
                });

                globalInit();
            </script>
        </body>
        </html>
        <?
        $s
.= ob_get_clean();
        endif;

        return
$s;
    }
?>
miguelangelhdz at NOSPAM dot com
22-Sep-2008 01:19
After searching how to extend the DOMDocument and DOMElement I found a way in the bug: http://bugs.php.net/bug.php?id=35104. The following code shows how:

<?php
class extDOMDocument extends DOMDocument {
 public function
createElement($name, $value=null) {
 
$orphan = new extDOMElement($name, $value); // new  sub-class object
 
$docFragment = $this->createDocumentFragment(); // lightweight container maintains "ownerDocument"
 
$docFragment->appendChild($orphan); // attach
 
$ret = $docFragment->removeChild($orphan); // remove
 
return $ret; // ownerDocument set; won't be destroyed on  method exit
 
}
 
// .. more class definition
}

class
extDOMElement extends DOMElement {
 function
__construct($name, $value='', $namespaceURI=null) {
 
parent::__construct($name, $value, $namespaceURI);
 }
 
//  ... more class definition here
}

$doc = new extDOMDocument('test');
$el = $doc->createElement('tagname');
$el->setAttribute("attr", "val");
$doc->appendChild($el);

// append discards the DOMDocumentFragment and just adds its child nodes, but ownerDocument is maintained.
echo get_class($el)."<br/>";
echo
get_class($doc->documentElement)."<br/>";
echo
"<xmp>".$doc->saveXML()."</xmp>";
?>
tobiasz.cudnik[at]gmail.com
29-Jul-2008 01:47
If you need simple interface to DOM check out phpQuery - jQuery port to PHP:
http://code.google.com/p/phpquery/

It uses CSS selectors to fetch nodes.
Here's example how it works:
<?php
// just one file to include
require('phpQuery/phpQuery.php');

$html = '
<div>
    mydiv
    <ul>
        <li>1</li>
        <li>2</li>
        <li>3</li>
    </ul>
</div>'
;

// intialize new DOM from markup
phpQuery::newDocument($markup)
    ->
find('ul > li')
        ->
addClass('my-new-class')
        ->
filter(':last')
            ->
addClass('last-li');

// query all unordered lists in last used DOM
pq('ul')->insertAfter('div');

// iterate all LIs from last used DOM
foreach(pq('li') as $li) {
   
// iteration returns plain DOM nodes, not phpQuery objects
   
pq($li)->addClass('my-second-new-class');
}

// same as pq('anything')->htmlOuter()
// but on document root (returns doctype etc)
print phpQuery::getDocument();
?>

It uses DOM extension and XPath so it works only in PHP5.
Sven Arduwie
17-Mar-2008 02:28
I needed a function that quickly converts an xml with key/value pairs to an array.

for example:
<?xml version="1.0" encoding="UTF-8"?>
<test>
    <key id="Array key #1" value="Value #1"/>
    <key id="Array key #2" value="Value #2"/>
    <key id="Dupe" value="Duplicate keys"/>
    <key id="Dupe" value="create numeric arrays"/>
    <key id="And another key">
        <![CDATA[
            Multiline
            data
            works
            just
            as
            well.
        ]]>
    </key>
    <nested>
        <key id="Nested key" value="Nested data works as well, but it still results in a 1 dimensional array."/>
    </nested>
</test>

Results in the following array:
array(5) {
  ["Array key #1"]=>
  string(8) "Value #1"
  ["Array key #2"]=>
  string(8) "Value #2"
  ["Dupe"]=>
  array(2) {
    [0]=>
    string(14) "Duplicate keys"
    [1]=>
    string(21) "create numeric arrays"
  }
  ["And another key"]=>
  string(49) "Multiline
            data
            works
            just
            as
            well."
  ["Nested key"]=>
  string(73) "Nested data works as well, but it still results in a 1 dimensional array."
}

Here's the code:
<?php
   
function xml2array($xml) {
       
$domDocument = new DOMDocument;
       
$domDocument->loadXML($xml);
       
$domXPath = new DOMXPath($domDocument);
       
$array = array();
        foreach (
$domXPath->query('//key') as $keyDOM) {
           
$id = $keyDOM->getAttribute('id');
           
$value = $keyDOM->hasAttribute('value') ? $keyDOM->getAttribute('value') : trim($keyDOM->textContent);
            if (
array_key_exists($id, $array)) {
                if (
is_array($array[$id])) {
                   
$array[$id][] = $value;
                } else {
                   
$array[$id] = array($array[$id]);
                   
$array[$id][] = $value;
                }
            } else {
               
$array[$id] = $value;
            }
        }
        return
$array;
    }
?>
danf dot 1979 at []gmail[] dot com
24-Feb-2008 03:47
This is a couple of classes to deal with yahoo yui menu.

/*
  $menubar = new MenuBar();

  $file = new Menu("File");
  $file->setAttribute("href", "http://file.com");

  $quit = new Menu("Quit");
  $quit->setAttribute("href", "http://quit.com");

  $file->appendChild($quit);
  $menubar->appendChild($file);

  echo $menubar->grab();
*/

//
// Author: Daniel Queirolo.
// LGPL
//

/** ---------------------------------
/**  Class MenuBar()
/**  Creates a the menubar and appends
/**  yuimenubaritems to it.
/** ---------------------------------*/

class MenuBar extends DOMDocument
{

  public $menuID = "nav_menu";  // holds the css id that javascript yui menu code should have to recognize
  private $UL;                  // This node holds every menu, This is THE node.

  /** ---------------------------------
  /**  Constructor
  /**  Generates a menubar skeleton and the UL node
  /** ---------------------------------*/

  public function __construct() {

    parent::__construct();

    $rootdiv = parent::createElement("div");
    $rootdiv->setAttribute("class", "yui-skin-sam");

    parent::appendChild($rootdiv);

    $yui_menubar = parent::createElement("div");
    $yui_menubar->setAttribute("id", $this->menuID);
    $yui_menubar->setAttribute("class", "yuimenubar");

    $rootdiv->appendChild($yui_menubar);

    $bd = parent::createElement("div");
    $bd->setAttribute("class", "bd");

    $yui_menubar->appendChild($bd);

    $ul = parent::createElement("ul");
    $ul->setAttribute("class", "first-of-type");

    // ALL Menu() instances ocurr inside an <ul> tag.

    $this->UL = $bd->appendChild($ul);

  }

  /** ---------------------------------
  /**  appendChild()
  /**  Appends a new yuimenubaritem to the menubar UL node.
  /**  This function changes <li> and <a> classes to yuiMENUBARsomething
  /** ---------------------------------*/

  public function appendChild($child) {

    $li = parent::importNode($child->LI, true);

    $li->setAttribute("class", "yuimenubaritem");

    $li->getElementsByTagName("a")->item(0)->setAttribute("class", "yuimenubaritemlabel");

    $this->UL->appendChild($li);

  }

  public function grab() {

    return parent::saveHTML();

  }

}

/** ---------------------------------
/**  Class Menu()
/**  Creates a yuimenuitem li node
/** ---------------------------------*/

class Menu extends DOMDocument {

  public $LI; // stores the <li> node (THE link) that will be exported to MenuBar() or used on appendChild()

  /** ---------------------------------
  /**  Constructor
  /**  Generates a yuimenuitem li node
  /**  No yuimenubar items are created here. MenuBar handles that.
  /** ---------------------------------*/

  public function __construct($link_name) {

    parent::__construct();

    $li = parent::createElement("li");
    $li->setAttribute("class", "yuimenuitem");

    // LI node stores THE link.
    // if appendChild is used, the new (sub) Menu() would be LI node child.

    $this->LI = parent::appendChild($li);

    $a = parent::createElement("a", $link_name);
    $a->setAttribute("class", "yuimenuitemlabel");

    $li->appendChild($a);

    $this->li = $li;
    $this->a = $a;

  }

  /** ---------------------------------
  /**  appendChild
  /**  Appends a (sub) Menu() to current Menu() in LI
  /** ---------------------------------*/

  public function appendChild($child) {

    $yuimenu = parent::createElement("div");
    $yuimenu->setAttribute("class", "yuimenu");

    $this->LI->appendChild($yuimenu);

    $bd = parent::createElement("div");
    $bd->setAttribute("class", "bd");

    $yuimenu->appendChild($bd);

    $ul = parent::createElement("ul");

    $bd->appendChild($ul);

    // child->NODE holds THE link from the new child (from child's __construct())

    $ul->appendChild(parent::importNode($child->LI, true));

  }

  public function setAttribute($name, $value, $node="a") {

      if ($node == "a") {
        $this->a->setAttribute($name, $value);
      }

      else {
        $this->li->setAttribute($name, $value);
      }
  }

}
ptichy at pobox dot sk
09-Feb-2008 10:40
How to get contents of node with all tags by PHP Dom:
<?php
// XML data
$xml_string = "<?xml version='1.0' ?>
<sentence>
How to get contents of node with all tags by PHP Dom: <br/>
<b>cabbages</b>, <i>tomatoes</i>,
  <i>apples</i>, <font  color='purple'>aubergines</font>
<ol>
   <li> row 1</li>
   <li> row 2 </li>
   <li> row 3 </li>
 </ol>
 <table border = '1'>
  <tbody>
    <tr>
      <td>I am best</td>
    </tr>
    <tr>
      <td>Programmer</td>
    </tr>
  </tbody>
</table>
You see my projects at:
<strong><a href='http://www.itdeveloping.eu' >www.itdeveloping.eu</a></strong>
</sentence>"
;

// parse it
$doc= new DOMDocument();
if (!
$doc->loadXML($xml_string))
{
   echo (
"Error in XML document");
}

$nody = $doc->getElementsByTagName('sentence'); // gets NodeList

$nod=$nody->item(0);//Node
getContent($Content,$nod);
echo
$Content;

function
getContent(&$NodeContent="",$nod)
{   
$NodList=$nod->childNodes;
    for(
$j=0 $j < $NodList->length; $j++ )
    {      
$nod2=$NodList->item($j);//Node j
       
$nodemane=$nod2->nodeName;
       
$nodevalue=$nod2->nodeValue;
        if(
$nod2->nodeType == XML_TEXT_NODE)
           
$NodeContent .=  $nodevalue;
        else
        {    
$NodeContent .= "<$nodemane ";
          
$attAre=$nod2->attributes;
           foreach (
$attAre as $value)
             
$NodeContent .="{$value->nodeName}='{$value->nodeValue}'" ;
           
$NodeContent .=">";                    
           
getContent($NodeContent,$nod2);                    
           
$NodeContent .= "</$nodemane>";
        }
    }
   
}
?>
Anonymous
30-Jan-2008 07:37
In response to...
"If you create your own custom element extending DOMElement and append him in place of the document element, you cannot access to any new members newly defined in your custom class via DOMDocument::$documentElement."

... it is not a bug, it is a feature. The DOMDocument::$documentElement property name may be misleading but according to the DOM Level 2 Core specification it is a convenience attribute meant to access the root element of your DOMDocument. See here: http://www.w3.org/TR/DOM-Level-2-Core/core.html#i-Document
ryoroxdahouse at hotmail dot com
25-Jan-2008 08:14
I use DOM to generate dynamically XHTML document.

When trying to extend the DOMDocument and DOMElement classes, I found a very annoying bug concerning DOMDocument::$documentElement.

If you create your own custom element extending DOMElement and append him in place of the document element, you cannot access to any new members newly defined in your custom class via DOMDocument::$documentElement.

In my situation, I cannot use DOMDocument::registerNodeClass() because the document element is not necessarily the base class for all the elements in my document.

*******
problem
*******

See bellow for the repro step:

<?php
   
class MyElement extends DOMElement{
        public
$myProp="myProp";
        public function
myMethod(){
            return
'myMethod()';
        }
    }
   
   
$myDocument=new DOMDocument();
   
$myDocument->appendChild(new MyElement('myElement','myElement'));
    echo (
'$myElement->myProp :'.$myDocument->documentElement->myProp.'<br />');
    echo (
'$myElement->myMethod :'.$myDocument->documentElement->myMethod().'<br />');
?>

will output:

Notice: Undefined property: DOMElement::$myProp in C:\Program Files\EasyPHP 2.0b1\www\testDOMBug\test2.php on line 11
$myElement->myProp :

Fatal error: Call to undefined method DOMElement::myMethod() in C:\Program Files\EasyPHP 2.0b1\www\testDOMBug\test2.php on line 12

*******
solution
*******

After searching around, I found a pretty odd way to fix this problem. It seems that you have to stock a reference to your appended document element in an user-defined (and persistent) variable (in other words, not only in DOMDocument::$documentElement). See below:

<?php   
   
class MyElement extends DOMElement{
        public
$myProp="myProp";
        public function
myMethod(){
            return
'myMethod()';
        }
    }
   
   
$myDocument=new DOMDocument();
   
$mydocumentElement=$myDocument->appendChild(new MyElement('myElement','myElement')); //here is the hack
   
echo ('$myElement->myProp :'.$myDocument->documentElement->myProp.'<br />');
    echo (
'$myElement->myMethod :'.$myDocument->documentElement->myMethod().'<br />');
?>

will output:

$myElement->myProp :myProp
$myElement->myMethod :myMethod()

Hope it will help.
moshedolev at gmail dot com
08-Jan-2008 06:15
I developed a group of functions that make it very easy to extract any information you want from any page you load from the internet. All based on the DOMDocument object.
You can read the entire documentation and download the source code here:
http://www.tintetoner-shop.de/DomUtilities/

Enjoy !!
naudyj at aus3d.com
04-Jan-2008 01:06
The following can take a XML_TEXT_NODE node and return the contents in an array. Yanick's contribution rocks - but
it overwrote with duplicates only keeping the last line
in the returned array. All the other functions i tested from various sources failed to handle text nodes correctly. Hope this helps someone. It is adapted from code on this site.

function myTextNode($n, &$a)
{
 static $depth = 0;
 static $sz = '';

 if ($cn = $n->firstChild)
 {
  while ($cn)
  {
   if ($cn->nodeType == XML_TEXT_NODE)
   {
    $sz .= $cn->nodeValue;
   }
   elseif ($cn->nodeType == XML_ELEMENT_NODE)
   {
    $b = 1;
    if ($cn->hasChildNodes())
    {
     $depth++;
     if ($this->myHeadings($cn, $a))
     {
      if ($sz){
       array_push($a, $sz);
       $sz = '';
      }
     }
     $depth--;
    }
   }
   $cn = $cn->nextSibling;
  }
  return $b;
 }
}

so you could use:  

$nodes = $dom->getElementsByTagName("td");
if($nodes){
 foreach ($nodes as $node){
  $a = Array();
  myTextNode($node, $a);
 }
}
Joe dot Cattlet at msn dot com
13-Nov-2007 02:56
In response to TrollBoy:

You might want to look a little harder before you go and write new code, someone posted a function that does exactly what your class does about a week before you. Also their function allows you to seed the document with a root so it could technically work for HTML documents as well.
trollboy at shoggoth dot net
12-Nov-2007 11:12
I wrote a simple class to turn an associative array into xml, as this seems like something fairly simple, but nothing out there does it that I know of.  That said,  enjoy.

<?php

   
/**
     * basic class for converting an array to xml.
     * @author Matt Wiseman (trollboy at shoggoth.net)
     *
     */
   
class array2xml {
       
        public
$data;
        public
$dom_tree;
       
       
/**
         * basic constructor
         *
         * @param array $array
         */
       
public  function __construct($array){
            if(!
is_array($array)){
                throw new
Exception('array2xml requires an array', 1);
                unset(
$this);
            }
            if(!
count($array)){
                throw new
Exception('array is empty', 2);
                unset(
$this);
            }
           
           
$this->data = new DOMDocument('1.0');
           
           
$this->dom_tree = $this->data->createElement('result');
           
$this->data->appendChild($this->dom_tree);
           
$this->recurse_node($array, $this->dom_tree);
        }
       
       
/**
         * recurse a nested array and return dom back
         *
         * @param array $data
         * @param dom element $obj
         */
       
private function recurse_node($data, $obj){
           
$i = 0;
            foreach(
$data as $key=>$value){
                if(
is_array($value)){
                   
//recurse if neccisary
                   
$sub_obj[$i] = $this->data->createElement($key);
                   
$obj->appendChild($sub_obj[$i]);
                   
$this->recurse_node($value, $sub_obj[$i]);
                } elseif(
is_object($value)) {
                   
//no object support so just say what it is
                   
$sub_obj[$i] = $this->data->createElement($key, 'Object: "' . $key . '" type: "'  . get_class($value) . '"');
                   
$obj->appendChild($sub_obj[$i]);
                } else {
                   
//straight up data, no weirdness
                   
$sub_obj[$i] = $this->data->createElement($key, $value);
                   
$obj->appendChild($sub_obj[$i]);
                }
               
$i++;
            }
        }
       
       
/**
         * get the finished xml
         *
         * @return string
         */
       
public function saveXML(){
            return
$this->data->saveXML();
        }
    }
   
      
   
$test = array(
       
'cat'=>'animal',
       
'container'=> array(
           
'thing'=>'stuff',
           
'thing2'=>'stuff2',
           
'thing3'=>3,
           
'thing4'=>4,
           
'wtf'=> new stdClass(),
        ),
       
'foo'=>'bar',
    );
   
   
var_dump($test);
    try {
   
$o_test = new array2xml($test);
    } catch (
Exception $e) {
        echo
$e->getMessage();
    }
    echo
$o_test->saveXML();
   
?>
jim.filter (at gmail.com)
03-Nov-2007 03:42
Array to DOM

Here is a recursive function to turn a multidimensional array into an XML document.  It will handle multiple elements of the same tag, but only one per parent element. IE:

Can't generate:         Can generate:
<root>                  <root>
  <sub1>data1</sub1>      <subs1>
  <sub1>data2</sub1>         <value>data1</value>
  <sub2>data1</sub2>         <value>data2</value>
  <sub2>data2</sub2>      </subs1>
</root>                   <subs2>
                            <value>data1</value>
                            <value>data2</value>
                          <subs2>
                        </root>

Also, the function performs no type of error checking on your array and will throw a DOMException if a key value you used in your array contains invalid characters for a proper DOM tag. This function is untested for "deep" multidimensional arrays.

Complete code ready to run with example:

<?PHP
 
function AtoX($array, $DOM=null, $root=null){
   
    if(
$DOM  == null){$DOM  = new DOMDocument('1.0', 'iso-8859-1');}
    if(
$root == null){$root = $DOM->appendChild($DOM->createElement('root'));}
   
   
$name = $array['#MULTIPLE_ELEMENT_NAME'];

      foreach(
$array as $key => $value){   
        if(
is_int($key) && $name != null){
          if(
is_array($value)){
           
$subroot = $root->appendChild($DOM->createElement($name));
           
AtoX($value, $DOM, $subroot);
          }
          else if(
is_scalar($value)){
           
$root->appendChild($DOM->createElement($name, $value));
          }
        }
        else if(
is_string($key) && $key != '#MULTIPLE_ELEMENT_NAME'){
          if(
is_array($value)){
           
$subroot = $root->appendChild($DOM->createElement($key));
           
AtoX($value, $DOM, $subroot);
          }
          else if(
is_scalar($value)){
           
$root->appendChild($DOM->createElement($key, $value));
          }
        }
      }
    return
$DOM
  }
 
 
$array = array(
                   
'#MULTIPLE_ELEMENT_NAME' => 'GenericDatas',
                   
'Date'      => 'November 03, 2007',
                   
'Company'   => 'Facility One',
                   
'Field'     => 'Facility Management Software',
                   
'Employees' => array(
                                     
'#MULTIPLE_ELEMENT_NAME' => 'Employee',
                                     
'Cindy',
                                     
'Sean',
                                     
'Joe',
                                     
'Owen',
                                     
'Jim',
                                     
'Dale',
                                     
'Kelly',
                                     
'Ryan',
                                     
'Johnathan',
                                     
'Robin',
                                     
'William Marcus',
                                     
'NewCoops' => array(
                                                         
'#MULTIPLE_ELEMENT_NAME' => 'Coop',
                                                         
'John',
                                                         
'Tyler',
                                                         
'Ray',
                                                         
'Dawn'
                                                        
)    
                                    ),
                   
'Datas',
                   
'DATAS',
                   
'OtherDatas'
               
);
 
 
$DOM  = new DOMDocument('1.0', 'iso-8859-1');
 
$root = $DOM->appendChild($DOM->createElement('CompanyData'));
 
$DOM  = AtoX($array, $DOM, $root);
 
$DOM->save('C:\test.xml');
?>
freyjkell at gmail dot com
02-Nov-2007 06:02
In order to REALLY well handle XHTML entities with DOM, you can do following things:

1. Add this DOCTYPE to your documents
<!DOCTYPE xhtmlentities PUBLIC "-//W3C//ENTITIES XHTML Character Entities 1.0//EN" "/xhtml11.ent">

2. Copy http://freyjkell.ovh.org/xhtml11.ent into your document root.

3. In your PHP:
<?php
$dom
=new DOMDocument();
$dom->load('file.xhtml',LIBXML_DTDLOAD); // NOT resolveExternals - it needs true doctype, and includes crap code
// some DOM operations
$doctype=DOMImplementation::createDocumentType("html","-//W3C//DTD XHTML 1.1//EN","http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"); // creating real doctype
$output=DOMImplementation::createDocument('','',$doctype);
$output->appendChild($output->importNode($dom->documentElement,true));
$output->encoding='utf-8';
$output=$output->saveXML();
$xhtml=preg_match(
   
'/application\/xhtml\+xml(?![+a-z])'.
   
'(;q=(0\.\d{1,3}|[01]))?/i',
   
$_SERVER['HTTP_ACCEPT'],$xhtml) &&
    (isset(
$xhtml[2])?$xhtml[2]:1) > 0 ||
   
strpos($_SERVER["HTTP_USER_AGENT"],
   
"W3C_Validator")!==false ||
   
strpos($_SERVER["HTTP_USER_AGENT"],
   
"WebKit")!==false; // XHTML Content-Negotiation
header('Content-Type: '.($xhtml?'application/xhtml+xml':'text/html').'; charset=utf-8');
print
$output;
?>
PHPdeveloper
06-Sep-2007 09:46
The Yanik's dom2array() function (added on 14-Mar-2007 08:40) does not handle multiple nodes with the same name, i.e.:

<foo>
  <name>aa</name>
  <name>bb</name>
</foo>

It will overwrite former and your array will contain just the last one ("bb")
Francois Hill
01-Aug-2007 06:21
In response to lutfi at smartconsultant dot us :

(see my post on
http://fr2.php.net/manual/en/
function.dom-domdocument-getelementsbytagname.php
)

Use this class I wrote:

class XPathableNode extends DOMNode
{
    protected $Node;
    protected $DOMDocument_from_node;
    protected $DOMXpath_for_node;

    public function __construct(/* DOMNode */ $node)
    {
        $this->Node=$node;
        $this->DOMDocument_from_node=new
                                                          DomDocument();
        $domNode=$this->DOMDocument_from_node
                                  ->importNode($this->Node, true);
        $this->DOMDocument_from_node
                                 ->appendChild($domNode);
        $this->DomXpath_for_node =
                    new Domxpath($this->
                                         DOMDocument_from_node);
    }

    public function convertHTML()
    {    return $this->DOMDocument_from_node
                                                             ->saveHTML();
    }

    public /*DomNodeList*/ function applyXpath($xpath)
    {    return $this->DomXpath_for_node
                                                       ->query($xpath);
    }
}

(sorry for the display... What a terrible hinderance on the
part of php.net !)

Then :
Make a new XPathableNode out of your parent node.
You may then retrieve a DOMNodeList from it by applying a
xpath (thus being able to specify the depth  and name of
elements you want).

Has got me around some (of the many) DOM awkwardnesses a few times.

;o)
lpetrov AT axisvista.com
21-Jul-2007 12:41
Basicly there are alot of problems on dynamic namespaces registering and other maybe 'not well' documented parts of DOM.

Here is an article covering some of the problems that our company web developers found while we were developing a template engine for our new framework.

The link:
http://blog.axisvista.com/?p=35
lutfi at smartconsultant dot us
20-Jul-2007 04:06
i have some problem parsing recurred xml tree here:

<menu name='parent1' >
  <submenu name='file' >
     <submenu name='open' >Open file</submenu>
     <submenu name='close' >Close file</submenu>
  </submenu>
  <submenu name='edit' >
     <submenu name='cut' >Cut Clipboards</submenu>
     <submenu name='copy' >Copy Clipboards</submenu>
     <submenu name='paste' >Paste Clipboards</submenu>
  </submenu>
</menu>

with getElementsByTagName all submenu is on the same level.
i want it to be structured like tree list, but not change the 'submenu' tag
Sanados at failure dot at
05-Jun-2007 09:45
appended to
brian dot reynolds at risaris dot com
20-Feb-2007 10:09

when you got variable nodes at start you array fails and looses nodes  beneath.
solution that counts occurance though eats up performance:

function xmlToArray($n)
{
    $xml_array = array();
    $occurance = array();

     foreach($n->childNodes as $nc)
     {
         $occurance[$nc->nodeName]++;
     }
    
    foreach($n->childNodes as $nc){
        if( $nc->hasChildNodes() )
        {
            if($occurance[$nc->nodeName] > 1)
            {
                $xml_array[$nc->nodeName][] = xmlToArray($nc);
            }
            else
            {
                $xml_array[$nc->nodeName] = xmlToArray($nc);
            }
        }
        else
        {
            return utf8_decode($nc->nodeValue);
        }
    }
    return $xml_array;
}
Yanik <clonyara(at)ahoo(dot)com>
14-Mar-2007 07:40
I hate DOM model !
so I wrote dom2array simple function (simple for use):

function dom2array($node) {
  $res = array();
  print $node->nodeType.'<br/>';
  if($node->nodeType == XML_TEXT_NODE){
      $res = $node->nodeValue;
  }
  else{
      if($node->hasAttributes()){
          $attributes = $node->attributes;
          if(!is_null($attributes)){
              $res['@attributes'] = array();
              foreach ($attributes as $index=>$attr) {
                  $res['@attributes'][$attr->name] = $attr->value;
              }
          }
      }
      if($node->hasChildNodes()){
          $children = $node->childNodes;
          for($i=0;$i<$children->length;$i++){
              $child = $children->item($i);
              $res[$child->nodeName] = dom2array($child);
          }
      }
  }
  return $res;
}
Nevyn at N dot O dot S dot P dot A dot M dot emai dot it
10-Mar-2007 03:35
I wrote a couple of functions to:
 - create a DOMDocument from a file
 - parse the namespaces in it
 - create a XPath object with all the namespaces registered
 - load the schemalocations
 - validate the file on the main schema (the one without prefix)

It is useful for me, see if it is also for someone else!!

Giulio

function decodeNode($node)
{
    $out = $node->ownerDocument->saveXML($node);
    $re = "{^<((?:\\w*:)?\\w*)". //the tag name
    "[\\s\n\r]*((?:[\\s\n\r]*".
    "(?:\\w*:)?\\w+[\\s\n\r]*=[\\s\n\r]*". //possible attribute name
    "(?:\"[^\"]*\"|\'[^\']*\'))*)". //attribute value
    "[\\s\n\r]*>[\r\n]*".
    "((?:.*[\r\n]*)*)". //content
    "[\r\n]*</\\1>$}"; //closing tag
    preg_match($re, $out, $mat);
    return $mat;
}

function innerXml($node)
{
    $mat = decodeNode($node);
    return $mat[3];
}

function getnodeAttributes($node)
{
    $mat = decodeNode($node);
    $txt = $mat[2];
    $re = "{((?:\\w*:)?\\w+)[\\s\n\r]*=[\\s\n\r]*(\"[^\"]*\"|\'[^\']*\')}";
    preg_match_all($re, $txt, $mat);
    $att = array();
    for ($i=0; $i<count($mat[0]); $i++)
    {
        $value = $mat[2][$i];
        if ($value[0] == "\'" || $value[0] == "\"")
        {
            $len = strlen($value);
            $value = substr($value, 1, strlen($value)-2);
        }
        $att[ $mat[1][$i] ] = $value;
    }
    return $att;
}

function loadXml($file)
{
    $doc = new DOMDocument();
    $doc->load($file);
    //cerca l'attributo xmlns
    $xsi = false;
    $doc->namespaces = array();
    $doc->xpath = new DOMXPath($doc);
   
    $attr = getnodeAttributes($doc->documentElement);
    foreach ($attr as $name => $value)
    {
        if (substr($name,0,5) == "xmlns")
        {
            $uri = $value;
            $pre = $doc->documentElement->lookupPrefix($uri);
            if ($uri == "http://www.w3.org/2001/XMLSchema-instance")
                $xsi = $pre;
            $doc->namespaces[$pre] = $uri;
            if ($pre == "")
                $pre = "noname";
            $doc->xpath->registerNamespace($pre, $uri);
        }
    }
   
    if ($xsi)
    {
        $doc->schemaLocations = array();
        $lst = $doc->xpath->query("//@$xsi:schemaLocation");
        foreach($lst as $el)
        {
            $re = "{[\\s\n\r]*([^\\s\n\r]+)[\\s\n\r]*([^\\s\n\r]+)}";
            preg_match_all($re, $el->nodeValue, $mat);
            for ($i=0; $i<count($mat[0]); $i++)
            {
                $value = $mat[2][$i];
                $doc->schemaLocations[ $mat[1][$i] ] = $value;
            }
        }

        $olddir = getcwd();
        chdir(dirname($file));
        $schema = $doc->schemaLocations[$doc->namespaces[""]];
        if (substr($schema,0,7) == "file://")
        {
            $schema = substr($value,7);
        }
        if (!$doc->schemaValidate($schema))
            dbg()->err("Invalid file");
        chdir($olddir);
    }
   
    return $doc;
}
brian dot reynolds at risaris dot com
20-Feb-2007 09:09
I found the xml2array function below very useful, but there seems to be a bug in it. The $item variable was never getting set. I've expanded this out to be a bit more readable, and the corrected code is :

function xmlToArray($n)
{
    $return=array();

    foreach($n->childNodes as $nc){
        if( $nc->hasChildNodes() ){
            if( $n->firstChild->nodeName== $n->lastChild->nodeName&&$n->childNodes->length>1){
                $item = $n->firstChild;
                $return[$nc->nodeName][]=$this->xmlToArray($item);
            }
            else{
                 $return[$nc->nodeName]=$this->xmlToArray($nc);
            }
       }
       else{
           $return=$nc->nodeValue;
       }
    }
    return $return;
}
cooper at asu dot ntu-kpi dot kiev dot ua
22-Nov-2006 10:32
If you are using not object-oriented functions and it takes too much time to change them all (or you'll be replacing them later) then as a temporary decision can be used this modules:

For DOM XML:
http://alexandre.alapetite.net/doc-alex/domxml-php4-php5/

For XSLT:
http://alexandre.alapetite.net/doc-alex/xslt-php4-php5/
cormac at idreamproducts dot com
17-Oct-2006 10:48
Most email clients ignore stylesheets in HTML formatted emails.  The best way to ensure your HTML is formatted correctly by a broad spectrum of email clients, including webmail implementations as Gmail, is to use inline style attributes.  The following function uses DOM to parse an inline stylesheet, and will replace element class and id attributes with inline style attributes, and add inline style attributes for generic tag stylesheet rules.  It will remove the stylesheet and any used class and id attributes as these are defunct for most email clients.  It is a fairly lightweight function and does not support CSS inheritance, but will work for simple stylesheets e.g.:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>HTML EMAIL</title>
<style type="text/css">
body {
  margin: 10px 10px;
  font: 8pt arial;
  background: #fff;
  color: #000;
}
p {
  margin: 0 0 10px;
  line-height: 1.2em;
  text-align: justify;
}
p.centered {
  text-align: centre;
}
p#right {
  text-align: right;
}
</style>
</head>
<body>
<p>Sample text justified</p>
<p class="centered">Centered text here</p>
<p id="right">Right-aligned text</p>
</body>
</html>

Here's the function:

<?php
function parseStyleSheetfor Email($html)
{
 
$doc = new DOMDocument;
 
$doc->loadHTML($html);
 
// grab inline stylesheet as DOM object
 
$oStyle = $doc->getElementsByTagName('style')->item(0);
 
// grab rule identifiers and rules
 
preg_match_all('/^([-#._a-z0-9]+) ?\{(.*?)\}/ims', $oStyle->nodeValue, $aMatches, PREG_SET_ORDER);
  foreach (
$aMatches as $aRule) {
   
$rule_id = $aRule[1];
   
// clean up rules
   
$rule = str_replace(array("\r", "\n", '  ', '; '), array('', '', ' ', ';'), $aRule[2]);
   
$rule = preg_replace(array('/^ /', '/;$/'), '', $rule);
   
// generic rules
   
if (!strstr($rule_id, '.') && !strstr($rule_id, '#')) {
     
$items = $doc->getElementsByTagName($rule_id);
     
// set style attribute equal to rule from stylesheet
     
foreach ($items as $item) {
       
// if there is already inline style append it to end of stylesheet rule
       
$current_style = $item->getAttribute('style');
        if (!empty(
$current_style)) {
         
$item->setAttribute('style', $rule . ';' . $current_style);
        } else {
         
$item->setAttribute('style', $rule);
        }
      }
   
// classes
   
} elseif (strstr($rule_id, '.')) {
      list(
$rule_tag, $rule_class) = explode('.', $rule_id);
     
$items = $doc->getElementsByTagName($rule_tag);
      foreach (
$items as $item) {
       
$class = $item->getAttribute('class');
        if (
$class == $rule_class) {
         
// if there is already inline style append it to end of stylesheet rule
         
$current_style = $item->getAttribute('style');
          if (!empty(
$current_style)) {
           
$item->setAttribute('style', $current_style . ';' . $rule);
          } else {
           
$item->setAttribute('style', $rule);
          }
         
// remove class as it won't be used now
         
$item->removeAttribute('class');
        }
      }
   
// ids
   
} elseif (strstr($rule_id, '#')) {
      list(
$rule_tag, $id) = explode('#', $rule_id);
     
$item = $doc->getElementById($id);
     
$current_style = $item->getAttribute('style');
      if (!empty(
$current_style)) {
       
$item->setAttribute('style', $current_style . ';' . $rule);
      } else {
       
$item->setAttribute('style', $rule);
      }
     
// remove class as it won't be used now
     
$item->removeAttribute('id');
    }
  }
 
// remove inline stylesheet
 
$oStyle->parentNode->removeChild($oStyle);
  return
$doc->saveHTML();
}
?>
sean at lookin3d dot com
17-Aug-2006 05:21
$xmlDoc=<<<XML
<?xml version="1.0"?>
<methodCall>
   <methodName>examples.getStateName</methodName>
   <params>
      <param>
         <value><i4>41</i4></value>
         </param>
      </params>
   </methodCall>
XML;

$xml= new DOMDocument();
$xml->preserveWhiteSpace=false;
$xml->loadXML($xmlDoc);
print_r(xml2array($xml));

function xml2array($n)
{
    $return=array();
    foreach($n->childNodes as $nc)
    ($nc->hasChildNodes())
    ?($n->firstChild->nodeName== $n->lastChild->nodeName&&$n->childNodes->length>1)
    ?$return[$nc->nodeName][]=xml2array($item)
    :$return[$nc->nodeName]=xml2array($nc)
    :$return=$nc->nodeValue;
    return $return;
}
massimo dot scamarcia at gmail dot com
20-Feb-2006 10:56
If you're moving from PHP4 to PHP5, you can keep your scripts untouched using this:

http://alexandre.alapetite.net/doc-alex/domxml-php4-php5/index.en.html
simlee at indiana dot edu
29-Dec-2005 08:16
The project I'm currently working on uses XPaths to dynamically navigate through chunks of an XML file.  I couldn't find any PHP code on the net that would build the XPath to a node for me, so I wrote my own function.  Turns out it wasn't as hard as I thought it might be (yay recursion), though it does entail using some PHP shenanigans... 

Hopefully it'll save someone else the trouble of reinventing this wheel.

<?php
   
function getNodeXPath( $node ) {
       
// REMEMBER THAT XPATHS USE BASE-1 INSTEAD OF BASE-0!!!
       
        // Get the index for the current node by looping through the siblings.
       
$parentNode = $node->parentNode;
        if(
$parentNode != null ) {
           
$nodeIndex = 0;
            do {
               
$testNode = $parentNode->childNodes->item( $nodeIndex );
               
$nodeName = $testNode->nodeName;
               
$nodeIndex++;
               
               
// PHP trickery!  Here we create a counter based on the node
                //  name of the test node to use in the XPath.
               
if( !isset( $$nodeName ) ) $$nodeName = 1;
                else $
$nodeName++;
               
               
// Failsafe return value.
               
if( $nodeIndex > $parentNode->childNodes->length ) return( "/" );
            } while( !
$node->isSameNode( $testNode ) );
           
           
// Recursively get the XPath for the parent.
           
return( getNodeXPath( $parentNode ) . "/{$node->nodeName}[{$$nodeName}]" );
        } else {
           
// Hit the root node!  Note that the slash is added when
            //  building the XPath, so we return just an empty string.
           
return( "" );
        }
    }
?>
johanwthijs-at-hotmail-dot-com
14-Dec-2005 02:25
Being an experienced ASP developer I was wondering how to replace textual content of a node (with msxml this is simply acheived by setting the 'text' property of a node). Out of frustration I started to play around with SimpleXml but I could not get it to work in combination with xPath.

I took me a lot of time to find out so I hope this helps others:

function replaceNodeText($objXml, $objNode, $strNewContent){
    /*
    This function replaces a node's string content with strNewContent
    */
    $objNodeListNested = &$objNode->childNodes;
    foreach ( $objNodeListNested as $objNodeNested ){
         if ($objNodeNested->nodeType == XML_TEXT_NODE)$objNode->removeChild ($objNodeNested);
    }
   
    $objNode->appendChild($objXml->createTextNode($strNewContent));
}

$objXml= new DOMDocument();
$objXml->loadXML('<root><node id="1">bla</note></root>');
$objXpath = new domxpath($objXml);

$strXpath="/root/node[@id='1']";
$objNodeList = $objXpath ->query($strXpath);
foreach ($objNodeList as $objNode){
//pass the node by reference
replaceNodeText($objXml, &$objNode, $strImportedValue);
}
mark at vectrex dot org dot uk
17-Nov-2005 10:10
Note that these DOM functions expect (and presumably return) all their data in UTF-8 character encoding, regardless of what PHP's current encoding is. This means that text nodes, attribute values etc, should be in utf8.

This applies even if you're generating an XML document which is not ultimately in utf8.

Mark
toby at tobiasly dot com
22-Oct-2005 06:08
This module is not included by default either in the CentOS 4 "centosplus" repository. For those using PHP5 on CentOS 4, a simple "yum --enablerepo=centosplus install php-xml" will do the trick (this will install both the XML and DOM modules).
pes_cz
29-Sep-2005 07:32
When I tried to parse my XHTML Strict files with DOM extension, it couldn't understand xhtml entities (like &copy;). I found post about it here (14-Jul-2005 09:05) which adviced to add resolveExternals = true, but it was very slow. There was some small note about xml catalogs but without any glue. Here it is:

XML catalogs is something like cache. Download all needed dtd's to /etc/xml, edit file /etc/xml/catalog and add this line: <public publicId="-//W3C//DTD XHTML 1.0 Strict//EN" uri="file:///etc/xml/xhtml1-strict.dtd" />

Thats all. Thanks to http://www.whump.com/moreLikeThis/link/03815
amir.laherATcomplinet.com
22-Aug-2005 12:09
This particular W3C page provides invaluable documentation for the DOM classes implemented in php5 (via libxml2). It fills in plenty of php.net's gaps:

http://www.w3.org/TR/DOM-Level-2-Core/core.html

Some key examples:
* concise summary of the class heirachy (1.1.1)
* clarification that DOM level 2 doesn't allow for population of internal DTDs
* explanation of DOMNode->normalize()
* explanation of the DOMImplementation class

The interfaces are described in OMG's Interface Definition Language
aidan at php dot net
19-Jul-2005 01:04
As of PHP 5.1, libxml options may be set using constants rather than the use of proprietary DomDocument properties.

DomDocument->resolveExternals is equivilant to setting
LIBXML_DTDLOAD
LIBXML_DTDATTR

DomDocument->validateOnParse is equivilant to setting
LIBXML_DTDLOAD
LIBXML_DTDVALID

PHP 5.1 users are encouraged to use the new constants.

Example:

DomDocument->load($file, LIBXML_DTDLOAD|LIBXML_DTDATTR);

DomDocument->load($file, LIBXML_DTDLOAD|LIBXML_DTDVALID);
aidan at php dot net
19-Jul-2005 03:27
When dealing with validation or loading, the output errors can be quite annoying.

PHP 5.1 introduces libxml_get_errors().

http://php.net/libxml_get_errors
php at webdevelopers dot cz
14-Jul-2005 07:05
[Editor's Note: If you're using entities, then you have no choice. XML Catalogs can speed DTD resolution.]

Never use

$dom->resolveExternals=true;

when parsing XHTML document that has the DOCTYPE declaration with DTD URL specified in it.

Otherwise parsing the XHTML with DOCTYPE like this one:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

will result in PHP/DOM downloading the DTD file from W3C site when parsing your document. It will add extra delay to your script - I experienced that $dom->load()'s total time was from 1 to 16 seconds.

elixon
spammable69 at hotmail dot com
12-Apr-2005 05:18
I wrote a framework to implement the StyleSheet interfaces as specified on the W3C website.  The code is written in PHP, and is NOT a complete implementation.  Use it how ya like.  I was planning on adding the CSSStyleSheet interfaces as well.  Feel free to ask.

<?
   
class StyleSheetList {
        public
length;
        private
self;
       
        function
__construct ( ) {
           
$this->self = array();
        }
       
        function
__get($property, $&ret) {
            if(
$property == 'length')
               
$ret = count($this->self);
            return
true;
        }
       
        function
__set($property, $val) {
            if(
$property == 'length')
                return
true;
        }
       
        function
item( $index ) {
            return
$this->self[$index];
        }
    }
   
    class
MediaList extends StyleSheetList {
       
        function
appendMedium ( $newMedium ) {
           
array_push($this->self, $newMedium);
        }
       
        function
deleteMedium ( $oldMedium ) {
            foreach(
$this->self as $item) {
                if(
$item == $oldMedium ) {
                   
$item = $this->self[ $this->length-1 ];
                   
array_pop($this->self);
                    break;
                }
            }
        }
    }
   
    class
DocumentStyle {
        public
styleSheets;
       
        function
__construct ( ) {
           
$this->styleSheets = new StyleSheetList();
        }
       
        function
__set($property, $val) {
            if(
$property == 'styleSheets')
                return
true;
        }
    }
   
    class
LinkStyle {
        public
sheet;
       
        function
__construct () {
           
$this->sheet = new StyleSheet();
        }
       
        function
__set($property, $val) {
            if(
$property == 'sheet')
                return
true;
        }
    }
   
    class
StyleSheet {
        public
type;
        public
disabled;
        public
ownerNode;
        public
parentStyleSheet;
        public
href;
        public
title;
        public
media;
       
        function
__construct( $type, $disabled, $ownerNode, $parentStyleSheet, $href, $title){
           
$this->type = $type;
           
$this->disabled = $disabled;
           
$this->media = new MediaList();
           
$this->ownerNode = $ownerNode;
           
$this->parentStyleSheet = $parentStyleSheet;
           
$this->href = $href;
           
$this->title = $title;
        }
    }
?>

Only contactable via http://murpsoft.com/contact.html
add a note

Introduction XML Manipulation
Last updated: Fri, 03 Apr 2009
 
 
show source | credits | sitemap | contact | advertising | mirror sites