Browse Source

- Added ability to add elements by index if such elements already exist

- Added SimpleXMLElement::getName() to access the node name
# This allows to retrieve the name of the root element which is otherwise
# only available by converting the sxe object into a dom object.
migration/RELEASE_1_0_0
Marcus Boerger 21 years ago
parent
commit
d1f3c48041
  1. 46
      ext/simplexml/simplexml.c
  2. 40
      ext/simplexml/tests/026.phpt
  3. 74
      ext/simplexml/tests/027.phpt

46
ext/simplexml/simplexml.c

@ -130,10 +130,10 @@ static inline int match_ns(php_sxe_object *sxe, xmlNodePtr node, xmlChar *name)
} }
/* }}} */ /* }}} */
static xmlNodePtr sxe_get_element_by_offset(php_sxe_object *sxe, long offset, xmlNodePtr node) /* {{{ */
static xmlNodePtr sxe_get_element_by_offset(php_sxe_object *sxe, long offset, xmlNodePtr node, long *cnt) /* {{{ */
{ {
long nodendx = 0; long nodendx = 0;
if (sxe->iter.type == SXE_ITER_NONE) { if (sxe->iter.type == SXE_ITER_NONE) {
return NULL; return NULL;
} }
@ -151,6 +151,10 @@ static xmlNodePtr sxe_get_element_by_offset(php_sxe_object *sxe, long offset, xm
next_iter: next_iter:
node = node->next; node = node->next;
} }
if (cnt) {
*cnt = nodendx;
}
return node; return node;
} }
@ -303,7 +307,7 @@ static zval * sxe_prop_dim_read(zval *object, zval *member, zend_bool elements,
if (sxe->iter.type == SXE_ITER_CHILD) { if (sxe->iter.type == SXE_ITER_CHILD) {
node = php_sxe_get_first_node(sxe, node TSRMLS_CC); node = php_sxe_get_first_node(sxe, node TSRMLS_CC);
} }
node = sxe_get_element_by_offset(sxe, Z_LVAL_P(member), node);
node = sxe_get_element_by_offset(sxe, Z_LVAL_P(member), node, NULL);
if (node) { if (node) {
_node_as_zval(sxe, node, return_value, SXE_ITER_NONE, NULL, sxe->iter.nsprefix TSRMLS_CC); _node_as_zval(sxe, node, return_value, SXE_ITER_NONE, NULL, sxe->iter.nsprefix TSRMLS_CC);
} }
@ -397,6 +401,7 @@ static void sxe_prop_dim_write(zval *object, zval *member, zval *value, zend_boo
int is_attr = 0; int is_attr = 0;
int nodendx = 0; int nodendx = 0;
int test = 0; int test = 0;
long cnt;
zval tmp_zv, trim_zv; zval tmp_zv, trim_zv;
if (!member) { if (!member) {
@ -482,7 +487,7 @@ static void sxe_prop_dim_write(zval *object, zval *member, zval *value, zend_boo
if (elements) { if (elements) {
if (Z_TYPE_P(member) == IS_LONG) { if (Z_TYPE_P(member) == IS_LONG) {
newnode = sxe_get_element_by_offset(sxe, Z_LVAL_P(member), node);
newnode = sxe_get_element_by_offset(sxe, Z_LVAL_P(member), node, &cnt);
if (newnode) { if (newnode) {
++counter; ++counter;
} }
@ -513,8 +518,15 @@ next_iter:
change_node_zval(newnode, value TSRMLS_CC); change_node_zval(newnode, value TSRMLS_CC);
} else if (counter > 1) { } else if (counter > 1) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot assign to an array of nodes (duplicate subnodes or attr detected)"); php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot assign to an array of nodes (duplicate subnodes or attr detected)");
} else if (elements && !node) {
xmlNewChild(mynode, mynode->ns, name, Z_STRVAL_P(value));
} else if (elements) {
if (!node) {
xmlNewTextChild(mynode, mynode->ns, name, Z_STRVAL_P(value));
} else if (Z_TYPE_P(member) == IS_LONG) {
if (cnt < Z_LVAL_P(member)) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot add element %s number %ld when only %ld such elements exist", mynode->name, Z_LVAL_P(member), cnt);
}
xmlNewTextChild(mynode->parent, mynode->ns, mynode->name, Z_STRVAL_P(value));
}
} else { } else {
if (attribs) { if (attribs) {
switch (Z_TYPE_P(value)) { switch (Z_TYPE_P(value)) {
@ -612,7 +624,7 @@ static int sxe_prop_dim_exists(zval *object, zval *member, int check_empty, zend
if (sxe->iter.type == SXE_ITER_CHILD) { if (sxe->iter.type == SXE_ITER_CHILD) {
node = php_sxe_get_first_node(sxe, node TSRMLS_CC); node = php_sxe_get_first_node(sxe, node TSRMLS_CC);
} }
node = sxe_get_element_by_offset(sxe, Z_LVAL_P(member), node);
node = sxe_get_element_by_offset(sxe, Z_LVAL_P(member), node, NULL);
} }
else { else {
zval tmp_zv; zval tmp_zv;
@ -1221,7 +1233,7 @@ SXE_METHOD(getDocNamespaces)
} }
/* }}} */ /* }}} */
/* {{{ proto object SimpleXMLElement::children()
/* {{{ proto object SimpleXMLElement::children([string ns])
Finds children of given node */ Finds children of given node */
SXE_METHOD(children) SXE_METHOD(children)
{ {
@ -1248,6 +1260,23 @@ SXE_METHOD(children)
} }
/* }}} */ /* }}} */
/* {{{ proto object SimpleXMLElement::getName()
Finds children of given node */
SXE_METHOD(getName)
{
php_sxe_object *sxe;
xmlNodePtr node;
int namelen;
sxe = php_sxe_fetch_object(getThis() TSRMLS_CC);
GET_NODE(sxe, node);
namelen = xmlStrlen(node->name);
RETURN_STRINGL((char*)node->name, namelen, 1);
}
/* }}} */
/* {{{ proto array SimpleXMLElement::attributes([string ns]) /* {{{ proto array SimpleXMLElement::attributes([string ns])
Identifies an element's attributes */ Identifies an element's attributes */
SXE_METHOD(attributes) SXE_METHOD(attributes)
@ -1985,6 +2014,7 @@ static zend_function_entry sxe_functions[] = {
SXE_ME(children, NULL, ZEND_ACC_PUBLIC) SXE_ME(children, NULL, ZEND_ACC_PUBLIC)
SXE_ME(getNamespaces, NULL, ZEND_ACC_PUBLIC) SXE_ME(getNamespaces, NULL, ZEND_ACC_PUBLIC)
SXE_ME(getDocNamespaces, NULL, ZEND_ACC_PUBLIC) SXE_ME(getDocNamespaces, NULL, ZEND_ACC_PUBLIC)
SXE_ME(getName, NULL, ZEND_ACC_PUBLIC)
{NULL, NULL, NULL} {NULL, NULL, NULL}
}; };

40
ext/simplexml/tests/026.phpt

@ -0,0 +1,40 @@
--TEST--
SimpleXML: getName()
--SKIPIF--
<?php if (!extension_loaded("simplexml")) print "skip"; ?>
--FILE--
<?php
$xml =<<<EOF
<people>
<person>Jane</person>
</people>
EOF;
function traverse_xml($xml, $pad = '')
{
$name = $xml->getName();
echo "$pad<$name";
foreach($xml->attributes() as $attr => $value)
{
echo " $attr=\"$value\"";
}
echo ">" . trim($xml) . "\n";
foreach($xml->children() as $node)
{
traverse_xml($node, $pad.' ');
}
echo $pad."</$name>\n";
}
$people = simplexml_load_string($xml);
traverse_xml($people);
?>
===DONE===
--EXPECTF--
<people>
<person>Jane
</person>
</people>
===DONE===

74
ext/simplexml/tests/027.phpt

@ -0,0 +1,74 @@
--TEST--
SimpleXML: Adding an elements
--SKIPIF--
<?php if (!extension_loaded("simplexml")) print "skip"; ?>
--FILE--
<?php
$xml =<<<EOF
<people></people>
EOF;
function traverse_xml($xml, $pad = '')
{
$name = $xml->getName();
echo "$pad<$name";
foreach($xml->attributes() as $attr => $value)
{
echo " $attr=\"$value\"";
}
echo ">" . trim($xml) . "\n";
foreach($xml->children() as $node)
{
traverse_xml($node, $pad.' ');
}
echo $pad."</$name>\n";
}
$people = simplexml_load_string($xml);
traverse_xml($people);
$people->person = 'Joe';
$people->person['gender'] = 'male';
traverse_xml($people);
$people->person = 'Jane';
traverse_xml($people);
$people->person['gender'] = 'female';
$people->person[1] = 'Joe';
$people->person[1]['gender'] = 'male';
traverse_xml($people);
$people->person[3] = 'Minni-me';
$people->person[2]['gender'] = 'male';
traverse_xml($people);
$people->person[3]['gender'] = 'error';
?>
===DONE===
--EXPECTF--
<people>
</people>
<people>
<person gender="male">Joe
</person>
</people>
<people>
<person gender="male">Jane
</person>
</people>
<people>
<person gender="female">Jane
</person>
<person gender="male">Joe
</person>
</people>
Warning: main(): Cannot add element person number 3 when only 2 such elements exist in %sext/simplexml/tests/027.php on line %d
<people>
<person gender="female">Jane
</person>
<person gender="male">Joe
</person>
<person gender="male">Minni-me
</person>
</people>
Fatal error: Objects used as arrays in post/pre increment/decrement must return values by reference in %sext/simplexml/tests/027.php on line %d
Loading…
Cancel
Save