XXIX. DOM Functions

简介

The DOM extension is the replacement for the DOM XML extension from PHP 4. The extension still contains many old functions, but they should no longer be used. In particular, functions that are not object-oriented should be avoided.

The extension allows you to operate on an XML document with the DOM API.

安装

本函数库作为 PHP 内核的一部分,不用安装就能使用。

预定义类

The API of the module follows the DOM Level 2 standard as closely as possible. Consequently, the API is fully object-oriented. It is a good idea to have the DOM standard available when using this module.

This module defines a number of classes, which are explained in the following tables. Classes with an equivalent in the DOM standard are named DOMxxx.

DOMAttr

Extends DOMNode. The DOMAttr interface represents an attribute in an DOMElement object.

构造函数

方法

属性

表格 1.

NameTypeRead-onlyDescription
namestringyesThe name of the attribute
ownerElementDOMElementyesThe element which contains the attribute
schemaTypeInfoboolyesNot implemented yet, always return NULL
specifiedboolyesNot implemented yet, always return NULL
valuestringnoThe value of the attribute

DOMCharacterData

Extends DOMNode.

方法

属性

表格 2.

NameTypeRead-onlyDescription
datastringnoThe contents of the node
lengthintyesThe length of the contents

DOMComment

Extends DOMCharacterData.

构造函数

DOMDocument

Extends DOMNode.

构造函数

方法

属性

表格 3.

NameTypeRead-onlyDescription
actualEncodingstringyes 
configDOMConfigurationyes 
doctypeDOMDocumentTypeyes The Document Type Declaration associated with this document.
documentElementDOMElementyes This is a convenience attribute that allows direct access to the child node that is the document element of the document.
documentURIstringno The location of the document or NULL if undefined.
encodingstringno 
formatOutputboolno 
implementationDOMImplementationyes The DOMImplementation object that handles this document.
preserveWhiteSpaceboolnoDo not remove redundant white space. Default to TRUE.
recoverboolno 
resolveExternalsboolno Set it to TRUE to load external entities from a doctype declaration. This is useful for including character entities in your XML document.
standaloneboolno 
strictErrorCheckingboolnoThrows DOMException on errors. Default to TRUE.
substituteEntitiesboolno 
validateOnParseboolnoLoads and validates against the DTD. Default to FALSE.
versionstringno 
xmlEncodingstringyes An attribute specifying, as part of the XML declaration, the encoding of this document. This is NULL when unspecified or when it is not known, such as when the Document was created in memory.
xmlStandaloneboolno An attribute specifying, as part of the XML declaration, whether this document is standalone. This is FALSE when unspecified.
xmlVersionstringno An attribute specifying, as part of the XML declaration, the version number of this document. If there is no declaration and if this document supports the "XML" feature, the value is "1.0".

DOMDocumentType

Extends DOMNode

Each DOMDocument has a doctype attribute whose value is either NULL or a DOMDocumentType object.

属性

表格 4.

NameTypeRead-onlyDescription
publicIdstringyesThe public identifier of the external subset.
systemIdstringyesThe system identifier of the external subset. This may be an absolute URI or not.
namestringyesThe name of DTD; i.e., the name immediately following the DOCTYPE keyword.
entitiesDOMNamedNodeMapyes A DOMNamedNodeMap containing the general entities, both external and internal, declared in the DTD.
notationsDOMNamedNodeMapyes A DOMNamedNodeMap containing the notations declared in the DTD.
internalSubsetstringyes The internal subset as a string, or null if there is none. This is does not contain the delimiting square brackets.

DOMElement

Extends DOMNode.

构造函数

方法

属性

表格 5.

NameTypeRead-onlyDescription
schemaTypeInfoboolyesNot implemented yet, always return NULL
tagNamestringyesThe element name

DOMEntity

Extends DOMNode

This interface represents a known entity, either parsed or unparsed, in an XML document.

属性

表格 6.

NameTypeRead-onlyDescription
publicIdstringyes The public identifier associated with the entity if specified, and NULL otherwise.
systemIdstringyes The system identifier associated with the entity if specified, and NULL otherwise. This may be an absolute URI or not.
notationNamestringyes For unparsed entities, the name of the notation for the entity. For parsed entities, this is NULL.
actualEncodingstringno An attribute specifying the encoding used for this entity at the time of parsing, when it is an external parsed entity. This is NULL if it an entity from the internal subset or if it is not known.
encodingstringyes An attribute specifying, as part of the text declaration, the encoding of this entity, when it is an external parsed entity. This is NULL otherwise.
versionstringyes An attribute specifying, as part of the text declaration, the version number of this entity, when it is an external parsed entity. This is NULL otherwise.

DOMEntityReference

Extends DOMNode.

构造函数

DOMException

DOM operations raise exceptions under particular circumstances, i.e., when an operation is impossible to perform for logical reasons.

See also 20 章.

属性

表格 7.

NameTypeRead-onlyDescription
codeintyesAn integer indicating the type of error generated

DOMImplementation

The DOMImplementation interface provides a number of methods for performing operations that are independent of any particular instance of the document object model.

构造函数

方法

DOMNode

方法

属性

表格 8.

NameTypeRead-onlyDescription
nodeNamestringyesReturns the more accurate name for the current node type
nodeValuestringnoThe value of this node, depending on its type.
nodeTypeintyesGets the type of the node. One of the predefined XML_xxx_NODE constants
parentNodeDOMNodeyesThe parent of this node.
childNodesDOMNodeListyes A DOMNodeList that contains all children of this node. If there are no children, this is an empty DOMNodeList.
firstChildDOMNodeyes The first child of this node. If there is no such node, this returns NULL.
lastChildDOMNodeyes The last child of this node. If there is no such node, this returns NULL.
previousSiblingDOMNodeyes The node immediately preceding this node. If there is no such node, this returns NULL.
nextSiblingDOMNodeyes The node immediately following this node. If there is no such node, this returns NULL.
attributesDOMNamedNodeMapyes A DOMNamedNodeMap containing the attributes of this node (if it is a DOMElement) or NULL otherwise.
ownerDocumentDOMDocumentyes The DOMDocument object associated with this node.
namespaceURIstringyes The namespace URI of this node, or NULL if it is unspecified.
prefixstringno The namespace prefix of this node, or NULL if it is unspecified.
localNamestringyes Returns the local part of the qualified name of this node.
baseURIstringyes The absolute base URI of this node or NULL if the implementation wasn't able to obtain an absolute URI.
textContentstringno This attribute returns the text content of this node and its descendants.

DOMNodeList

方法

属性

表格 9.

NameTypeRead-onlyDescription
lengthintyes The number of nodes in the list. The range of valid child node indices is 0 to length - 1 inclusive.

DOMNotation

Extends DOMNode

属性

表格 10.

NameTypeRead-onlyDescription
publicIdstringyes 
systemIdstringyes 

DOMProcessingInstruction

Extends DOMNode.

构造函数

属性

表格 11.

NameTypeRead-onlyDescription
targetstringyes 
datastringno 

DOMText

Extends DOMCharacterData.

构造函数

方法

属性

表格 12.

NameTypeRead-onlyDescription
wholeTextstringyes 

DOMXPath

构造函数

方法

属性

表格 13.

NameTypeRead-onlyDescription
documentDOMDocument  

范例

Many examples in this reference require an XML file. We will use book.xml that contains the following:

例子 1. chapter.xml

<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
 "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [
]>
<book id="listing">
 <title>My lists</title>
 <chapter id="books">
  <title>My books</title>
  <para>
   <informaltable>
    <tgroup cols="4">
     <thead>
      <row>
       <entry>Title</entry>
       <entry>Author</entry>
       <entry>Language</entry>
       <entry>ISBN</entry>
      </row>
     </thead>
     <tbody>
      <row>
       <entry>The Grapes of Wrath</entry>
       <entry>John Steinbeck</entry>
       <entry>en</entry>
       <entry>0140186409</entry>
      </row>
      <row>
       <entry>The Pearl</entry>
       <entry>John Steinbeck</entry>
       <entry>en</entry>
       <entry>014017737X</entry>
      </row>
      <row>
       <entry>Samarcande</entry>
       <entry>Amine Maalouf</entry>
       <entry>fr</entry>
       <entry>2253051209</entry>
      </row>
      <!-- TODO: I have a lot of remaining books to add.. -->
     </tbody>
    </tgroup>
   </informaltable>
  </para>
 </chapter>
</book>

预定义常量

以下常量由本扩展模块定义,因此只有在本扩展模块被编译到 PHP 中,或者在运行时被动态加载后才有效。

表格 14. XML constants

ConstantValueDescription
XML_ELEMENT_NODE (integer) 1Node is a DOMElement
XML_ATTRIBUTE_NODE (integer) 2Node is a DOMAttr
XML_TEXT_NODE (integer) 3Node is a DOMText
XML_CDATA_SECTION_NODE (integer) 4Node is a DOMCharacterData
XML_ENTITY_REF_NODE (integer) 5Node is a DOMEntityReference
XML_ENTITY_NODE (integer) 6Node is a DOMEntity
XML_PI_NODE (integer) 7Node is a DOMProcessingInstruction
XML_COMMENT_NODE (integer) 8Node is a DOMComment
XML_DOCUMENT_NODE (integer) 9Node is a DOMDocument
XML_DOCUMENT_TYPE_NODE (integer) 10Node is a DOMDocumentType
XML_DOCUMENT_FRAG_NODE (integer) 11Node is a DOMDocumentFragment
XML_NOTATION_NODE (integer) 12Node is a DOMNotation
XML_HTML_DOCUMENT_NODE (integer) 13 
XML_DTD_NODE (integer) 14 
XML_ELEMENT_DECL_NODE (integer) 15 
XML_ATTRIBUTE_DECL_NODE (integer) 16 
XML_ENTITY_DECL_NODE (integer) 17 
XML_NAMESPACE_DECL_NODE (integer) 18 
XML_ATTRIBUTE_CDATA (integer) 1 
XML_ATTRIBUTE_ID (integer) 2 
XML_ATTRIBUTE_IDREF (integer) 3 
XML_ATTRIBUTE_IDREFS (integer) 4 
XML_ATTRIBUTE_ENTITY (integer) 5 
XML_ATTRIBUTE_NMTOKEN (integer) 7 
XML_ATTRIBUTE_NMTOKENS (integer) 8 
XML_ATTRIBUTE_ENUMERATION (integer) 9 
XML_ATTRIBUTE_NOTATION (integer) 10 

表格 15. DOMException constants

ConstantValueDescription
DOM_INDEX_SIZE_ERR (integer) 1 If index or size is negative, or greater than the allowed value.
DOMSTRING_SIZE_ERR (integer) 2 If the specified range of text does not fit into a DOMString.
DOM_HIERARCHY_REQUEST_ERR (integer) 3If any node is inserted somewhere it doesn't belong
DOM_WRONG_DOCUMENT_ERR (integer) 4 If a node is used in a different document than the one that created it.
DOM_INVALID_CHARACTER_ERR (integer) 5 If an invalid or illegal character is specified, such as in a name.
DOM_NO_DATA_ALLOWED_ERR (integer) 6 If data is specified for a node which does not support data.
DOM_NO_MODIFICATION_ALLOWED_ERR (integer) 7 If an attempt is made to modify an object where modifications are not allowed.
DOM_NOT_FOUND_ERR (integer) 8 If an attempt is made to reference a node in a context where it does not exist.
DOM_NOT_SUPPORTED_ERR (integer) 9 If the implementation does not support the requested type of object or operation.
DOM_INUSE_ATTRIBUTE_ERR (integer) 10 If an attempt is made to add an attribute that is already in use elsewhere.
DOM_INVALID_STATE_ERR (integer) 11 If an attempt is made to use an object that is not, or is no longer, usable.
DOM_SYNTAX_ERR (integer) 12If an invalid or illegal string is specified.
DOM_INVALID_MODIFICATION_ERR (integer) 13If an attempt is made to modify the type of the underlying object.
DOM_NAMESPACE_ERR (integer) 14 If an attempt is made to create or change an object in a way which is incorrect with regard to namespaces.
DOM_INVALID_ACCESS_ERR (integer) 15 If a parameter or an operation is not supported by the underlying object.
DOM_VALIDATION_ERR (integer) 16 If a call to a method such as insertBefore or removeChild would make the Node invalid with respect to "partial validity", this exception would be raised and the operation would not be done.
目录
DOMAttr->__construct() --  Creates a new DOMAttr object
DOMAttr->isId() --  Checks if attribute is a defined ID
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->__construct() --  Creates a new DOMComment object
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->normalize() --  Normalizes the document
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
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
DOMAttr->__construct() --  Creates a new DOMEntityReference object
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->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->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->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->item() --  Retrieves a node specified by index
DOMProcessingInstruction->__construct() --  Creates a new DOMProcessingInstruction object
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->__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_import_simplexml --  Gets a DOMElement object from a SimpleXMLElement object

add a note add a note User Contributed Notes
cormac at idreamproducts dot com
17-Oct-2006 06: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();
}
?>
herwig dot huber at pythia dot at
13-Oct-2006 04:09
Another XML2Array function:

<?
$xmldoc
= '<?xml version="1.0" encoding="ISO-8859-1"?>
<Pythia>
   <Car>
       <CarId>123</CarId>
       <CarName>Lada</CarName>
       <CarDriver></CarDriver>
       <CarOwner>Trotzky</CarOwner>
       <Engine>
           <Valves>12</Valves>
           <Power>140PS</Power>
       </Engine>
   </Car>
</Pythia>'
;

$a = array();

function
XmlToArray( &$a, $DomDocument )
{
   foreach(
$DomDocument->childNodes AS $ChildNode )
   {
       if (
$ChildNode->nodeName != '#text' )
       {
          
//echo "<font color='red'>".$ChildNode->nodeName . "</font>, " . $ChildNode->nodeValue . ", <font color=green>" . $ChildNode->childNodes->length . "</font><BR>";
          
if ( $ChildNode->childNodes->length < 2 )
           {
              
XmlToArray( $a, $ChildNode );
              
$a[ $ChildNode->nodeName ] = $ChildNode->nodeValue;
           }
           else
           {
              
XmlToArray( $a[$ChildNode->nodeName], $ChildNode );
           }
       }
   }
}

$xml = new DOMDocument();
$xml->LoadXML( $xmldoc );

XmlToArray( $a, $xml );

print_r( $a );
?>

output:

Array
(
   [Pythia] => Array
       (
           [Car] => Array
               (
                   [CarId] => 123
                   [CarName] => Lada
                   [CarDriver] =>
                   [CarOwner] => Trotzky
                   [Engine] => Array
                       (
                           [Valves] => 12
                           [Power] => 140PS
                       )
               )
       )
)
ashwinee_raut at yahoo dot com
24-Aug-2006 06:39
I found a lot about how to add new elements to existing xml file using PHP 5.0.4.
Here is the code-
$file_name="my_xml.xml";

$dom = new DomDocument();
$dom->load($file_name);

$item = $dom->createElement("item");
$title = $dom->createElement("title");
$link=$dom->createElement("link");
$titletext = $dom->createTextNode("New Title");
$title->appendChild($titletext);
$link_text=$dom->createTextNode("New Link");
$link->appendChild($link_text);
$item->appendChild($title);
$item->appendChild($link);
$dom->documentElement->appendChild($item);
$dom->save($file_name);

This will load xml file.. append new element to it and then save it back to the file..
sean at lookin3d dot com
18-Aug-2006 01: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;
}
bernat dot wiandt at gmail dot com
12-Aug-2006 11:33
Reply-to: com dot yahoo at adjwilli

it's easier to use xpath instead your function. this should solve your problem:

"//*[@attr_name]" where attr_name is the attribute name

it will return all nodes that have the attribute "attr_name"
you can evaluate xpath with DOMXPath->query() or DOMXPath->evaluate()

you can learn more about xpath at http://www.w3schools.com/xpath/xpath_intro.asp
com dot yahoo at adjwilli
17-Jul-2006 11:48
Here's a function to get a node by attribute. I thought I'd post it to save other people from reinventing the wheel too. $attr is the attribute the node should have, $nodeID is the value you're looking for in that attribute, and $xmldoc is the doc you're looking in. I'd also welcome suggestion to make this function more efficient.

function getNodeByAttr ($attr,$nodeID,$xmldoc) {
   if ($xmldoc->hasChildNodes()) {
       $children = $xmldoc->childNodes;
       foreach($children as $node) {
           if ($node->hasAttributes()) {
               $attributes = $node->attributes;
               foreach ($attributes as $attribute) {
                   if (($attribute->name == $attr) && ($attribute->value == $nodeID)) {
                       return $node;
                   } else {
                       if (getNodeByAttr($attr,$nodeID,$node)) {
                           return getNodeByAttr($attr,$nodeID,$node);
                       }
                   }
               }
           } else {
               if (getNodeByAttr($attr,$nodeID,$node)) {
                   return getNodeByAttr($attr,$nodeID,$node);
               }
           }
       }
   } else {
       return null;
   }
}
medyk dot php dot net at medikoo dot com
17-Apr-2006 08:19
In installation notes it is stated that DOM functions are part of php core. Which is not exactly true (at least for 5.1x branch). They're loaded by default but they're not part of a core. If you use --disable-all in cofigure options and want to use DOM functions you need to add --enable-dom and --enable-libxml to have it.
When not using --disable-all you can take out DOM functionality from your installation using --disable-dom
massimo dot scamarcia at gmail dot com
20-Feb-2006 06: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
me at somewhere dot com
08-Jan-2006 11:56
When using include/require statements to bring in common PHP code, you may accidentally put a blank line after the trailing "?>" in the included file (ie. two newlines following the "?>" sequence). The output will contain these blank lines and, for outputting HTML, this is no biggie as web browsers are usually relaxed about parsing HTML syntax. However, XML output generated via DOMDocument->saveXML() will be checked more carefully, and XML parsers (like the one that comes with firefox/mozilla) will complain that the <?xml ....?> tag doesn't begin on the first line.

While the best solution is to make sure blank lines do not trail in the included files, you can't always guarentee that a set of include files you grab from the internet will comply. Since the nature of DOM XML generation involves building the DOM structure first, then converting it all to XML, and finally printing it all in one shot, you can safely wipe any blank lines that snuck into the output buffer when files were getting included by calling ob_clear() right before printing/echoing the XML:

dom.php:
<?php
$doc
= new DOMDocument('1.0', 'iso-8859-1');
$doc->formatOutput = true;
?>
...garbage trailing at the end....

foobar.php:
<?php
include 'dom.php'

//Build up $doc here

header("Content-type: text/xml");
ob_clean();
echo
$doc->saveXML();
?>
simlee at indiana dot edu
29-Dec-2005 04: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 10: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
18-Nov-2005 06: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
23-Oct-2005 02: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 03: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 08: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
lhaire at lettres dot unige dot ch
19-Aug-2005 12:39
Text nodes contain utf-8 encoding internally, no matter if you specify iso-8859-1 in the file you parse or create a new doc using

$xmltree = new DomDocument('1.0','iso-8859-1');

The solution is to use utf8_decode

$original =
utf8_decode(
$myitem->getElementsByTagName('ORIGINAL')->item(0)->nodeValue);
aidan at php dot net
19-Jul-2005 09: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 11: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
15-Jul-2005 03: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 01: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
shruti224 at yahoo dot com
31-Mar-2005 11:25
my bad..its not an attribute ..its a text element node so if one checks for that, it can be easily corrected.

Wrote the corrected function. I hope it takes care of all conditions. If someone finds any issues with it, I would be glad to know about it.

function readXml($domnode, &$array)
{
       $array_ptr = &$array;
       $domnode = $domnode->firstChild;
       while (!is_null($domnode))
       {
               switch ($domnode->nodeType)
               {
                       case XML_TEXT_NODE:      if(!(trim($domnode->nodeValue) == ""))
                                                       $array_ptr['cdata'] = $domnode->nodeValue;
                                               break;
                       case XML_ELEMENT_NODE:
                                               $array_ptr = &$array[$domnode->nodeName][];
                                               if ($domnode->hasAttributes() )
                                               {
                                                       $attributes = $domnode->attributes;
                                                       foreach ($attributes as $index => $domobj)
                                                       {
                                                             $array_ptr[$domobj->name] = $domobj->value;
                                                       }
                                               }
                                               break;
               }
               if ( $domnode->hasChildNodes() )
               {
                       readXml($domnode, $array_ptr);
               }
               $domnode = $domnode->nextSibling;
       }
}
roger4a45 at yahoo dot es
23-Feb-2005 07:35
Output a special chars like &agrave in your XML/XSLT

Following example create a easy XML that is transformed by a xsl i'll show below:

XSL FILE v1.xsl

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.w3.org/TR/REC-html40">
<xsl:template match="TEST">
<xsl:value-of select="NAME"/><BR/>
</xsl:template>
</xsl:stylesheet>

PHP SOURCE CODE

<?php
$xml
= new DOMDocument('1.0', 'utf-8'); //Change encoding to utf-8
$xsl = new DOMDocument;
$xsl->load('v1.xsl');
$proc = new XSLTProcessor;
$root = $xml->CreateElement("TEST");
$val = utf8_encode ('Andrs Poluk'); //New Line
$child = $xml->CreateElement("NAME",$val);
$root->appendChild($child);
$xml->appendChild($root);
$proc->importStyleSheet($xsl);
echo
$proc->transformToXML($xml);   
?>
oliver dot christen at camptocamp dot com
20-Nov-2004 12:20
simple exemple of how to get the value of an attribute, delete that attribute and create a new element at the place we want with the value of the attribute

<?xml version="1.0"?>

<book type="paperback">
   <title name='MAP'>Red Nails</title>
   <price>$12.99</price>
   <author>
       <name first="Robert" middle="E" last="Howard"/>
       <birthdate>9/21/1977</birthdate>
   </author>
</book>

<?php

//filename xml file to use
$file = 'book.xml';

$doc = new domDocument;

if (
file_exists($file)) {
  
$doc->load($file);
} else {
   exit(
'Erreur !.');
}

$xpath = new domXPath($doc);

$query = "//author/*";
$xpathQuery = $xpath->query($query);

// a for loop to iterate all the elements in the xpathQuery nodelist and allow us to find what we want
// i could have used a while loop also, use what you prefer
$size = $xpathQuery->length;
for (
$i=0; $i<$size; $i++){
  
$node = $xpathQuery->item($i);
   if (
$node->nodeName == 'name' && $node->hasAttributes()){

       foreach (
$node->attributes as $attribute) {
           if (
$attribute->name == 'last' && $attribute->value == 'Howard'){
               foreach (
$node->attributes as $attribute) {
                   if (
$attribute->name == 'first'){
                      
// get first name value
                      
$firstname = $attribute->value;
                      
// we need the current node later so we know where to add the new element
                      
$refnode = $node;
                      
// remove the firstname attribut
                      
$node->removeAttribute('first');
                   }
               }
           }
       }
   }
}
if (isset(
$refnode)) {
  
// we need the parent node (see below)
  
$parentnode = $refnode->parentNode;
  
// creat new element firstname
  
$newnode = $doc->createElement('firstname', $firstname);
  
// optional, creat a linebreak element
  
$newtextnode = $doc->createTextNode(chr(10));
  
// insert the new element before the reference node (in this case, the 'name' node)
  
$newnode = $parentnode->insertBefore($newnode, $refnode);
  
// optional, insert the linebreak before the reference node, hence after the new 'firstname' element
  
$newtextnode = $parentnode->insertBefore($newtextnode, $refnode);
}

print
$doc->saveXML();

?>