 |
XXX. DOM XML Functions
The DOM XML extension has been overhauled in PHP 4.3.0 to better comply with
the DOM standard. 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.
It also provides a function domxml_xmltree() to turn the
complete XML document into a tree of PHP objects. Currently, this
tree should be considered read-only - you can modify it, but this
would not make any sense since DomDocument_dump_mem()
cannot be
applied to it. Therefore, if you want to read an XML file and write
a modified version, use DomDocument_create_element(),
DomDocument_create_text_node(),
set_attribute(), etc. and finally the
DomDocument_dump_mem() function.
注:
本扩展已被移动到 PECL 库中且自以下版本起不再被绑定到 PHP 中:5.0.0.
注:
This extension is no longer marked experimental. It will, however, never
be released with PHP 5, and will only be distributed with PHP 4.
If you need DOM XML support with PHP 5 you can use the
DOM extension. This
domxml extension is not compatible with the
DOM extension.
This extension makes use of the
GNOME XML library. Download
and install this library. You will need at least libxml-2.4.14.
To use DOM XSLT features you can use the
libxslt library and EXSLT
enhancements from http://www.exslt.org/.
Download and install these libraries if you plan to use (enhanced) XSLT
features. You will need at least libxslt-1.0.18.
本 PECL 扩展未绑定于 PHP 中。
进一步信息例如新版本,下载,源程序,维护者信息以及更新日志可以在此找到:
http://pecl.php.net/package/domxml.
在 PHP 4 中本 PECL 扩展的源程序位于
PHP 源程序中的 ext/ 目录下或者在上面的
PECL 连接中。
This extension is only available if PHP was configured with
--with-dom[=DIR]. Add
--with-dom-xslt[=DIR] to include DOM
XSLT support. DIR is the libxslt install directory. Add
--with-dom-exslt[=DIR] to include DOM
EXSLT support, where DIR is the libexslt install directory.
Windows users will enable php_domxml.dll inside
of php.ini in order to use these functions.
在 PHP 4 中本 DLL 位于
PHP Windows 执行包中的 extensions/ 目录下。
可以从 PHP
下载页面或者 http://snaps.php.net/
下载此 PECL 扩展的
DLL 文件。
Also, there is one additional DLL that must be made available to your
system's PATH in order for this extension to work. In PHP 4 this is
in the dlls/ directory. It's name:
For PHP <= 4.2.0, it's libxml2.dll.
For PHP >= 4.3.0, it's iconv.dll.
And as of PHP 5.0.0, iconv is compiled into your Windows PHP binaries by
default so no extra DLL is needed.
There are quite a few functions that do not fit into the DOM standard and
should no longer be used. These functions are listed in the following table.
The function DomNode_append_child() has changed its
behaviour. It now adds a child and not a sibling. If this
breaks your application, use the non-DOM function
DomNode_append_sibling().
表格 1. Deprecated functions and their replacements
以下常量由本扩展模块定义,因此只有在本扩展模块被编译到
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.
Though the API is object-oriented, there are many functions which can
be called in a non-object-oriented way by passing the object to operate
on as the first argument. These functions are mainly to retain compatibility
to older versions of the extension, and should not be used when creating new
scripts.
This API differs from the official DOM API in two ways. First, all
class attributes are implemented as functions with the same name.
Secondly, the function names follow the PHP naming convention. This means
that a DOM function lastChild() will be written as last_child().
This module defines a number of classes, which are listed -
including their
method - in the following tables. Classes with an equivalent in the
DOM standard are named DOMxxx.
表格 3. List of classes Class name | Parent classes |
---|
DomAttribute | DomNode | DomCData | DomNode | DomComment | DomCData : DomNode | DomDocument | DomNode | DomDocumentType | DomNode | DomElement | DomNode | DomEntity | DomNode | DomEntityReference | DomNode | DomProcessingInstruction | DomNode | DomText | DomCData : DomNode | Parser | Currently still called DomParser | XPathContext | |
表格 4. DomDocument class (DomDocument : DomNode)
表格 5. DomElement class (DomElement : DomNode)
表格 7. DomAttribute class (DomAttribute : DomNode)
表格 8. DomProcessingInstruction class (DomProcessingInstruction : DomNode)
表格 9. Parser class Method name | Function name | Remark |
---|
add_chunk | Parser_add_chunk() | | end | Parser_end() | |
表格 10. XPathContext class Method name | Function name | Remark |
---|
eval | XPathContext_eval() | | eval_expression | XPathContext_eval_expression() | | register_ns | XPathContext_register_ns() | |
表格 11. DomDocumentType class (DomDocumentType : DomNode)
The classes DomDtd is derived from DomNode. DomComment is derived from
DomCData.
Many examples in this reference require an XML string. Instead of
repeating this string in every example, it will be put into a file
which will be included by each example. This include file is shown in the
following example section. Alternatively, you could create an XML document and
read it with DomDocument_open_file().
例子 1. Include file example.inc with XML string
<?php $xmlstr = "<?xml version='1.0' standalone='yes'?> <!DOCTYPE chapter SYSTEM '/share/sgml/Norman_Walsh/db3xml10/db3xml10.dtd' [ <!ENTITY sp \"spanish\"> ]> <!-- lsfj --> <chapter language='en'><title language='en'>Title</title> <para language='ge'> &sp; <!-- comment --> <informaltable ID='findme' language='&sp;'> <tgroup cols='3'> <tbody> <row><entry>a1</entry><entry morerows='1'>b1</entry><entry>c1</entry></row> <row><entry>a2</entry><entry>c2</entry></row> <row><entry>a3</entry><entry>b3</entry><entry>c3</entry></row> </tbody> </tgroup> </informaltable> </para> </chapter>"; ?>
|
|
junk at gieson dot com
30-Jan-2006 12:13
### Moderator:
### This is a very slight tweak to to the dom_to_simple_array function posted earliers by jas at uci dot edu. I recommend just editing the previous post rather than posting the function again.
---------------------------------
The previously posted dom_to_simple_array function has a slight error, which prevents PHP from processing if there are attributes present.
The line that reads:
$attributes = $domnode->attributes();
... should read:
$attributes = $domnode->attributes;
---------------------------------
Here is the full code again with the correction:
function dom_to_simple_array($domnode, &$array) {
$array_ptr = &$array;
$domnode = $domnode->firstChild;
while (!is_null($domnode)) {
if (! (trim($domnode->nodeValue) == "") ) {
switch ($domnode->nodeType) {
case XML_TEXT_NODE: {
$array_ptr['cdata'] = $domnode->nodeValue;
break;
}
case XML_ELEMENT_NODE: {
$array_ptr = &$array[$domnode->nodeName][];
if ($domnode->hasAttributes() ) {
$attributes = $domnode->attributes;
if (!is_array ($attributes)) {
break;
}
foreach ($attributes as $index => $domobj) {
$array_ptr[$index] = $array_ptr[$domobj->name] = $domobj->value;
}
}
break;
}
}
if ( $domnode->hasChildNodes() ) {
dom_to_simple_array($domnode, $array_ptr);
}
}
$domnode = $domnode->nextSibling;
}
}
Palatinusz - karoly_szalkary at yahoo dot com
25-Jan-2006 08:05
My short way of parsing an XML document, for example displaying the document in a structured form:
<?php
$indent = "";
$file = "semi.xml";
$showfile = file_get_contents("c:/Program Files/Apache Group/apache/htdocs/phpxml" . "/" . $file); // whatever path
// maybe the whole path is not important, look it up in other posts
$newstring=utf8_encode($showfile); // it's important!
if(!$domDocument = domxml_open_mem($newstring)) {
echo "Couldn't load xml...";
exit;
}
$rootDomNode = $domDocument->document_element();
print "<pre>";
printElements($rootDomNode);
print "</pre>";
function printElements($domNode)
{
if($domNode)
{
global $indent;
if($domNode->node_type() == XML_ELEMENT_NODE)
{
print "<br />".$indent."<".$domNode->node_name();
if($domNode->has_attributes())
{
$attributes = $domNode->attributes();
foreach($attributes as $domAttribute)
{
print " $domAttribute->name=\"$domAttribute->value\"";
}
}
print ">";
if($domNode->has_child_nodes())
{
$indent.=" ";
$nextNode = $domNode->first_child();
printElements($nextNode);
$indent= substr($indent, 0, strlen($indent)-2);
print "<br />".$indent."<"."/".$domNode->node_name().">";
}
else
{
print "$domNode->node_value()</".$domNode->node_name().">";
}
}
$nextNode = $domNode->next_sibling();
printElements($nextNode);
}
}
?>
Squiz
14-Dec-2005 03:04
Re: websiterepairguys... Close but no cigar ;-)
As written it will not work if the repeated tags are somewhere other than the first node, i.e. the following will not work:
<nodes>
<node>onething</node>
<node>something</node>
<node>something</node>
</nodes>
You must store the new node name when you get a new sibling that doesn't match the previous and then it will work OK. Amended code:
function dom_to_array($domnode, &$array) {
$parent=$domnode;
$domnode = $domnode->firstChild;
$myname=$domnode->nodeName;
$x=1;
while (!is_null($domnode)) {
switch ($domnode->nodeType) {
case XML_ELEMENT_NODE: {
if ( !$domnode->hasChildNodes()) {
$array[$domnode->nodeName]='';
} else if ( $domnode->hasChildNodes() && $domnode->firstChild->nodeType==XML_TEXT_NODE) {
$array[$domnode->nodeName]=$domnode->firstChild->nodeValue;
} else if ( $domnode->hasChildNodes() ) {
$array_ptr = & $array[$domnode->nodeName];
dom_to_array($domnode, $array_ptr);
}
break;
}
}
$domnode = $domnode->nextSibling;
if($domnode->nodeName == $myname)
{
$domnode->nodeName.=($x++);
} else {
$myname = $domnode->nodeName;
}
}
}
websiterepairguys at spamnot dot yahoo dot com
12-Nov-2005 01:43
I tried using the dom_to_simple_array that the user jas posted above, but it didnt work very well.
The problems were it didnt handle sibling nodes with the same name, such as:
<nodes>
<node>something</node>
<node>something</node>
</nodes>
Also, when it built child arrays from child nodes, it always interjected an wrapping array around the child, which isnt necessary. Here is the patched code:
function dom_to_array($domnode, &$array) {
$parent=$domnode;
$domnode = $domnode->firstChild;
$myname=$domnode->nodeName;
$x=1;
while (!is_null($domnode)) {
switch ($domnode->nodeType) {
case XML_ELEMENT_NODE: {
if ( !$domnode->hasChildNodes()) {
$array[$domnode->nodeName]='';
} else if ( $domnode->hasChildNodes() && $domnode->firstChild->nodeType==XML_TEXT_NODE) {
$array[$domnode->nodeName]=$domnode->firstChild->nodeValue;
} else if ( $domnode->hasChildNodes() ) {
$array_ptr = & $array[$domnode->nodeName];
dom_to_array($domnode, $array_ptr);
break;
}
}
}
$domnode = $domnode->nextSibling;
if($domnode->nodeName==$myname)
{
$domnode->nodeName.=($x++);
}
}
}
snippet of array produced by this:
[admin] => Array
(
[menu] => Array
(
[title] => Page Manager
[view] => list
)
[files] => Array
(
[filename] => modules/testmodule/testmodule.php
[filename1] => modules/testmodule/testmodule.xml
[filename2] => media/lang/en-us/templates/testmodule.tpl
)
)
timo dot hummel at 4fb dot de
07-Jul-2005 03:57
If you want to subclass the domxml-classes, you have to use PHP5. It doesn't work with PHP4, and never will.
steve at find-information-on dot com
12-Feb-2005 08:33
If you are using apache, instead of copying files around (iconv.dll for instance) you can use this in your httpd.conf for apache:
LoadFile "d:/php/dlls/iconv.dll"
I placed this line before
LoadModule php4_module "d:/php/sapi/php4apache2.dll"
and it worked, no copying of files or anything therefore helps when updating php, don't have to mess around searching for files and other stuff.
ndaniel at bsi-scs dot com
22-Dec-2004 09:54
I recently developed a script for parsing DHL XML transaction responses - finding it a pain in the rear to actually parse the XML and set my variables - it actually wasn't that hard once I figured it out - and it goes something like this...
<?php
// Use with a class containing functions set_attributes() and
// set_data(). Use the following to set variables from the
// resulting xml. $node is a dom xml object - in the first call
// to loop, $node would be equal to the root document
// element.
function loop($node) {
// set attribute tags here
if ($node->has_attributes()) {
$this->set_attributes($node);
} // end if node has attributes
if ($node->has_child_nodes()) {
$this->loop($node->first_child());
} // end if node has child
else {
$this->set_data($node);
} // end if node has no child
// get next sibling
$node = $node->next_sibling();
if ($node) {
$this->loop($node);
} // end if node
} // end function loop
?>
The code goes from the root element, if the element has attributes - it sets attribute variables. Second, it recursively proceeds to the lowest level element (no more children). Once that level has been reached, data variables are set. The next step goes to the next sibling of the element, if it exists. If the next sibling does not exists, the function is ended and the current element is returned to the parent element. The parent element is then checked for siblings. This process continues (as is with recursion) until the parent element is back at the root element, which is the end of the document.
deborah dot seidman at imc-fr dot com
11-Dec-2004 12:15
You can always use a sax parser (expat) which saves on memory storage (there is none as sax is event driven) and use this neat code to produce an array structure of you xml file :
see http://fr2.php.net/manual/fr/function.xml-parse.php
comment by
tgrabietz at bupnet dot de
22-Sep-2004 05:05
jas at uci dot edu
16-Nov-2004 07:56
i needed to have an easy way to create a multi-dimensional but EXTREMELY SIMPLE php array out of some XML text i'm receiving. NOT an object. just an ARRAY.
i found that as simple a request as this seemed to be, the new (php5) DOM functions do not provide this functionality.
even the SimpleXML functions are object-oriented, which doesn't work for some of my purposes (sending to a Smarty template variable for looping through, etc.) -- returning attributes as SimpleXMLElement objects instead of strings, etc.. i just wanted an ARRAY containing the data as STRINGS.
eli (http://www.hoktar.com) had submitted such code earlier, based on domxml/php4 calls. his function was called "domxml_xmlarray".
but when php5 came out, eli's comments at the bottom of the PHP site got erased. (fortunately, i had already saved his code.) no doubt, mine will too w/next version..
furthermore, as far as i can tell, no one has taken the cue to add something like eli's domxml_xmlarray function directly into the DOMDocument object (but it would be nice).
so i translated eli's code, now using the dom calls (instead of the older domxml calls), and renamed the function to "dom_to_simple_array()".
below is a script containing the function itself as well as an example of its use. just copy it to your server somewhere and execute it and it should work right off the bat if you are using php5.
thanks.
jeff stern
==================================================================
<?php
function dom_to_simple_array($domnode, &$array) {
$array_ptr = &$array;
$domnode = $domnode->firstChild;
while (!is_null($domnode)) {
if (! (trim($domnode->nodeValue) == "") ) {
switch ($domnode->nodeType) {
case XML_TEXT_NODE: {
$array_ptr['cdata'] = $domnode->nodeValue;
break;
}
case XML_ELEMENT_NODE: {
$array_ptr = &$array[$domnode->nodeName][];
if ($domnode->hasAttributes() ) {
$attributes = $domnode->attributes ();
if (!is_array ($attributes)) {
break;
}
foreach ($attributes as $index => $domobj) {
$array_ptr[$index] = $array_ptr[$domobj->name] = $domobj->value;
}
}
break;
}
}
if ( $domnode->hasChildNodes() ) {
dom_to_simple_array($domnode, $array_ptr);
}
}
$domnode = $domnode->nextSibling;
}
}
# now, let's make a sample string containing some XML
$strXMLData = "<contacts>
<contact>
<name>
John Doe
</name>
<phone>
123-456-7890
</phone>
</contact>
<contact>
<name>
Mary Smiley
</name>
<phone>
567-890-1234
</phone>
</contact>
</contacts>";
# create a DOM tree xml object (hierarchical array) from
# this XML string
$domdoc = new DOMDocument;
$domdoc->loadXML($strXMLData);
# now simplify the DOM array into a very simple array structure
# first, create an empty array to be filled with your
# simplified array result..
$aData = array();
# now, pass the dom document and your empty array to the
# converter function.
dom_to_simple_array($domdoc, $aData);
# now $aData contains your simplified array, so print it out
?><html>
<body>
<p>there are <? echo count($aData['contacts'][0]['contact']); ?>
contacts</p>
<p>the 2nd contact's phone number is
<?echo $aData['contacts'][0]['contact'][1]['phone'][0]['cdata']; ?>
</p>
<hr />
<p>Here is the raw array structure:</p>
<pre>
<? print_r($aData); ?>
</pre>
</body>
</html>
==================================================================
Alex
05-Jul-2004 12:48
PHP4/DOMXML code is not compatible with the new PHP5/dom extension. While the conversion is quite strait forward, it can take a long time if domxml has been broadly used. Moreover, it can be interesting to have old PHP4 scripts ready for PHP5 as soon as possible even if the server is still running PHP4. Since I have that kind of problem, if have written a small library to include in PHP4 scripts to enable them to be run on PHP5. http://alexandre.alapetite.net/doc-alex/domxml-php4-php5/
It does not cover all the domxml functionality, but most of the main functions and can easily be extended. Tested with PHP4.3.7 and PHP5.0.0RC3 but I will try to keep it updated. I hope it can help.
SAM
23-Apr-2004 02:05
When installing PHP --with-dom and --with-dom-xslt on a Red Hat 9.0 remember to install the following packages:
libxml
libxml2
libxml2-devel
libxslt
libxslt-devel
Then you will be spared error messages when trying to configure.
regards
SAM
ngc(dontSpamMe)rapanden(SpamOFF)dk
28-Jan-2004 08:48
Sorry, a bug in my code... I made the first version late at night, sorry!
The bug was in the "if ($ChildDomNode->has_child_nodes())" block, I didn't save the data for the for the CildNode of the CildNodes. the bug has been fixed.
<?php
function getElementAttributes($DomNode,$elementName,$attriName)
{
if ($ChildDomNode = $DomNode->first_child())
{
while($ChildDomNode)
{
if ($ChildDomNode->node_type() == XML_ELEMENT_NODE)
{
if($ChildDomNode->node_name() == $elementName)
{
if ($ChildDomNode->has_attributes())
{
$Array = $ChildDomNode->attributes();
foreach ($Array AS $DomAttribute)
{
if($DomAttribute->name() == $attriName)
{
$nodeArray[] = $DomAttribute->value();
}
}// foreach ($Array AS $DomAttribute)
}//if ($ChildDomNode->has_attributes())
}
if ($ChildDomNode->has_child_nodes())
{
$tmpArray = (getElementAttributes($ChildDomNode,$elementName,$attriName));
$nodeArray = array_merge($nodeArray, $tmpArray);
unset($tmpArray);
}// if ($ChildDomNode->has_child_nodes())
}//if ($ChildDomNode->node_type() == XML_ELEMENT_NODE)
$ChildDomNode = $ChildDomNode->next_sibling();
}//while($ChildDomNode)
return $nodeArray;
}//if ($ChildDomNode = $DomNode->first_child())
}
$file = "test3.xml";
$element = "pb";
$att = "id";
$DomDocument = domxml_open_file($file);
$RootDomNode = $DomDocument->document_element();
$array = getElementAttributes($RootDomNode,$element,$att);
echo "<pre>";
print_r($array);
echo "</pre>";
?>
bart at mediawave dot nl
12-Nov-2003 03:46
This recursive function will iterate over a DOM object and display it as a nicely formatted XML structure. I used intuitive variable names to help learn more about the DOM functions and their return values.
<<?php
function PrintDomTree($DomNode)
{
if ($ChildDomNode = $DomNode->first_child()) {
static $depth = 0;
$whitespace = "\n<br>".str_repeat(" ", ($depth * 2));
while ($ChildDomNode) {
if ($ChildDomNode->node_type() == XML_TEXT_NODE) {
echo trim($ChildDomNode->node_value());
} elseif ($ChildDomNode->node_type() == XML_ELEMENT_NODE) {
$HasTag = 1;
echo $whitespace;
echo "<", $ChildDomNode->node_name();
if ($ChildDomNode->has_attributes()) {
$Array = $ChildDomNode->attributes();
foreach ($Array AS $DomAttribute) {
echo " ", $DomAttribute->name(), "=\"", $DomAttribute->value(), "\"";
}
}
echo ">";
if ($ChildDomNode->has_child_nodes()) {
$depth++;
if (PrintDomTree($ChildDomNode)) {
echo $whitespace;
}
$depth--;
}
echo "</", $ChildDomNode->node_name(), ">";
}
$ChildDomNode = $ChildDomNode->next_sibling();
}
return $HasTag;
}
}
?>
sorn at dsl dot upc dot es
18-Mar-2003 07:38
When parsing "iso-8859-1" encoded XML files, use "utf8_decode" to recover node contents (libxml uses "UTF-8" internal encoding, so conversion needed).
--- BEGIN: mydata.xml ---
<?xml version="1.0" encoding="iso-8859-1"?>
...
--- END: mydata.xml---
--- BEGIN: myparser.php ---
<?php
...
$domxml = domxml_open_file("mydata.xml"));
...
$content = utf8_decode(trim($node->content));
echo $content;
...
?>
--- END: myparser.php
-eof-
|  |