From 6ac34646acf2f7088614c6c778b17e839e1bf161 Mon Sep 17 00:00:00 2001 From: Rob Richards Date: Sat, 29 Nov 2003 20:40:18 +0000 Subject: [PATCH] implement namednodemap and nodelist fix xsl/dom integration under windows update tests and examples --- ext/dom/config.m4 | 2 +- ext/dom/document.c | 25 ++++--- ext/dom/documenttype.c | 115 +++------------------------- ext/dom/element.c | 22 ++++-- ext/dom/examples/dom1.inc | 2 +- ext/dom/examples/dom1.php | 6 +- ext/dom/namednodemap.c | 149 +++++++++++++++++++++++++++++++++++-- ext/dom/node.c | 52 +++---------- ext/dom/nodelist.c | 85 +++++++++++++++++++-- ext/dom/php_dom.c | 128 ++++++++++++++++++++++++++----- ext/dom/php_dom.h | 28 ++++++- ext/dom/tests/dom001.phpt | 6 +- ext/dom/tests/dom_test.inc | 2 +- ext/dom/xml_common.h | 4 +- 14 files changed, 418 insertions(+), 208 deletions(-) diff --git a/ext/dom/config.m4 b/ext/dom/config.m4 index 41699b0807..82c97e6bd3 100644 --- a/ext/dom/config.m4 +++ b/ext/dom/config.m4 @@ -22,7 +22,7 @@ if test "$PHP_DOM" != "no" && test "$PHP_LIBXML" != "no"; then documenttype.c domimplementationlist.c entity.c \ nodelist.c text.c comment.c domconfiguration.c \ domimplementationsource.c entityreference.c \ - notation.c xpath.c \ + notation.c xpath.c dom_iterators.c \ typeinfo.c domerror.c domlocator.c namednodemap.c userdatahandler.c], $ext_shared) PHP_SUBST(DOM_SHARED_LIBADD) diff --git a/ext/dom/document.c b/ext/dom/document.c index 8246d891f7..034b83f399 100644 --- a/ext/dom/document.c +++ b/ext/dom/document.c @@ -884,10 +884,10 @@ PHP_FUNCTION(dom_document_get_elements_by_tag_name) { zval *id; xmlDocPtr docp; - xmlNodePtr elemp; int name_len; - dom_object *intern; + dom_object *intern, *namednode; char *name; + xmlChar *local; DOM_GET_THIS_OBJ(docp, id, xmlDocPtr, intern); @@ -895,10 +895,10 @@ PHP_FUNCTION(dom_document_get_elements_by_tag_name) return; } - array_init(return_value); - elemp = xmlDocGetRootElement(docp); - - dom_get_elements_by_tag_name_ns_raw(elemp, NULL, name, &return_value, intern TSRMLS_CC); + php_dom_create_interator(return_value, DOM_NODELIST TSRMLS_CC); + namednode = (dom_object *)zend_objects_get_address(return_value TSRMLS_CC); + local = xmlCharStrndup(name, name_len); + dom_namednode_iter(intern, 0, namednode, NULL, local, NULL); } /* }}} end dom_document_get_elements_by_tag_name */ @@ -1075,10 +1075,10 @@ PHP_FUNCTION(dom_document_get_elements_by_tag_name_ns) { zval *id; xmlDocPtr docp; - xmlNodePtr elemp; int uri_len, name_len; - dom_object *intern; + dom_object *intern, *namednode; char *uri, *name; + xmlChar *local, *nsuri; DOM_GET_THIS_OBJ(docp, id, xmlDocPtr, intern); @@ -1086,10 +1086,11 @@ PHP_FUNCTION(dom_document_get_elements_by_tag_name_ns) return; } - array_init(return_value); - elemp = xmlDocGetRootElement(docp); - - dom_get_elements_by_tag_name_ns_raw(elemp, uri, name, &return_value, intern TSRMLS_CC); + php_dom_create_interator(return_value, DOM_NODELIST TSRMLS_CC); + namednode = (dom_object *)zend_objects_get_address(return_value TSRMLS_CC); + local = xmlCharStrndup(name, name_len); + nsuri = xmlCharStrndup(uri, uri_len); + dom_namednode_iter(intern, 0, namednode, NULL, local, nsuri); } /* }}} end dom_document_get_elements_by_tag_name_ns */ diff --git a/ext/dom/documenttype.c b/ext/dom/documenttype.c index cd6af0d076..036e825a6d 100644 --- a/ext/dom/documenttype.c +++ b/ext/dom/documenttype.c @@ -27,57 +27,6 @@ #if HAVE_LIBXML && HAVE_DOM #include "php_dom.h" -typedef struct _nodeIterator nodeIterator; -struct _nodeIterator { - int cur; - int index; - xmlNode *node; -}; - -typedef struct _notationIterator notationIterator; -struct _notationIterator { - int cur; - int index; - xmlNotation *notation; -}; - -static void itemHashScanner (void *payload, void *data, xmlChar *name) { - nodeIterator *priv = (nodeIterator *)data; - - if(priv->cur < priv->index) { - priv->cur++; - } else { - if(priv->node == NULL) { - priv->node = (xmlNode *)payload; - } - } -} - -/* {{{ static xmlEntityPtr create_notation(const xmlChar *name, - const xmlChar *ExternalID, const xmlChar *SystemID) */ -static xmlNodePtr create_notation(const xmlChar *name, - const xmlChar *ExternalID, const xmlChar *SystemID) { - xmlEntityPtr ret; - - ret = (xmlEntityPtr) xmlMalloc(sizeof(xmlEntity)); - memset(ret, 0, sizeof(xmlEntity)); - ret->type = XML_NOTATION_NODE; - ret->name = xmlStrdup(name); - ret->ExternalID = xmlStrdup(ExternalID); - ret->SystemID = xmlStrdup(SystemID); - ret->length = 0; - ret->content = NULL; - ret->URI = NULL; - ret->orig = NULL; - ret->children = NULL; - ret->parent = NULL; - ret->doc = NULL; - ret->_private = NULL; - ret->last = NULL; - ret->prev = NULL; - return((xmlNodePtr) ret); -} - /* * class domdocumenttype extends domnode * @@ -120,36 +69,18 @@ int dom_documenttype_entities_read(dom_object *obj, zval **retval TSRMLS_DC) { xmlDtdPtr doctypep; xmlHashTable *entityht; - nodeIterator *iter; - xmlNode *nodep = NULL; - int ret, htsize, index = 0; + dom_object *intern; doctypep = (xmlDtdPtr) dom_object_get_node(obj); - ALLOC_ZVAL(*retval); - array_init(*retval); + MAKE_STD_ZVAL(*retval); + php_dom_create_interator(*retval, DOM_NAMEDNODEMAP TSRMLS_CC); entityht = (xmlHashTable *) doctypep->entities; - if (entityht) { - if ((htsize = xmlHashSize(entityht)) > 0) { - iter = emalloc(sizeof(nodeIterator)); - while (index < htsize) { - iter->cur = 0; - iter->index = index; - iter->node = NULL; - xmlHashScan(entityht, itemHashScanner, iter); - index++; - nodep = iter->node; - if (nodep != NULL) { - zval *child; - MAKE_STD_ZVAL(child); - child = php_dom_create_object(nodep, &ret, NULL, child, obj TSRMLS_CC); - add_assoc_zval(*retval, (char *) nodep->name, child); - } - } - efree(iter); - } - } + + intern = (dom_object *)zend_objects_get_address(*retval TSRMLS_CC); + dom_namednode_iter(obj, XML_ENTITY_NODE, intern, entityht, NULL, NULL); + return SUCCESS; } @@ -166,38 +97,14 @@ int dom_documenttype_notations_read(dom_object *obj, zval **retval TSRMLS_DC) { xmlDtdPtr doctypep; xmlHashTable *notationht; - notationIterator *iter; - xmlNotationPtr notep = NULL; - xmlNode *nodep = NULL; - int ret, htsize, index = 0; + dom_object *intern; doctypep = (xmlDtdPtr) dom_object_get_node(obj); + notationht = (xmlHashTable *) doctypep->notations; - MAKE_STD_ZVAL(*retval); - array_init(*retval); + intern = (dom_object *)zend_objects_get_address(*retval TSRMLS_CC); + dom_namednode_iter(obj, XML_NOTATION_NODE, intern, notationht, NULL, NULL); - notationht = (xmlHashTable *) doctypep->notations; - if (notationht) { - if ((htsize = xmlHashSize(notationht)) > 0) { - iter = emalloc(sizeof(nodeIterator)); - while (index < htsize) { - iter->cur = 0; - iter->index = index; - iter->notation = NULL; - xmlHashScan(notationht, itemHashScanner, iter); - index++; - notep = iter->notation; - if (notep != NULL) { - zval *child; - nodep = create_notation(notep->name, notep->PublicID, notep->SystemID); - MAKE_STD_ZVAL(child); - child = php_dom_create_object(nodep, &ret, NULL, child, obj TSRMLS_CC); - add_assoc_zval(*retval, (char *) nodep->name, child); - } - } - efree(iter); - } - } return SUCCESS; } diff --git a/ext/dom/element.c b/ext/dom/element.c index 84b01618bd..bd146637e6 100644 --- a/ext/dom/element.c +++ b/ext/dom/element.c @@ -394,8 +394,9 @@ PHP_FUNCTION(dom_element_get_elements_by_tag_name) zval *id; xmlNodePtr elemp; int name_len; - dom_object *intern; + dom_object *intern, *namednode; char *name; + xmlChar *local; DOM_GET_THIS_OBJ(elemp, id, xmlNodePtr, intern); @@ -403,10 +404,10 @@ PHP_FUNCTION(dom_element_get_elements_by_tag_name) return; } - array_init(return_value); - elemp = elemp->children; - - dom_get_elements_by_tag_name_ns_raw(elemp, NULL, name, &return_value, intern TSRMLS_CC); + php_dom_create_interator(return_value, DOM_NODELIST TSRMLS_CC); + namednode = (dom_object *)zend_objects_get_address(return_value TSRMLS_CC); + local = xmlCharStrndup(name, name_len); + dom_namednode_iter(intern, 0, namednode, NULL, local, NULL); } /* }}} end dom_element_get_elements_by_tag_name */ @@ -708,8 +709,10 @@ PHP_FUNCTION(dom_element_get_elements_by_tag_name_ns) zval *id; xmlNodePtr elemp; int uri_len, name_len; - dom_object *intern; + dom_object *intern, *namednode; char *uri, *name; + xmlChar *local, *nsuri; +// xmlHashTable *ht; DOM_GET_THIS_OBJ(elemp, id, xmlNodePtr, intern); @@ -717,9 +720,12 @@ PHP_FUNCTION(dom_element_get_elements_by_tag_name_ns) return; } - array_init(return_value); + php_dom_create_interator(return_value, DOM_NODELIST TSRMLS_CC); + namednode = (dom_object *)zend_objects_get_address(return_value TSRMLS_CC); + local = xmlCharStrndup(name, name_len); + nsuri = xmlCharStrndup(uri, uri_len); + dom_namednode_iter(intern, 0, namednode, NULL, local, nsuri); - dom_get_elements_by_tag_name_ns_raw(elemp->children, uri, name, &return_value, intern TSRMLS_CC); } /* }}} end dom_element_get_elements_by_tag_name_ns */ diff --git a/ext/dom/examples/dom1.inc b/ext/dom/examples/dom1.inc index 96acddc669..792d6f2dbc 100644 --- a/ext/dom/examples/dom1.inc +++ b/ext/dom/examples/dom1.inc @@ -24,7 +24,7 @@ function print_node($node) { print "Node Name: " . $node->nodeName; print "\nNode Type: " . $node->nodeType; - $child_count = count($node->childNodes); + $child_count = $node->childNodes->length; print "\nNum Children: " . $child_count; if($child_count <= 1){ print "\nNode Content: " . $node->nodeValue; diff --git a/ext/dom/examples/dom1.php b/ext/dom/examples/dom1.php index 8654b19c2f..99125a2a37 100644 --- a/ext/dom/examples/dom1.php +++ b/ext/dom/examples/dom1.php @@ -60,7 +60,7 @@ $attrs = $rootnode->attributes; print_node_list($attrs); echo "--------- children of an attribute\n"; -$children = current($attrs)->childNodes; +$children = $attrs->item(0)->childNodes; print_node_list($children); echo "--------- Add child to root\n"; @@ -80,8 +80,8 @@ $children = $rootnode->getElementsByTagName("Silly"); print_node_list($children); echo "--------- Unlink Node\n"; -print_node($children[0]); -$rootnode->removeChild($children[0]); +print_node($children.item(0)); +$rootnode->removeChild($children.item(0)); print_node_list($rootnode->childNodes); print $dom->savexml(); diff --git a/ext/dom/namednodemap.c b/ext/dom/namednodemap.c index ada109ad80..1e4eefbe23 100644 --- a/ext/dom/namednodemap.c +++ b/ext/dom/namednodemap.c @@ -55,8 +55,30 @@ Since: */ int dom_namednodemap_length_read(dom_object *obj, zval **retval TSRMLS_DC) { - ALLOC_ZVAL(*retval); - ZVAL_STRING(*retval, "TEST", 1); + dom_nnodemap_object *objmap; + xmlAttrPtr curnode; + xmlNodePtr nodep; + int count = 0; + + objmap = (dom_nnodemap_object *)obj->ptr; + if (objmap->ht) { + count = xmlHashSize(objmap->ht); + } else { + nodep = dom_object_get_node(objmap->baseobj); + if (nodep) { + curnode = nodep->properties; + if (curnode) { + count++; + while (curnode->next != NULL) { + count++; + curnode = curnode->next; + } + } + } + } + + MAKE_STD_ZVAL(*retval); + ZVAL_LONG(*retval, count); return SUCCESS; } @@ -71,7 +93,44 @@ Since: */ PHP_FUNCTION(dom_namednodemap_get_named_item) { - DOM_NOT_IMPLEMENTED(); + zval *id, *rv = NULL; + int ret, namedlen=0; + dom_object *intern; + xmlNodePtr itemnode = NULL; + char *named; + + dom_nnodemap_object *objmap; + xmlNodePtr nodep; + xmlNotation *notep = NULL; + + id = getThis(); + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &named, &namedlen) == FAILURE) { + return; + } + + intern = (dom_object *)zend_object_store_get_object(id TSRMLS_CC); + + objmap = (dom_nnodemap_object *)intern->ptr; + if (objmap->ht) { + if (objmap->nodetype == XML_ENTITY_NODE) { + itemnode = (xmlNodePtr)xmlHashLookup(objmap->ht, named); + } else { + notep = (xmlNotation *)xmlHashLookup(objmap->ht, named); + itemnode = create_notation(notep->name, notep->PublicID, notep->SystemID); + } + } else { + nodep = dom_object_get_node(objmap->baseobj); + if (nodep) { + itemnode = (xmlNodePtr)xmlHasProp(nodep, named); + } + } + + if (itemnode) { + DOM_RET_OBJ(rv, itemnode, &ret, objmap->baseobj); + } else { + RETVAL_NULL(); + } } /* }}} end dom_namednodemap_get_named_item */ @@ -104,7 +163,50 @@ Since: */ PHP_FUNCTION(dom_namednodemap_item) { - DOM_NOT_IMPLEMENTED(); + zval *id, *rv = NULL; + int index, ret; + dom_object *intern; + xmlNodePtr itemnode = NULL; + + dom_nnodemap_object *objmap; + xmlNodePtr nodep, curnode; + int count; + + id = getThis(); + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == FAILURE) { + return; + } + + if (index >= 0) { + intern = (dom_object *)zend_object_store_get_object(id TSRMLS_CC); + + objmap = (dom_nnodemap_object *)intern->ptr; + if (objmap->ht) { + if (objmap->nodetype == XML_ENTITY_NODE) { + itemnode = php_dom_libxml_hash_iter(objmap->ht, index); + } else { + itemnode = php_dom_libxml_notation_iter(objmap->ht, index); + } + } else { + nodep = dom_object_get_node(objmap->baseobj); + if (nodep) { + curnode = (xmlNodePtr)nodep->properties; + count = 0; + while (count < index && curnode != NULL) { + count++; + curnode = (xmlNodePtr)curnode->next; + } + itemnode = curnode; + } + } + } + + if (itemnode) { + DOM_RET_OBJ(rv, itemnode, &ret, objmap->baseobj); + } else { + RETVAL_NULL(); + } } /* }}} end dom_namednodemap_item */ @@ -115,7 +217,44 @@ Since: DOM Level 2 */ PHP_FUNCTION(dom_namednodemap_get_named_item_ns) { - DOM_NOT_IMPLEMENTED(); + zval *id, *rv = NULL; + int ret, namedlen=0, urilen=0; + dom_object *intern; + xmlNodePtr itemnode = NULL; + char *uri, *named; + + dom_nnodemap_object *objmap; + xmlNodePtr nodep; + xmlNotation *notep = NULL; + + id = getThis(); + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &uri, &urilen, &named, &namedlen) == FAILURE) { + return; + } + + intern = (dom_object *)zend_object_store_get_object(id TSRMLS_CC); + + objmap = (dom_nnodemap_object *)intern->ptr; + if (objmap->ht) { + if (objmap->nodetype == XML_ENTITY_NODE) { + itemnode = (xmlNodePtr)xmlHashLookup(objmap->ht, named); + } else { + notep = (xmlNotation *)xmlHashLookup(objmap->ht, named); + itemnode = create_notation(notep->name, notep->PublicID, notep->SystemID); + } + } else { + nodep = dom_object_get_node(objmap->baseobj); + if (nodep) { + itemnode = (xmlNodePtr)xmlHasNsProp(nodep, named, uri); + } + } + + if (itemnode) { + DOM_RET_OBJ(rv, itemnode, &ret, objmap->baseobj); + } else { + RETVAL_NULL(); + } } /* }}} end dom_namednodemap_get_named_item_ns */ diff --git a/ext/dom/node.c b/ext/dom/node.c index fc146051d5..e638ec003f 100644 --- a/ext/dom/node.c +++ b/ext/dom/node.c @@ -27,7 +27,6 @@ #if HAVE_LIBXML && HAVE_DOM #include "php_dom.h" - /* * class domnode * @@ -280,31 +279,13 @@ Since: */ int dom_node_child_nodes_read(dom_object *obj, zval **retval TSRMLS_DC) { - xmlNodePtr nodep, last; - int ret; - - nodep = dom_object_get_node(obj); + dom_object *intern; - if (dom_node_children_valid(nodep) == SUCCESS) { - if ((nodep->type == XML_DOCUMENT_NODE) || (nodep->type == XML_HTML_DOCUMENT_NODE)) { - last = ((xmlDoc *) nodep)->children; - } else { - last = nodep->children; - } - } else { - last = NULL; - } + ALLOC_ZVAL(*retval); + php_dom_create_interator(*retval, DOM_NODELIST TSRMLS_CC); - MAKE_STD_ZVAL(*retval); - array_init(*retval); - - while (last) { - zval *child; - MAKE_STD_ZVAL(child); - child = php_dom_create_object(last, &ret, NULL, child, obj TSRMLS_CC); - add_next_index_zval(*retval, child); - last = last->next; - } + intern = (dom_object *)zend_objects_get_address(*retval TSRMLS_CC); + dom_namednode_iter(obj, XML_ELEMENT_NODE, intern, NULL, NULL, NULL); return SUCCESS; } @@ -446,28 +427,13 @@ Since: */ int dom_node_attributes_read(dom_object *obj, zval **retval TSRMLS_DC) { - xmlNodePtr nodep; - xmlAttr *attr; - int ret; - - nodep = dom_object_get_node(obj); + dom_object *intern; ALLOC_ZVAL(*retval); + php_dom_create_interator(*retval, DOM_NAMEDNODEMAP TSRMLS_CC); - if (nodep->type == XML_ELEMENT_NODE) { - attr = nodep->properties; - array_init(*retval); - - while (attr) { - zval *curattr; - MAKE_STD_ZVAL(curattr); - curattr = php_dom_create_object((xmlNodePtr) attr, &ret, NULL, curattr, obj TSRMLS_CC); - add_assoc_zval(*retval, (char *) attr->name, curattr); - attr = attr->next; - } - } else { - ZVAL_NULL(*retval); - } + intern = (dom_object *)zend_objects_get_address(*retval TSRMLS_CC); + dom_namednode_iter(obj, XML_ATTRIBUTE_NODE, intern, NULL, NULL, NULL); return SUCCESS; } diff --git a/ext/dom/nodelist.c b/ext/dom/nodelist.c index bcaee1f93e..5ecd2d763e 100644 --- a/ext/dom/nodelist.c +++ b/ext/dom/nodelist.c @@ -49,23 +49,98 @@ Since: */ int dom_nodelist_length_read(dom_object *obj, zval **retval TSRMLS_DC) { - ALLOC_ZVAL(*retval); - ZVAL_STRING(*retval, "TEST", 1); + dom_nnodemap_object *objmap; + xmlNodePtr nodep, curnode; + int count = 0; + + objmap = (dom_nnodemap_object *)obj->ptr; + if (objmap->ht) { + count = xmlHashSize(objmap->ht); + } else { + nodep = dom_object_get_node(objmap->baseobj); + if (nodep) { + if (objmap->nodetype == XML_ATTRIBUTE_NODE || objmap->nodetype == XML_ELEMENT_NODE) { + curnode = nodep->children; + if (curnode) { + count++; + while (curnode->next != NULL) { + count++; + curnode = curnode->next; + } + } + } else { + if (nodep->type == XML_DOCUMENT_NODE || nodep->type == XML_HTML_DOCUMENT_NODE) { + nodep = xmlDocGetRootElement((xmlDoc *) nodep); + } + curnode = dom_get_elements_by_tag_name_ns_raw(nodep, objmap->ns, objmap->local, &count, -1); + } + } + } + + MAKE_STD_ZVAL(*retval); + ZVAL_LONG(*retval, count); return SUCCESS; } /* }}} */ - - /* {{{ proto domnode dom_nodelist_item(unsigned long index); URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#ID-844377136 Since: */ PHP_FUNCTION(dom_nodelist_item) { - DOM_NOT_IMPLEMENTED(); + zval *id, *rv = NULL; + int index, ret; + dom_object *intern; + xmlNodePtr itemnode = NULL; + + dom_nnodemap_object *objmap; + xmlNodePtr nodep, curnode; + int count = 0; + + id = getThis(); + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == FAILURE) { + return; + } + + if (index >= 0) { + intern = (dom_object *)zend_object_store_get_object(id TSRMLS_CC); + + objmap = (dom_nnodemap_object *)intern->ptr; + if (objmap->ht) { + if (objmap->nodetype == XML_ENTITY_NODE) { + itemnode = php_dom_libxml_hash_iter(objmap->ht, index); + } else { + itemnode = php_dom_libxml_notation_iter(objmap->ht, index); + } + } else { + nodep = dom_object_get_node(objmap->baseobj); + if (nodep) { + if (objmap->nodetype == XML_ATTRIBUTE_NODE || objmap->nodetype == XML_ELEMENT_NODE) { + curnode = nodep->children; + while (count < index && curnode != NULL) { + count++; + curnode = curnode->next; + } + itemnode = curnode; + } else { + if (nodep->type == XML_DOCUMENT_NODE || nodep->type == XML_HTML_DOCUMENT_NODE) { + nodep = xmlDocGetRootElement((xmlDoc *) nodep); + } + itemnode = dom_get_elements_by_tag_name_ns_raw(nodep, objmap->ns, objmap->local, &count, index); + } + } + } + } + + if (itemnode) { + DOM_RET_OBJ(rv, itemnode, &ret, objmap->baseobj); + } else { + RETVAL_NULL(); + } } /* }}} end dom_nodelist_item */ #endif diff --git a/ext/dom/php_dom.c b/ext/dom/php_dom.c index 592ff5736a..9ddf5ebfc0 100644 --- a/ext/dom/php_dom.c +++ b/ext/dom/php_dom.c @@ -432,14 +432,20 @@ PHP_MINIT_FUNCTION(dom) zend_hash_merge(&dom_document_prop_handlers, &dom_node_prop_handlers, NULL, NULL, sizeof(dom_prop_handler), 0); zend_hash_add(&classes, ce.name, ce.name_length + 1, &dom_document_prop_handlers, sizeof(dom_document_prop_handlers), NULL); - REGISTER_DOM_CLASS(ce, "domnodelist", NULL, php_dom_nodelist_class_functions, dom_nodelist_class_entry); - + INIT_CLASS_ENTRY(ce, "domnodelist", php_dom_nodelist_class_functions); + ce.create_object = dom_nnodemap_objects_new; + dom_nodelist_class_entry = zend_register_internal_class_ex(&ce, NULL, NULL TSRMLS_CC); + dom_nodelist_class_entry->get_iterator = php_dom_get_iterator; + zend_hash_init(&dom_nodelist_prop_handlers, 0, NULL, NULL, 1); dom_register_prop_handler(&dom_nodelist_prop_handlers, "length", dom_nodelist_length_read, NULL TSRMLS_CC); zend_hash_add(&classes, ce.name, ce.name_length + 1, &dom_nodelist_prop_handlers, sizeof(dom_nodelist_prop_handlers), NULL); - REGISTER_DOM_CLASS(ce, "domnamednodemap", NULL, php_dom_namednodemap_class_functions, dom_namednodemap_class_entry); - + INIT_CLASS_ENTRY(ce, "domnamednodemap", php_dom_namednodemap_class_functions); + ce.create_object = dom_nnodemap_objects_new; + dom_namednodemap_class_entry = zend_register_internal_class_ex(&ce, NULL, NULL TSRMLS_CC); + dom_namednodemap_class_entry->get_iterator = php_dom_get_iterator; + zend_hash_init(&dom_namednodemap_prop_handlers, 0, NULL, NULL, 1); dom_register_prop_handler(&dom_namednodemap_prop_handlers, "length", dom_namednodemap_length_read, NULL TSRMLS_CC); zend_hash_add(&classes, ce.name, ce.name_length + 1, &dom_namednodemap_prop_handlers, sizeof(dom_namednodemap_prop_handlers), NULL); @@ -686,7 +692,7 @@ PHP_MSHUTDOWN_FUNCTION(dom) uncomment the following line, this will tell you the amount of not freed memory and the total used memory into apaches error_log */ /* xmlMemoryDump();*/ - +xmlMemoryDump(); return SUCCESS; } @@ -773,7 +779,29 @@ void dom_objects_dtor(void *object, zend_object_handle handle TSRMLS_DC) } /* }}} */ -/* {{{ dom_objects_set_class */ +void dom_namednode_iter(dom_object *basenode, int ntype, dom_object *intern, xmlHashTablePtr ht, xmlChar *local, xmlChar *ns) +{ + dom_nnodemap_object *mapptr; + zval *baseobj = NULL; + + mapptr = (dom_nnodemap_object *)intern->ptr; + if (basenode) { + MAKE_STD_ZVAL(baseobj); + baseobj->type = IS_OBJECT; + baseobj->is_ref = 1; + baseobj->value.obj.handle = basenode->handle; + baseobj->value.obj.handlers = &dom_object_handlers; + zval_copy_ctor(baseobj); + } + mapptr->baseobjptr = baseobj; + mapptr->baseobj = basenode; + mapptr->nodetype = ntype; + mapptr->ht = ht; + mapptr->local = local; + mapptr->ns = ns; + +} + static dom_object* dom_objects_set_class(zend_class_entry *class_type TSRMLS_DC) { zend_class_entry *base_class; @@ -801,7 +829,6 @@ static dom_object* dom_objects_set_class(zend_class_entry *class_type TSRMLS_DC) return intern; } -/* }}} */ /* {{{ dom_objects_new */ zend_object_value dom_objects_new(zend_class_entry *class_type TSRMLS_DC) @@ -837,6 +864,70 @@ zend_object_value dom_xpath_objects_new(zend_class_entry *class_type TSRMLS_DC) /* }}} */ #endif +void dom_nnodemap_objects_dtor(void *object, zend_object_handle handle TSRMLS_DC) +{ + dom_nnodemap_object *objmap; + zval *baseobj; + dom_object *intern = (dom_object *)object; + + php_libxml_decrement_doc_ref((php_libxml_node_object *)intern TSRMLS_CC); + objmap = (dom_nnodemap_object *)intern->ptr; + if (objmap) { + if (objmap->local) { + xmlFree(objmap->local); + } + if (objmap->ns) { + xmlFree(objmap->ns); + } + if (objmap->baseobjptr) { + baseobj = objmap->baseobjptr; + zval_ptr_dtor((zval **)&baseobj); + } + efree(objmap); + } + + zend_hash_destroy(intern->std.properties); + FREE_HASHTABLE(intern->std.properties); + + efree(object); +} + +zend_object_value dom_nnodemap_objects_new(zend_class_entry *class_type TSRMLS_DC) +{ + zend_object_value retval; + dom_object *intern; + dom_nnodemap_object *objmap; + + intern = dom_objects_set_class(class_type TSRMLS_CC); + intern->ptr = emalloc(sizeof(dom_nnodemap_object)); + objmap = (dom_nnodemap_object *)intern->ptr; + objmap->baseobj = NULL; + objmap->baseobjptr = NULL; + objmap->nodetype = 0; + objmap->ht = NULL; + objmap->local = NULL; + objmap->ns = NULL; + + retval.handle = zend_objects_store_put(intern, dom_nnodemap_objects_dtor, dom_objects_clone TSRMLS_CC); + intern->handle = retval.handle; + retval.handlers = &dom_object_handlers; + + return retval; +} + +void php_dom_create_interator(zval *return_value, int ce_type TSRMLS_DC) +{ + zend_class_entry *ce; + + if (ce_type == DOM_NAMEDNODEMAP) { + ce = dom_namednodemap_class_entry; + } else { + ce = dom_nodelist_class_entry; + } + + object_init_ex(return_value, ce); +} + /* {{{ php_dom_create_object */ zval *php_dom_create_object(xmlNodePtr obj, int *found, zval *wrapper_in, zval *return_value, dom_object *domobj TSRMLS_DC) { @@ -995,24 +1086,27 @@ int dom_has_feature(char *feature, char *version) } /* }}} end dom_has_feature */ -/* {{{ void dom_element_get_elements_by_tag_name_ns_raw(xmlNodePtr nodep, char *ns, char *local, zval **retval TSRMLS_DC) */ -void dom_get_elements_by_tag_name_ns_raw(xmlNodePtr nodep, char *ns, char *local, zval **retval, dom_object *intern TSRMLS_DC) +xmlNode *dom_get_elements_by_tag_name_ns_raw(xmlNodePtr nodep, char *ns, char *local, int *cur, int index) { - int ret; + xmlNodePtr ret = NULL; - while (nodep != NULL) { + while (nodep != NULL && (*cur <= index || index == -1)) { if (nodep->type == XML_ELEMENT_NODE && xmlStrEqual(nodep->name, local)) { if (ns == NULL || (nodep->ns != NULL && xmlStrEqual(nodep->ns->href, ns))) { - zval *child; - MAKE_STD_ZVAL(child); - - child = php_dom_create_object(nodep, &ret, NULL, child, intern TSRMLS_CC); - add_next_index_zval(*retval, child); + if (*cur == index) { + ret = nodep; + break; + } + (*cur)++; } } - dom_get_elements_by_tag_name_ns_raw(nodep->children, ns, local, retval, intern TSRMLS_CC); + ret = dom_get_elements_by_tag_name_ns_raw(nodep->children, ns, local, cur, index); + if (ret != NULL) { + break; + } nodep = nodep->next; } + return ret; } /* }}} end dom_element_get_elements_by_tag_name_ns_raw */ diff --git a/ext/dom/php_dom.h b/ext/dom/php_dom.h index 6c400d1754..ea99413d20 100644 --- a/ext/dom/php_dom.h +++ b/ext/dom/php_dom.h @@ -61,13 +61,28 @@ extern zend_module_entry dom_module_entry; therefore it's easier for the script-programmers to check, what's working how Can be checked with phpversion("dom"); */ -#define DOM_API_VERSION "20030901" +#define DOM_API_VERSION "20031129" + +typedef struct _dom_nnodemap_object { + dom_object *baseobj; + int nodetype; + xmlHashTable *ht; + xmlChar *local; + xmlChar *ns; + zval *baseobjptr; +} dom_nnodemap_object; + +typedef struct { + zend_object_iterator intern; + zval *curobj; +} php_dom_iterator; #include "dom_fe.h" dom_object *dom_object_get_data(xmlNodePtr obj); dom_doc_propsptr dom_get_doc_props(php_libxml_ref_obj *document); zend_object_value dom_objects_new(zend_class_entry *class_type TSRMLS_DC); +zend_object_value dom_nnodemap_objects_new(zend_class_entry *class_type TSRMLS_DC); #if defined(LIBXML_XPATH_ENABLED) zend_object_value dom_xpath_objects_new(zend_class_entry *class_type TSRMLS_DC); #endif @@ -79,12 +94,18 @@ xmlNsPtr dom_get_ns(xmlNodePtr node, char *uri, int *errorcode, char *prefix); void dom_set_old_ns(xmlDoc *doc, xmlNs *ns); xmlNsPtr dom_get_nsdecl(xmlNode *node, xmlChar *localName); void dom_normalize (xmlNodePtr nodep TSRMLS_DC); -void dom_get_elements_by_tag_name_ns_raw(xmlNodePtr nodep, char *ns, char *local, zval **retval, dom_object *intern TSRMLS_DC); +xmlNode *dom_get_elements_by_tag_name_ns_raw(xmlNodePtr nodep, char *ns, char *local, int *cur, int index); void php_dom_create_implementation(zval **retval TSRMLS_DC); int dom_hierarchy(xmlNodePtr parent, xmlNodePtr child); int dom_has_feature(char *feature, char *version); int dom_node_is_read_only(xmlNodePtr node); int dom_node_children_valid(xmlNodePtr node); +void php_dom_create_interator(zval *return_value, int ce_type TSRMLS_DC); +void dom_namednode_iter(dom_object *basenode, int ntype, dom_object *intern, xmlHashTablePtr ht, xmlChar *local, xmlChar *ns); +xmlNodePtr create_notation(const xmlChar *name, const xmlChar *ExternalID, const xmlChar *SystemID); +xmlNode *php_dom_libxml_hash_iter(xmlHashTable *ht, int index); +xmlNode *php_dom_libxml_notation_iter(xmlHashTable *ht, int index); +zend_object_iterator *php_dom_get_iterator(zend_class_entry *ce, zval *object TSRMLS_DC); #define REGISTER_DOM_CLASS(ce, name, parent_ce, funcs, entry) \ INIT_CLASS_ENTRY(ce, name, funcs); \ @@ -109,6 +130,9 @@ entry = zend_register_internal_class_ex(&ce, parent_ce, NULL TSRMLS_CC); php_error_docref(NULL TSRMLS_CC, E_WARNING, "Not yet implemented"); \ return; +#define DOM_NODELIST 0 +#define DOM_NAMEDNODEMAP 1 + PHP_MINIT_FUNCTION(dom); PHP_MSHUTDOWN_FUNCTION(dom); PHP_MINFO_FUNCTION(dom); diff --git a/ext/dom/tests/dom001.phpt b/ext/dom/tests/dom001.phpt index cf3298db6d..a0c78fbb0a 100644 --- a/ext/dom/tests/dom001.phpt +++ b/ext/dom/tests/dom001.phpt @@ -65,7 +65,7 @@ $attrs = $rootnode->attributes; print_node_list($attrs); echo "--------- children of an attribute\n"; -$children = current($attrs)->childNodes; +$children = $attrs->item(0)->childNodes; print_node_list($children); echo "--------- Add child to root\n"; @@ -85,8 +85,8 @@ $children = $rootnode->getElementsByTagName("Silly"); print_node_list($children); echo "--------- Unlink Node\n"; -print_node($children[0]); -$rootnode->removeChild($children[0]); +print_node($children->item(0)); +$rootnode->removeChild($children->item(0)); print_node_list($rootnode->childNodes); print $dom->savexml(); diff --git a/ext/dom/tests/dom_test.inc b/ext/dom/tests/dom_test.inc index 96acddc669..792d6f2dbc 100644 --- a/ext/dom/tests/dom_test.inc +++ b/ext/dom/tests/dom_test.inc @@ -24,7 +24,7 @@ function print_node($node) { print "Node Name: " . $node->nodeName; print "\nNode Type: " . $node->nodeType; - $child_count = count($node->childNodes); + $child_count = $node->childNodes->length; print "\nNum Children: " . $child_count; if($child_count <= 1){ print "\nNode Content: " . $node->nodeValue; diff --git a/ext/dom/xml_common.h b/ext/dom/xml_common.h index 8515eecbfb..86f492e2b8 100644 --- a/ext/dom/xml_common.h +++ b/ext/dom/xml_common.h @@ -24,9 +24,6 @@ #include "ext/libxml/php_libxml.h" -zend_class_entry *dom_node_class_entry; - - typedef struct _dom_doc_props { int formatoutput; int validateonparse; @@ -59,6 +56,7 @@ typedef struct _dom_object { #define PHP_DOM_EXPORT(__type) PHPAPI __type +PHP_DOM_EXPORT(zend_class_entry *) dom_node_class_entry; PHP_DOM_EXPORT(dom_object *) php_dom_object_get_data(xmlNodePtr obj); PHP_DOM_EXPORT(zval *) php_dom_create_object(xmlNodePtr obj, int *found, zval *in, zval* return_value, dom_object *domobj TSRMLS_DC); PHP_DOM_EXPORT(xmlNodePtr) dom_object_get_node(dom_object *obj); -- 2.40.0