Browse Source

- get_element_by_id() doesn't use xpath anymore but searches in

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
experimental/new_ui_api
Uwe Steinmann 25 years ago
parent
commit
d4c273c3a7
  1. 157
      ext/domxml/php_domxml.c

157
ext/domxml/php_domxml.c

@ -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);

Loading…
Cancel
Save