Browse Source

add support for $foo["a:bar"]

fix xsearch to only return values for text,element and attribute nodes
fix getChildren and return array
remove most methods
update test
PEAR_1_4DEV
Rob Richards 23 years ago
parent
commit
ad47abf0f6
  1. 230
      ext/simplexml/simplexml.c
  2. 4
      ext/simplexml/tests/017.phpt

230
ext/simplexml/simplexml.c

@ -158,9 +158,14 @@ static zval * sxe_prop_dim_read(zval *object, zval *member, zend_bool elements,
if (node) {
if (attribs) {
xmlChar *localname, *prefix=NULL;
localname = xmlSplitQName2(name, &prefix);
if (localname == NULL) {
localname = (xmlChar *)name;
}
attr = node->properties;
while (attr) {
if (!xmlStrcmp(attr->name, name)) {
if (!xmlStrcmp(attr->name, localname) && (prefix==NULL || (attr->ns && !xmlStrcmp(attr->ns->prefix, prefix)))) {
APPEND_PREV_ELEMENT(counter, value);
MAKE_STD_ZVAL(value);
@ -173,6 +178,12 @@ static zval * sxe_prop_dim_read(zval *object, zval *member, zend_bool elements,
}
attr = attr->next;
}
if (prefix) {
xmlFree(prefix);
if (localname) {
xmlFree(localname);
}
}
}
if (elements) {
@ -319,9 +330,14 @@ static void sxe_prop_dim_write(zval *object, zval *member, zval *value, zend_boo
if (node) {
if (attribs) {
xmlChar *localname, *prefix=NULL;
localname = xmlSplitQName2(name, &prefix);
if (localname == NULL) {
localname = (xmlChar *)name;
}
attr = node->properties;
while (attr) {
if (!xmlStrcmp(attr->name, name)) {
if (!xmlStrcmp(attr->name, localname) && (prefix==NULL || (attr->ns && !xmlStrcmp(attr->ns->prefix, prefix)))) {
is_attr = 1;
++counter;
break;
@ -329,6 +345,12 @@ static void sxe_prop_dim_write(zval *object, zval *member, zval *value, zend_boo
attr = attr->next;
}
if (prefix) {
xmlFree(prefix);
if (localname) {
xmlFree(localname);
}
}
}
if (elements) {
@ -402,6 +424,7 @@ static int sxe_prop_dim_exists(zval *object, zval *member, int check_empty, zend
char *name;
xmlNodePtr node;
xmlAttrPtr attr = NULL;
int exists = 0;
sxe = php_sxe_fetch_object(object TSRMLS_CC);
name = Z_STRVAL_P(member);
@ -410,14 +433,26 @@ static int sxe_prop_dim_exists(zval *object, zval *member, int check_empty, zend
if (node) {
if (attribs) {
xmlChar *localname, *prefix=NULL;
localname = xmlSplitQName2(name, &prefix);
if (localname == NULL) {
localname = (xmlChar *)name;
}
attr = node->properties;
while (attr) {
if (!xmlStrcmp(attr->name, name)) {
return 1;
if (!xmlStrcmp(attr->name, localname) && (prefix==NULL || (attr->ns && !xmlStrcmp(attr->ns->prefix, prefix)))) {
exists = 1;
break;
}
attr = attr->next;
}
if (prefix) {
xmlFree(prefix);
if (localname) {
xmlFree(localname);
}
}
}
if (elements) {
@ -435,7 +470,7 @@ next_iter:
}
}
return 0;
return exists;
}
/* }}} */
@ -479,15 +514,27 @@ static void sxe_prop_dim_delete(zval *object, zval *member, zend_bool elements,
if (node) {
if (attribs) {
xmlChar *localname, *prefix=NULL;
localname = xmlSplitQName2(Z_STRVAL_P(member), &prefix);
if (localname == NULL) {
localname = (xmlChar *)Z_STRVAL_P(member);
}
attr = node->properties;
while (attr) {
anext = attr->next;
if (!xmlStrcmp(attr->name, Z_STRVAL_P(member))) {
if (!xmlStrcmp(attr->name, localname) && (prefix==NULL || (attr->ns && !xmlStrcmp(attr->ns->prefix, prefix)))) {
xmlUnlinkNode((xmlNodePtr) attr);
php_libxml_node_free_resource((xmlNodePtr) attr TSRMLS_CC);
}
attr = anext;
}
if (prefix) {
xmlFree(prefix);
if (localname) {
xmlFree(localname);
}
}
}
if (elements) {
@ -687,6 +734,7 @@ SXE_METHOD(xsearch)
xmlNsPtr *ns = NULL;
xmlXPathObjectPtr retval;
xmlNodeSetPtr result;
xmlNodePtr nodeptr;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &query, &query_len) == FAILURE) {
return;
@ -740,18 +788,22 @@ SXE_METHOD(xsearch)
array_init(return_value);
for (i = 0; i < result->nodeNr; ++i) {
MAKE_STD_ZVAL(value);
/**
* Detect the case where the last selector is text(), simplexml
* always accesses the text() child by default, therefore we assign
* to the parent node.
*/
if (result->nodeTab[i]->type == XML_TEXT_NODE) {
_node_as_zval(sxe, result->nodeTab[i]->parent, value TSRMLS_CC);
} else {
_node_as_zval(sxe, result->nodeTab[i], value TSRMLS_CC);
nodeptr = result->nodeTab[i];
if (nodeptr->type == XML_TEXT_NODE || nodeptr->type == XML_ELEMENT_NODE || nodeptr->type == XML_ATTRIBUTE_NODE) {
MAKE_STD_ZVAL(value);
/**
* Detect the case where the last selector is text(), simplexml
* always accesses the text() child by default, therefore we assign
* to the parent node.
*/
if (nodeptr->type == XML_TEXT_NODE) {
_node_as_zval(sxe, nodeptr->parent, value TSRMLS_CC);
} else {
_node_as_zval(sxe, nodeptr, value TSRMLS_CC);
}
add_next_index_zval(return_value, value);
}
add_next_index_zval(return_value, value);
}
xmlXPathFreeObject(retval);
@ -912,31 +964,6 @@ SXE_METHOD(to_xml_file)
}
/* }}} */
/* {{{ simplexml_count()
*/
SXE_METHOD(count)
{
char *name;
int name_len;
HashTable *subnodes;
zval **data_ptr;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) {
return;
}
subnodes = sxe_properties_get(getThis() TSRMLS_CC);
if (zend_hash_find(subnodes, name, name_len+1, (void **) &data_ptr) == SUCCESS) {
if (Z_TYPE_PP(data_ptr) == IS_ARRAY) {
RETURN_LONG(zend_hash_num_elements(Z_ARRVAL_PP(data_ptr)));
} else {
RETURN_LONG(1);
}
} else {
RETURN_LONG(0);
}
}
/* }}} */
/* {{{ simplexml_attributes()
*/
SXE_METHOD(attributes)
@ -1307,14 +1334,6 @@ static void php_sxe_iterator_current(php_sxe_object *sxe TSRMLS_DC)
SKIP_TEXT(node);
do if (node->ns) {
if (node->parent->ns) {
if (!xmlStrcmp(node->ns->href, node->parent->ns->href)) {
break;
}
}
} while (0);
if (!sxe->iter.node->name) {
goto next_iter;
} else {
@ -1393,103 +1412,35 @@ static void php_sxe_iterator_rewind(zend_object_iterator *iter TSRMLS_DC)
php_sxe_iterator_current(iterator->sxe TSRMLS_CC);
}
/* {{{ rewind()
*/
SXE_METHOD(rewind)
{
php_sxe_object *sxe = php_sxe_fetch_object(getThis() TSRMLS_CC);
GET_NODE(sxe, sxe->iter.node);
if (sxe->iter.node) {
sxe->iter.node = sxe->iter.node->children;
}
php_sxe_iterator_current(sxe TSRMLS_CC);
}
/* }}} */
/* {{{ hasMore()
*/
SXE_METHOD(hasMore)
{
php_sxe_object *sxe = php_sxe_fetch_object(getThis() TSRMLS_CC);
RETURN_BOOL(sxe->iter.node);
}
/* }}} */
/* {{{ curent()
*/
SXE_METHOD(current)
{
php_sxe_object *sxe = php_sxe_fetch_object(getThis() TSRMLS_CC);
RETURN_ZVAL(sxe->iter.data, 1, 0);
}
/* }}} */
/* {{{ key()
*/
SXE_METHOD(key)
{
php_sxe_object *sxe = php_sxe_fetch_object(getThis() TSRMLS_CC);
RETURN_STRINGL(sxe->iter.name, sxe->iter.namelen-1, 1);
}
/* }}} */
/* {{{ next()
/* {{{ getChildren()
*/
SXE_METHOD(next)
SXE_METHOD(getChildren)
{
php_sxe_object *sxe = php_sxe_fetch_object(getThis() TSRMLS_CC);
php_sxe_object *sxe;
xmlNodePtr node;
xmlNodePtr child;
zval *value = NULL;
if (sxe->iter.node) {
sxe->iter.node = sxe->iter.node->next;
if (ZEND_NUM_ARGS() != 0) {
RETURN_FALSE;
}
php_sxe_iterator_current(sxe TSRMLS_CC);
}
/* }}} */
/* {{{ hasChildren()
*/
SXE_METHOD(hasChildren)
{
php_sxe_object *sxe = php_sxe_fetch_object(getThis() TSRMLS_CC);
php_sxe_object *child = php_sxe_fetch_object(sxe->iter.data TSRMLS_CC);
xmlNodePtr node;
sxe = php_sxe_fetch_object(getThis() TSRMLS_CC);
GET_NODE(sxe, node);
GET_NODE(child, node);
array_init(return_value);
if (node) {
node = node->children;
}
while (node) {
SKIP_TEXT(node);
do if (node->ns) {
if (node->parent->ns) {
if (!xmlStrcmp(node->ns->href, node->parent->ns->href)) {
break;
}
child = node->children;
while (child) {
if (node->type == XML_ELEMENT_NODE) {
MAKE_STD_ZVAL(value);
_node_as_zval(sxe, child, value TSRMLS_CC);
add_next_index_zval(return_value, value);
}
} while (0);
if (node->type == XML_ELEMENT_NODE) {
break;
child = child->next;
}
next_iter:
node = node->next;
}
RETURN_BOOL(node ? 1 : 0);
}
/* }}} */
/* {{{ getChildren()
*/
SXE_METHOD(getChildren)
{
php_sxe_object *sxe = php_sxe_fetch_object(getThis() TSRMLS_CC);
return_value->type = IS_OBJECT;
return_value->value.obj = zend_objects_store_clone_obj(sxe->iter.data TSRMLS_CC);
}
/* }}} */
@ -1582,14 +1533,7 @@ static zend_function_entry sxe_functions[] = {
SXE_ME(validate_schema_file, NULL, ZEND_ACC_PUBLIC)
#endif
SXE_ME(xsearch, NULL, ZEND_ACC_PUBLIC)
SXE_ME(rewind, NULL, ZEND_ACC_PUBLIC)
SXE_ME(hasMore, NULL, ZEND_ACC_PUBLIC)
SXE_ME(current, NULL, ZEND_ACC_PUBLIC)
SXE_ME(key, NULL, ZEND_ACC_PUBLIC)
SXE_ME(next, NULL, ZEND_ACC_PUBLIC)
SXE_ME(hasChildren, NULL, ZEND_ACC_PUBLIC)
SXE_ME(getChildren, NULL, ZEND_ACC_PUBLIC)
SXE_ME(count, NULL, ZEND_ACC_PUBLIC)
SXE_ME(attributes, NULL, ZEND_ACC_PUBLIC)
{NULL, NULL, NULL}
};

4
ext/simplexml/tests/017.phpt

@ -35,10 +35,10 @@ function print_xml($xml) {
}
function print_xml2($xml) {
$persons = $xml->count("person");
$persons = count($xml->person);
for ($i=0;$i<$persons;$i++) {
echo "person: ".$xml->person[$i]['name']."\n";
$children = $xml->person[$i]->count("child");
$children = count($xml->person[$i]->child);
for ($j=0;$j<$children;$j++) {
echo " child: ".$xml->person[$i]->child[$j]['name']."\n";
}

Loading…
Cancel
Save