]> granicus.if.org Git - php/commitdiff
- get_element_by_id() doesn't use xpath anymore but searches in
authorUwe Steinmann <steinm@php.net>
Tue, 23 Apr 2002 06:05:38 +0000 (06:05 +0000)
committerUwe Steinmann <steinm@php.net>
Tue, 23 Apr 2002 06:05:38 +0000 (06:05 +0000)
  xmlDoc->ids as provided by libxml.
- New function DomDocument->ids() returns a list of ids (subject to change)
- replace_node() doesn't make a copy of the new node if it has no parents

ext/domxml/php_domxml.c

index 8299b7d7c44368c2b01d8f0e28d5667844517382..2dc1eda5dc6eb266862cc24c6336ba6d7cd9d886 100644 (file)
@@ -258,7 +258,6 @@ static zend_function_entry domxml_functions[] = {
 static function_entry php_domxmldoc_class_functions[] = {
        PHP_FALIAS(doctype,                             domxml_doc_doctype,                     NULL)
        PHP_FALIAS(implementation,                      domxml_doc_implementation,              NULL)
-       PHP_FALIAS(root,                                        domxml_doc_document_element,    NULL)   /* not DOM */
        PHP_FALIAS(document_element,            domxml_doc_document_element,    NULL)
        PHP_FALIAS(create_element,                      domxml_doc_create_element,              NULL)
        PHP_FALIAS(create_text_node,            domxml_doc_create_text_node,    NULL)
@@ -269,11 +268,14 @@ static function_entry php_domxmldoc_class_functions[] = {
        PHP_FALIAS(create_processing_instruction,       domxml_doc_create_processing_instruction,       NULL)
        PHP_FALIAS(get_elements_by_tagname,     domxml_doc_get_elements_by_tagname,     NULL)
        PHP_FALIAS(get_element_by_id,           domxml_doc_get_element_by_id,   NULL)
+       /* Everything below this comment is none DOM compliant */
        /* children is deprecated because it is inherited from DomNode */
 /*     PHP_FALIAS(children,                            domxml_node_children,                   NULL) */
+       PHP_FALIAS(root,                                        domxml_doc_document_element,    NULL)
        PHP_FALIAS(add_root,                            domxml_add_root,                                NULL)
        PHP_FALIAS(imported_node,                       domxml_doc_imported_node,               NULL)
        PHP_FALIAS(dtd,                                         domxml_intdtd,                                  NULL)
+       PHP_FALIAS(ids,                                         domxml_doc_ids,                                 NULL)
        PHP_FALIAS(dumpmem,                                     domxml_dump_mem,                                NULL)
        PHP_FALIAS(dump_mem,                            domxml_dump_mem,                                NULL)
        PHP_FALIAS(dump_mem_file,                       domxml_dump_mem_file,                   NULL)
@@ -2007,9 +2009,18 @@ PHP_FUNCTION(domxml_node_replace_node)
 
        DOMXML_GET_OBJ(repnode, node, le_domxmlnodep);
 
-       if (NULL == (new_repnode = xmlCopyNode(repnode, 1))) {
-               php_error(E_WARNING, "%s(): unable to clone node", get_active_function_name(TSRMLS_C));
-               RETURN_FALSE;
+       /* check if the new node is already part of the document. In such a case
+        * we better make a copy to prevent changing identical nodes at different
+        * positions in the document at the same time.
+        * A node created with e.g. create_element() doesn't have parents.
+        */
+       if(repnode->parent) {
+               if (NULL == (new_repnode = xmlCopyNode(repnode, 1))) {
+                       php_error(E_WARNING, "%s(): unable to clone node", get_active_function_name(TSRMLS_C));
+                       RETURN_FALSE;
+               }
+       } else {
+               new_repnode = repnode;
        }
 
        repnode = xmlReplaceNode(nodep, new_repnode);
@@ -2635,77 +2646,47 @@ PHP_FUNCTION(domxml_doc_get_elements_by_tagname)
 }
 /* }}} */
 
-/* {{{ proto string domxml_doc_get_element_by_id(string id [,object xpathctx_handle] )
+typedef struct _idsIterator idsIterator;
+struct _idsIterator {
+         xmlChar *elementId;
+           xmlNode *element;
+};
+
+static void idsHashScanner(void *payload, void *data, xmlChar *name) {
+       idsIterator *priv = (idsIterator *)data;
+
+       if (priv->element == NULL && xmlStrEqual (name, priv->elementId))
+               priv->element = ((xmlNode *)((xmlID *)payload)->attr)->parent;
+}
+
+/* {{{ proto string domxml_doc_get_element_by_id(string id)
    Returns element for given id or false if not found */
 PHP_FUNCTION(domxml_doc_get_element_by_id)
 {
-       zval *id, *rv = NULL, *contextnode = NULL, *ctxpin = NULL;
-       xmlXPathContextPtr ctxp ;
+       zval *id, *rv = NULL;
        xmlDocPtr docp;
+       idsIterator iter;
+       xmlHashTable *ids = NULL;
+       int retnode;
 
-       xmlXPathObjectPtr xpathobjp;
-       xmlNode *contextnodep;
        int name_len;
        char *str, *name;
 
-       contextnode = NULL;
-       contextnodep = NULL;
+       id = getThis();
+       DOMXML_GET_OBJ(docp, id, le_domxmldocp);
 
-       DOMXML_PARAM_FOUR(docp, id, le_domxmldocp, "s|oo", &name, &name_len,&ctxpin,&contextnodep);
-       
-       /* if no xpath_context was submitted, create a new one */
-       if (ctxpin == NULL) {
-               ctxp = xmlXPathNewContext(docp);
+       ids = (xmlHashTable *) docp->ids;
+       if(ids) {
+               iter.elementId = (xmlChar *) 
+               iter.element = NULL;
+               xmlHashScan(ids, idsHashScanner, &iter);
+               rv = php_domobject_new(iter.element, &retnode TSRMLS_CC);
+               SEPARATE_ZVAL(&rv);
+               *return_value = *rv;
+               FREE_ZVAL(rv);
        } else {
-               DOMXML_GET_OBJ(ctxp, ctxpin, le_xpathctxp);
-       }
-       
-       if (contextnode) {
-               DOMXML_GET_OBJ(contextnodep, contextnode, le_domxmlnodep);
-       }
-       ctxp->node = contextnodep;
-       str = (char*) emalloc((name_len+14) * sizeof(char)) ;
-       if (str == NULL) {
-               php_error(E_WARNING, "%s(): cannot allocate memory for string", get_active_function_name(TSRMLS_C));
-       }
-       sprintf(str ,"//*[@ID = '%s']",name);
-       xpathobjp = xmlXPathEval(str, ctxp);
-       efree(str);
-       ctxp->node = NULL;
-       if (!xpathobjp) {
                RETURN_FALSE;
        }
-
-       switch (Z_TYPE_P(xpathobjp)) {
-
-               case XPATH_NODESET:
-               {
-                       xmlNodeSetPtr nodesetp;
-
-                       if (NULL == (nodesetp = xpathobjp->nodesetval)) {
-                               zval_dtor(rv);
-                               RETURN_FALSE;
-                       }
-
-                       if (nodesetp->nodeNr > 0) {
-                               xmlNodePtr node = nodesetp->nodeTab[0];
-                               int retnode;
-                               rv = php_domobject_new(node, &retnode TSRMLS_CC);
-                               SEPARATE_ZVAL(&rv);
-                       }
-                       else {
-                               /*return false, if no nodes were found */
-                               RETURN_FALSE;
-                       }
-
-                       break;
-               }
-               default:
-                       break;
-       }
-
-       *return_value = *rv;
-       FREE_ZVAL(rv);
 }
 /* }}} */
 #endif
@@ -3273,6 +3254,40 @@ PHP_FUNCTION(domxml_dump_node)
 }
 /* }}} */
 
+static void idsHashScanner2(void *payload, void *data, xmlChar *name) {
+       zval *return_value = (zval *) data;
+       zval *child;
+       int ret;
+       xmlNode *nodep;
+
+       nodep = ((xmlNode *)((xmlID *)payload)->attr)->parent;
+       child = php_domobject_new(nodep, &ret TSRMLS_CC);
+       add_next_index_zval(return_value, child);
+}
+
+/* {{{ proto string domxml_doc_ids(object doc_handle)
+   Returns array of ids */
+PHP_FUNCTION(domxml_doc_ids)
+{
+       zval *id;
+       xmlDoc *docp;
+       xmlHashTable *ids = NULL;
+
+       DOMXML_GET_THIS_OBJ(docp, id, le_domxmldocp);
+
+       ids = docp->ids;
+
+       if(ids) {
+               if (array_init(return_value) == FAILURE) {
+                       RETURN_FALSE;
+               }
+
+               xmlHashScan(ids, idsHashScanner2, return_value);
+       } else {
+               RETURN_FALSE;
+       }
+}
+/* }}} */
 
 /* {{{ proto object xmldoc(string xmldoc [, bool from_file])
    Creates DOM object of XML document */
@@ -3284,10 +3299,14 @@ PHP_FUNCTION(xmldoc)
        char *buffer;
        int buffer_len;
        zend_bool from_file = 0;
+       xmlDtdPtr dtd;
 
        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &buffer, &buffer_len, &from_file) == FAILURE) {
                return;
        }
+/*     Either of the following line force validation */
+/*     xmlLoadExtDtdDefaultValue = XML_DETECT_IDS; */
+/*     xmlDoValidityCheckingDefaultValue = 1; */
 
        if (from_file) {
                docp = xmlParseFile(buffer);
@@ -3297,6 +3316,11 @@ PHP_FUNCTION(xmldoc)
        if (!docp)
                RETURN_FALSE;
 
+/*     dtd = xmlGetIntSubset(docp);
+       if(dtd) {
+               xmlParseDTD(dtd->ExternalID, dtd->SystemID);
+       }
+*/
        DOMXML_RET_OBJ(rv, (xmlNodePtr) docp, &ret);
 }
 /* }}} */
@@ -3507,7 +3531,7 @@ PHP_FUNCTION(domxml_new_xmldoc)
 }
 /* }}} */
 
-/* {{{ proto object domxml_parer([string buf[,string filename]])
+/* {{{ proto object domxml_parser([string buf[,string filename]])
    Creates new xmlparser */
 PHP_FUNCTION(domxml_parser)
 {
@@ -3522,10 +3546,11 @@ PHP_FUNCTION(domxml_parser)
                return;
        }
 
-       parserp =  xmlCreatePushParserCtxt(NULL, NULL, buf, buf_len , filename);
+       parserp =  xmlCreatePushParserCtxt(NULL, NULL, buf, buf_len, filename);
        if (!parserp) {
                RETURN_FALSE;
        }
+/*     parserp->loadsubset = XML_DETECT_IDS; */
 
        rv = php_xmlparser_new(parserp, &ret TSRMLS_CC);    
        DOMXML_RET_ZVAL(rv);
@@ -4007,7 +4032,7 @@ static zval *php_xsltstylesheet_new(xsltStylesheetPtr obj, int *found TSRMLS_DC)
        zval *wrapper;
        int rsrc_type;
 
-               *found = 0;
+       *found = 0;
 
        if (!obj) {
                MAKE_STD_ZVAL(wrapper);