mirror of
https://github.com/php/php-src.git
synced 2025-08-15 21:48:51 +02:00
[RFC] Implement new DOM Living Standard APIs in ext/dom
This commit is contained in:
parent
87bc99439d
commit
5acd86df8e
35 changed files with 1565 additions and 41 deletions
|
@ -37,6 +37,10 @@ const zend_function_entry php_dom_characterdata_class_functions[] = {
|
|||
PHP_ME(domcharacterdata, insertData, arginfo_class_DOMCharacterData_insertData, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(domcharacterdata, deleteData, arginfo_class_DOMCharacterData_deleteData, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(domcharacterdata, replaceData, arginfo_class_DOMCharacterData_replaceData, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(domcharacterdata, remove, arginfo_class_DOMChildNode_remove, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(domcharacterdata, after, arginfo_class_DOMChildNode_after, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(domcharacterdata, before, arginfo_class_DOMChildNode_before, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(domcharacterdata, replaceWith, arginfo_class_DOMChildNode_replaceWith, ZEND_ACC_PUBLIC)
|
||||
PHP_FE_END
|
||||
};
|
||||
|
||||
|
@ -361,4 +365,104 @@ PHP_METHOD(domcharacterdata, replaceData)
|
|||
}
|
||||
/* }}} end dom_characterdata_replace_data */
|
||||
|
||||
PHP_METHOD(domcharacterdata, remove)
|
||||
{
|
||||
zval *id = ZEND_THIS;
|
||||
xmlNodePtr children, child;
|
||||
dom_object *intern;
|
||||
int stricterror;
|
||||
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
RETURN_THROWS();
|
||||
}
|
||||
|
||||
DOM_GET_OBJ(child, id, xmlNodePtr, intern);
|
||||
|
||||
if (dom_node_children_valid(child) == FAILURE) {
|
||||
RETURN_NULL();
|
||||
}
|
||||
|
||||
stricterror = dom_get_strict_error(intern->document);
|
||||
|
||||
if (dom_node_is_read_only(child) == SUCCESS ||
|
||||
(child->parent != NULL && dom_node_is_read_only(child->parent) == SUCCESS)) {
|
||||
php_dom_throw_error(NO_MODIFICATION_ALLOWED_ERR, stricterror);
|
||||
RETURN_NULL();
|
||||
}
|
||||
|
||||
if (!child->parent) {
|
||||
php_dom_throw_error(NOT_FOUND_ERR, stricterror);
|
||||
RETURN_NULL();
|
||||
}
|
||||
|
||||
children = child->parent->children;
|
||||
if (!children) {
|
||||
php_dom_throw_error(NOT_FOUND_ERR, stricterror);
|
||||
RETURN_NULL();
|
||||
}
|
||||
|
||||
while (children) {
|
||||
if (children == child) {
|
||||
xmlUnlinkNode(child);
|
||||
RETURN_NULL();
|
||||
}
|
||||
children = children->next;
|
||||
}
|
||||
|
||||
php_dom_throw_error(NOT_FOUND_ERR, stricterror);
|
||||
RETURN_NULL();
|
||||
}
|
||||
|
||||
PHP_METHOD(domcharacterdata, after)
|
||||
{
|
||||
int argc;
|
||||
zval *args, *id;
|
||||
dom_object *intern;
|
||||
xmlNode *context;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "+", &args, &argc) == FAILURE) {
|
||||
RETURN_THROWS();
|
||||
}
|
||||
|
||||
id = ZEND_THIS;
|
||||
DOM_GET_OBJ(context, id, xmlNodePtr, intern);
|
||||
|
||||
dom_parent_node_after(intern, args, argc);
|
||||
}
|
||||
|
||||
PHP_METHOD(domcharacterdata, before)
|
||||
{
|
||||
int argc;
|
||||
zval *args, *id;
|
||||
dom_object *intern;
|
||||
xmlNode *context;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "+", &args, &argc) == FAILURE) {
|
||||
RETURN_THROWS();
|
||||
}
|
||||
|
||||
id = ZEND_THIS;
|
||||
DOM_GET_OBJ(context, id, xmlNodePtr, intern);
|
||||
|
||||
dom_parent_node_before(intern, args, argc);
|
||||
}
|
||||
|
||||
PHP_METHOD(domcharacterdata, replaceWith)
|
||||
{
|
||||
int argc;
|
||||
zval *args, *id;
|
||||
dom_object *intern;
|
||||
xmlNode *context;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "+", &args, &argc) == FAILURE) {
|
||||
RETURN_THROWS();
|
||||
}
|
||||
|
||||
id = ZEND_THIS;
|
||||
DOM_GET_OBJ(context, id, xmlNodePtr, intern);
|
||||
|
||||
dom_parent_node_after(intern, args, argc);
|
||||
dom_child_node_remove(intern);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -13,7 +13,7 @@ if test "$PHP_DOM" != "no"; then
|
|||
PHP_SETUP_LIBXML(DOM_SHARED_LIBADD, [
|
||||
AC_DEFINE(HAVE_DOM,1,[ ])
|
||||
PHP_NEW_EXTENSION(dom, [php_dom.c attr.c document.c \
|
||||
domexception.c \
|
||||
domexception.c parentnode.c \
|
||||
processinginstruction.c cdatasection.c \
|
||||
documentfragment.c domimplementation.c \
|
||||
element.c node.c characterdata.c \
|
||||
|
|
|
@ -8,7 +8,7 @@ if (PHP_DOM == "yes") {
|
|||
CHECK_HEADER_ADD_INCLUDE("libxml/parser.h", "CFLAGS_DOM", PHP_PHP_BUILD + "\\include\\libxml2")
|
||||
) {
|
||||
EXTENSION("dom", "php_dom.c attr.c document.c \
|
||||
domexception.c processinginstruction.c \
|
||||
domexception.c parentnode.c processinginstruction.c \
|
||||
cdatasection.c documentfragment.c domimplementation.c element.c \
|
||||
node.c characterdata.c documenttype.c \
|
||||
entity.c nodelist.c text.c comment.c \
|
||||
|
|
|
@ -82,6 +82,8 @@ const zend_function_entry php_dom_document_class_functions[] = { /* {{{ */
|
|||
PHP_ME(domdocument, relaxNGValidateSource, arginfo_class_DOMDocument_relaxNGValidateSource, ZEND_ACC_PUBLIC)
|
||||
#endif
|
||||
PHP_ME(domdocument, registerNodeClass, arginfo_class_DOMDocument_registerNodeClass, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(domdocument, append, arginfo_class_DOMParentNode_append, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(domdocument, prepend, arginfo_class_DOMParentNode_prepend, ZEND_ACC_PUBLIC)
|
||||
PHP_FE_END
|
||||
};
|
||||
/* }}} */
|
||||
|
@ -2128,4 +2130,48 @@ PHP_METHOD(domdocument, registerNodeClass)
|
|||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto void domdocument::append(string|DOMNode ...$nodes)
|
||||
URL: https://dom.spec.whatwg.org/#dom-parentnode-append
|
||||
Since: DOM Living Standard (DOM4)
|
||||
*/
|
||||
PHP_METHOD(domdocument, append)
|
||||
{
|
||||
int argc;
|
||||
zval *args, *id;
|
||||
dom_object *intern;
|
||||
xmlNode *context;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "+", &args, &argc) == FAILURE) {
|
||||
RETURN_THROWS();
|
||||
}
|
||||
|
||||
id = ZEND_THIS;
|
||||
DOM_GET_OBJ(context, id, xmlNodePtr, intern);
|
||||
|
||||
dom_parent_node_append(intern, args, argc);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto void domdocument::prepend(string|DOMNode ...$nodes)
|
||||
URL: https://dom.spec.whatwg.org/#dom-parentnode-prepend
|
||||
Since: DOM Living Standard (DOM4)
|
||||
*/
|
||||
PHP_METHOD(domdocument, prepend)
|
||||
{
|
||||
int argc;
|
||||
zval *args, *id;
|
||||
dom_object *intern;
|
||||
xmlNode *context;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "+", &args, &argc) == FAILURE) {
|
||||
RETURN_THROWS();
|
||||
}
|
||||
|
||||
id = ZEND_THIS;
|
||||
DOM_GET_OBJ(context, id, xmlNodePtr, intern);
|
||||
|
||||
dom_parent_node_prepend(intern, args, argc);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
#endif /* HAVE_LIBXML && HAVE_DOM */
|
||||
|
|
|
@ -34,6 +34,8 @@
|
|||
const zend_function_entry php_dom_documentfragment_class_functions[] = {
|
||||
PHP_ME(domdocumentfragment, __construct, arginfo_class_DOMDocumentFragment___construct, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(domdocumentfragment, appendXML, arginfo_class_DOMDocumentFragment_appendXML, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(domdocumentfragment, append, arginfo_class_DOMParentNode_append, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(domdocumentfragment, prepend, arginfo_class_DOMParentNode_prepend, ZEND_ACC_PUBLIC)
|
||||
PHP_FE_END
|
||||
};
|
||||
|
||||
|
@ -137,4 +139,48 @@ PHP_METHOD(domdocumentfragment, appendXML) {
|
|||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto void domdocumentfragment::append(string|DOMNode ...$nodes)
|
||||
URL: https://dom.spec.whatwg.org/#dom-parentnode-append
|
||||
Since: DOM Living Standard (DOM4)
|
||||
*/
|
||||
PHP_METHOD(domdocumentfragment, append)
|
||||
{
|
||||
int argc;
|
||||
zval *args, *id;
|
||||
dom_object *intern;
|
||||
xmlNode *context;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "+", &args, &argc) == FAILURE) {
|
||||
RETURN_THROWS();
|
||||
}
|
||||
|
||||
id = ZEND_THIS;
|
||||
DOM_GET_OBJ(context, id, xmlNodePtr, intern);
|
||||
|
||||
dom_parent_node_append(intern, args, argc);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto void domdocumentfragment::prepend(string|DOMNode ...$nodes)
|
||||
URL: https://dom.spec.whatwg.org/#dom-parentnode-prepend
|
||||
Since: DOM Living Standard (DOM4)
|
||||
*/
|
||||
PHP_METHOD(domdocumentfragment, prepend)
|
||||
{
|
||||
int argc;
|
||||
zval *args, *id;
|
||||
dom_object *intern;
|
||||
xmlNode *context;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "+", &args, &argc) == FAILURE) {
|
||||
RETURN_THROWS();
|
||||
}
|
||||
|
||||
id = ZEND_THIS;
|
||||
DOM_GET_OBJ(context, id, xmlNodePtr, intern);
|
||||
|
||||
dom_parent_node_prepend(intern, args, argc);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,5 +1,28 @@
|
|||
<?php
|
||||
|
||||
interface DOMChildNode
|
||||
{
|
||||
public function remove(): void;
|
||||
|
||||
/** @var ...DOMNode|string $nodes */
|
||||
public function before(... $nodes): void;
|
||||
|
||||
/** @var ...DOMNode|string $nodes */
|
||||
public function after(...$nodes): void;
|
||||
|
||||
/** @var ...DOMNode|string $nodes */
|
||||
public function replaceWith(...$nodes): void;
|
||||
}
|
||||
|
||||
interface DOMParentNode
|
||||
{
|
||||
/** @var ...DOMNode|string $nodes */
|
||||
public function append(...$nodes): void;
|
||||
|
||||
/** @var ...DOMNode|string $nodes */
|
||||
public function prepend(...$nodes): void;
|
||||
}
|
||||
|
||||
class DOMNode {
|
||||
/** @return DOMNode|false */
|
||||
public function appendChild(DOMNode $newChild) {}
|
||||
|
@ -63,7 +86,7 @@ class DOMCdataSection {
|
|||
public function __construct(string $value) {}
|
||||
}
|
||||
|
||||
class DOMCharacterData {
|
||||
class DOMCharacterData implements DOMChildNode {
|
||||
/** @return bool */
|
||||
public function appendData(string $data) {}
|
||||
|
||||
|
@ -84,7 +107,7 @@ class DOMComment {
|
|||
public function __construct(string $value = "") {}
|
||||
}
|
||||
|
||||
class DOMDocument {
|
||||
class DOMDocument implements DOMParentNode {
|
||||
public function __construct(string $version = "1.0", string $encoding = UNKNOWN) {}
|
||||
|
||||
/** @return DOMAttr|false */
|
||||
|
@ -185,14 +208,14 @@ class DOMDocument {
|
|||
public function adoptNode(DOMNode $source) {}
|
||||
}
|
||||
|
||||
class DOMDocumentFragment {
|
||||
class DOMDocumentFragment implements DOMParentNode {
|
||||
public function __construct() {}
|
||||
|
||||
/** @return bool */
|
||||
public function appendXML(string $data) {}
|
||||
}
|
||||
|
||||
class DOMElement {
|
||||
class DOMElement implements DOMParentNode, DOMChildNode {
|
||||
public function __construct(string $name, ?string $value = null, string $uri = "") {}
|
||||
|
||||
/** @return string */
|
||||
|
|
|
@ -1,5 +1,20 @@
|
|||
/* This is a generated file, edit the .stub.php file instead. */
|
||||
|
||||
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_DOMChildNode_remove, 0, 0, IS_VOID, 0)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_DOMChildNode_before, 0, 0, IS_VOID, 0)
|
||||
ZEND_ARG_VARIADIC_INFO(0, nodes)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
#define arginfo_class_DOMChildNode_after arginfo_class_DOMChildNode_before
|
||||
|
||||
#define arginfo_class_DOMChildNode_replaceWith arginfo_class_DOMChildNode_before
|
||||
|
||||
#define arginfo_class_DOMParentNode_append arginfo_class_DOMChildNode_before
|
||||
|
||||
#define arginfo_class_DOMParentNode_prepend arginfo_class_DOMChildNode_before
|
||||
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_DOMNode_appendChild, 0, 0, 1)
|
||||
ZEND_ARG_OBJ_INFO(0, newChild, DOMNode, 0)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
#define DOM_FE_H
|
||||
|
||||
extern const zend_function_entry php_dom_domexception_class_functions[];
|
||||
extern const zend_function_entry php_dom_parent_node_class_functions[];
|
||||
extern const zend_function_entry php_dom_child_node_class_functions[];
|
||||
extern const zend_function_entry php_dom_domimplementation_class_functions[];
|
||||
extern const zend_function_entry php_dom_documentfragment_class_functions[];
|
||||
extern const zend_function_entry php_dom_document_class_functions[];
|
||||
|
@ -75,6 +77,8 @@ PHP_METHOD(domimplementation, getFeature);
|
|||
/* domdocumentfragment methods */
|
||||
PHP_METHOD(domdocumentfragment, __construct);
|
||||
PHP_METHOD(domdocumentfragment, appendXML);
|
||||
PHP_METHOD(domdocumentfragment, append);
|
||||
PHP_METHOD(domdocumentfragment, prepend);
|
||||
|
||||
/* domdocument methods */
|
||||
PHP_METHOD(domdocument, createElement);
|
||||
|
@ -102,6 +106,8 @@ PHP_METHOD(domdocument, saveXML);
|
|||
PHP_METHOD(domdocument, validate);
|
||||
PHP_METHOD(domdocument, xinclude);
|
||||
PHP_METHOD(domdocument, registerNodeClass);
|
||||
PHP_METHOD(domdocument, append);
|
||||
PHP_METHOD(domdocument, prepend);
|
||||
|
||||
#if defined(LIBXML_HTML_ENABLED)
|
||||
PHP_METHOD(domdocument, loadHTML);
|
||||
|
@ -152,6 +158,10 @@ PHP_METHOD(domcharacterdata, appendData);
|
|||
PHP_METHOD(domcharacterdata, insertData);
|
||||
PHP_METHOD(domcharacterdata, deleteData);
|
||||
PHP_METHOD(domcharacterdata, replaceData);
|
||||
PHP_METHOD(domcharacterdata, remove);
|
||||
PHP_METHOD(domcharacterdata, after);
|
||||
PHP_METHOD(domcharacterdata, before);
|
||||
PHP_METHOD(domcharacterdata, replaceWith);
|
||||
|
||||
/* domattr methods */
|
||||
PHP_METHOD(domattr, isId);
|
||||
|
@ -177,6 +187,12 @@ PHP_METHOD(domelement, setIdAttribute);
|
|||
PHP_METHOD(domelement, setIdAttributeNS);
|
||||
PHP_METHOD(domelement, setIdAttributeNode);
|
||||
PHP_METHOD(domelement, __construct);
|
||||
PHP_METHOD(domelement, remove);
|
||||
PHP_METHOD(domelement, after);
|
||||
PHP_METHOD(domelement, before);
|
||||
PHP_METHOD(domelement, append);
|
||||
PHP_METHOD(domelement, prepend);
|
||||
PHP_METHOD(domelement, replaceWith);
|
||||
|
||||
/* domtext methods */
|
||||
PHP_METHOD(domtext, splitText);
|
||||
|
|
|
@ -87,6 +87,11 @@ int dom_entity_version_write(dom_object *obj, zval *newval);
|
|||
/* namednodemap properties */
|
||||
int dom_namednodemap_length_read(dom_object *obj, zval *retval);
|
||||
|
||||
/* parent node properties */
|
||||
int dom_parent_node_first_element_child_read(dom_object *obj, zval *retval);
|
||||
int dom_parent_node_last_element_child_read(dom_object *obj, zval *retval);
|
||||
int dom_parent_node_child_element_count(dom_object *obj, zval *retval);
|
||||
|
||||
/* node properties */
|
||||
int dom_node_node_name_read(dom_object *obj, zval *retval);
|
||||
int dom_node_node_value_read(dom_object *obj, zval *retval);
|
||||
|
@ -98,6 +103,8 @@ int dom_node_first_child_read(dom_object *obj, zval *retval);
|
|||
int dom_node_last_child_read(dom_object *obj, zval *retval);
|
||||
int dom_node_previous_sibling_read(dom_object *obj, zval *retval);
|
||||
int dom_node_next_sibling_read(dom_object *obj, zval *retval);
|
||||
int dom_node_previous_element_sibling_read(dom_object *obj, zval *retval);
|
||||
int dom_node_next_element_sibling_read(dom_object *obj, zval *retval);
|
||||
int dom_node_attributes_read(dom_object *obj, zval *retval);
|
||||
int dom_node_owner_document_read(dom_object *obj, zval *retval);
|
||||
int dom_node_namespace_uri_read(dom_object *obj, zval *retval);
|
||||
|
|
|
@ -51,6 +51,12 @@ const zend_function_entry php_dom_element_class_functions[] = { /* {{{ */
|
|||
PHP_ME(domelement, setIdAttributeNS, arginfo_class_DOMElement_setIdAttributeNS, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(domelement, setIdAttributeNode, arginfo_class_DOMElement_setIdAttributeNode, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(domelement, __construct, arginfo_class_DOMElement___construct, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(domelement, remove, arginfo_class_DOMChildNode_remove, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(domelement, after, arginfo_class_DOMChildNode_after, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(domelement, before, arginfo_class_DOMChildNode_before, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(domelement, replaceWith, arginfo_class_DOMChildNode_replaceWith, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(domelement, append, arginfo_class_DOMParentNode_append, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(domelement, prepend, arginfo_class_DOMParentNode_prepend, ZEND_ACC_PUBLIC)
|
||||
PHP_FE_END
|
||||
};
|
||||
/* }}} */
|
||||
|
@ -1183,4 +1189,126 @@ PHP_METHOD(domelement, setIdAttributeNode)
|
|||
}
|
||||
/* }}} end dom_element_set_id_attribute_node */
|
||||
|
||||
/* {{{ proto void DOMElement::remove();
|
||||
URL:
|
||||
Since:
|
||||
*/
|
||||
PHP_METHOD(domelement, remove)
|
||||
{
|
||||
zval *id;
|
||||
xmlNodePtr child;
|
||||
dom_object *intern;
|
||||
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
RETURN_THROWS();
|
||||
}
|
||||
|
||||
id = ZEND_THIS;
|
||||
DOM_GET_OBJ(child, id, xmlNodePtr, intern);
|
||||
|
||||
dom_child_node_remove(intern);
|
||||
}
|
||||
/* }}} end DOMElement::remove */
|
||||
|
||||
PHP_METHOD(domelement, after)
|
||||
{
|
||||
int argc;
|
||||
zval *args, *id;
|
||||
dom_object *intern;
|
||||
xmlNode *context;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "+", &args, &argc) == FAILURE) {
|
||||
RETURN_THROWS();
|
||||
}
|
||||
|
||||
id = ZEND_THIS;
|
||||
DOM_GET_OBJ(context, id, xmlNodePtr, intern);
|
||||
|
||||
dom_parent_node_after(intern, args, argc);
|
||||
}
|
||||
|
||||
PHP_METHOD(domelement, before)
|
||||
{
|
||||
int argc;
|
||||
zval *args, *id;
|
||||
dom_object *intern;
|
||||
xmlNode *context;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "+", &args, &argc) == FAILURE) {
|
||||
RETURN_THROWS();
|
||||
}
|
||||
|
||||
id = ZEND_THIS;
|
||||
DOM_GET_OBJ(context, id, xmlNodePtr, intern);
|
||||
|
||||
dom_parent_node_before(intern, args, argc);
|
||||
}
|
||||
|
||||
/* {{{ proto void domelement::append(string|DOMNode ...$nodes)
|
||||
URL: https://dom.spec.whatwg.org/#dom-parentnode-append
|
||||
Since: DOM Living Standard (DOM4)
|
||||
*/
|
||||
PHP_METHOD(domelement, append)
|
||||
{
|
||||
int argc;
|
||||
zval *args, *id;
|
||||
dom_object *intern;
|
||||
xmlNode *context;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "+", &args, &argc) == FAILURE) {
|
||||
RETURN_THROWS();
|
||||
}
|
||||
|
||||
id = ZEND_THIS;
|
||||
DOM_GET_OBJ(context, id, xmlNodePtr, intern);
|
||||
|
||||
dom_parent_node_append(intern, args, argc);
|
||||
}
|
||||
/* }}} end DOMElement::append */
|
||||
|
||||
/* {{{ proto void domelement::prepend(string|DOMNode ...$nodes)
|
||||
URL: https://dom.spec.whatwg.org/#dom-parentnode-prepend
|
||||
Since: DOM Living Standard (DOM4)
|
||||
*/
|
||||
PHP_METHOD(domelement, prepend)
|
||||
{
|
||||
int argc;
|
||||
zval *args, *id;
|
||||
dom_object *intern;
|
||||
xmlNode *context;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "+", &args, &argc) == FAILURE) {
|
||||
RETURN_THROWS();
|
||||
}
|
||||
|
||||
id = ZEND_THIS;
|
||||
DOM_GET_OBJ(context, id, xmlNodePtr, intern);
|
||||
|
||||
dom_parent_node_prepend(intern, args, argc);
|
||||
}
|
||||
/* }}} end DOMElement::prepend */
|
||||
|
||||
/* {{{ proto void domelement::replaceWith(string|DOMNode ...$nodes)
|
||||
URL: https://dom.spec.whatwg.org/#dom-parentnode-prepend
|
||||
Since: DOM Living Standard (DOM4)
|
||||
*/
|
||||
PHP_METHOD(domelement, replaceWith)
|
||||
{
|
||||
int argc;
|
||||
zval *args, *id;
|
||||
dom_object *intern;
|
||||
xmlNode *context;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "+", &args, &argc) == FAILURE) {
|
||||
RETURN_THROWS();
|
||||
}
|
||||
|
||||
id = ZEND_THIS;
|
||||
DOM_GET_OBJ(context, id, xmlNodePtr, intern);
|
||||
|
||||
dom_parent_node_after(intern, args, argc);
|
||||
dom_child_node_remove(intern);
|
||||
}
|
||||
/* }}} end DOMElement::prepend */
|
||||
|
||||
#endif
|
||||
|
|
103
ext/dom/node.c
103
ext/dom/node.c
|
@ -53,36 +53,12 @@ const zend_function_entry php_dom_node_class_functions[] = { /* {{{ */
|
|||
};
|
||||
/* }}} */
|
||||
|
||||
static void dom_reconcile_ns(xmlDocPtr doc, xmlNodePtr nodep) /* {{{ */
|
||||
{
|
||||
xmlNsPtr nsptr, nsdftptr, curns, prevns = NULL;
|
||||
|
||||
if (nodep->type == XML_ELEMENT_NODE) {
|
||||
/* Following if block primarily used for inserting nodes created via createElementNS */
|
||||
if (nodep->nsDef != NULL) {
|
||||
curns = nodep->nsDef;
|
||||
while (curns) {
|
||||
nsdftptr = curns->next;
|
||||
if (curns->href != NULL) {
|
||||
if((nsptr = xmlSearchNsByHref(doc, nodep->parent, curns->href)) &&
|
||||
(curns->prefix == NULL || xmlStrEqual(nsptr->prefix, curns->prefix))) {
|
||||
curns->next = NULL;
|
||||
if (prevns == NULL) {
|
||||
nodep->nsDef = nsdftptr;
|
||||
} else {
|
||||
prevns->next = nsdftptr;
|
||||
}
|
||||
dom_set_old_ns(doc, curns);
|
||||
curns = prevns;
|
||||
}
|
||||
}
|
||||
prevns = curns;
|
||||
curns = nsdftptr;
|
||||
}
|
||||
}
|
||||
xmlReconciliateNs(doc, nodep);
|
||||
}
|
||||
}
|
||||
const zend_function_entry php_dom_child_node_class_functions[] = { /* {{{ */
|
||||
PHP_ABSTRACT_ME(DOMChildNode, remove, arginfo_class_DOMChildNode_remove)
|
||||
PHP_ABSTRACT_ME(DOMChildNode, after, arginfo_class_DOMChildNode_after)
|
||||
PHP_ABSTRACT_ME(DOMChildNode, before, arginfo_class_DOMChildNode_before)
|
||||
PHP_FE_END
|
||||
};
|
||||
/* }}} */
|
||||
|
||||
/* {{{ nodeName string
|
||||
|
@ -333,7 +309,6 @@ int dom_node_child_nodes_read(dom_object *obj, zval *retval)
|
|||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ firstChild DomNode
|
||||
|
@ -454,6 +429,72 @@ int dom_node_next_sibling_read(dom_object *obj, zval *retval)
|
|||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ previousElementSibling DomNode
|
||||
readonly=yes
|
||||
URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-640FB3C8
|
||||
Since:
|
||||
*/
|
||||
int dom_node_previous_element_sibling_read(dom_object *obj, zval *retval)
|
||||
{
|
||||
xmlNode *nodep, *prevsib;
|
||||
|
||||
nodep = dom_object_get_node(obj);
|
||||
|
||||
if (nodep == NULL) {
|
||||
php_dom_throw_error(INVALID_STATE_ERR, 0);
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
prevsib = nodep->prev;
|
||||
|
||||
while (prevsib && prevsib->type != XML_ELEMENT_NODE) {
|
||||
prevsib = prevsib->prev;
|
||||
}
|
||||
|
||||
if (!prevsib) {
|
||||
ZVAL_NULL(retval);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
php_dom_create_object(prevsib, retval, obj);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ nextElementSibling DomNode
|
||||
readonly=yes
|
||||
URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-6AC54C2F
|
||||
Since:
|
||||
*/
|
||||
int dom_node_next_element_sibling_read(dom_object *obj, zval *retval)
|
||||
{
|
||||
xmlNode *nodep, *nextsib;
|
||||
|
||||
nodep = dom_object_get_node(obj);
|
||||
|
||||
if (nodep == NULL) {
|
||||
php_dom_throw_error(INVALID_STATE_ERR, 0);
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
nextsib = nodep->next;
|
||||
|
||||
while (nextsib != NULL && nextsib->type != XML_ELEMENT_NODE) {
|
||||
nextsib = nextsib->next;
|
||||
}
|
||||
|
||||
if (!nextsib) {
|
||||
ZVAL_NULL(retval);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
php_dom_create_object(nextsib, retval, obj);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ attributes DomNamedNodeMap
|
||||
readonly=yes
|
||||
URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-84CF096
|
||||
|
|
408
ext/dom/parentnode.c
Normal file
408
ext/dom/parentnode.c
Normal file
|
@ -0,0 +1,408 @@
|
|||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| PHP Version 7 |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) The PHP Group |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 3.01 of the PHP license, |
|
||||
| that is bundled with this package in the file LICENSE, and is |
|
||||
| available through the world-wide-web at the following url: |
|
||||
| http://www.php.net/license/3_01.txt |
|
||||
| If you did not receive a copy of the PHP license and are unable to |
|
||||
| obtain it through the world-wide-web, please send a note to |
|
||||
| license@php.net so we can mail you a copy immediately. |
|
||||
+----------------------------------------------------------------------+
|
||||
| Authors: Benjamin Eberlei <beberlei@php.net> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "php.h"
|
||||
#if HAVE_LIBXML && HAVE_DOM
|
||||
#include "php_dom.h"
|
||||
#include "dom_arginfo.h"
|
||||
|
||||
|
||||
/* {{{ DOMParentNode methods */
|
||||
const zend_function_entry php_dom_parent_node_class_functions[] = { /* {{{ */
|
||||
PHP_ABSTRACT_ME(DOMParentNode, append, arginfo_class_DOMParentNode_append)
|
||||
PHP_ABSTRACT_ME(DOMParentNode, prepend, arginfo_class_DOMParentNode_prepend)
|
||||
PHP_FE_END
|
||||
};
|
||||
/* }}} */
|
||||
|
||||
/* {{{ firstElementChild DomParentNode
|
||||
readonly=yes
|
||||
URL: https://www.w3.org/TR/dom/#dom-parentnode-firstelementchild
|
||||
*/
|
||||
int dom_parent_node_first_element_child_read(dom_object *obj, zval *retval)
|
||||
{
|
||||
xmlNode *nodep, *first = NULL;
|
||||
|
||||
nodep = dom_object_get_node(obj);
|
||||
|
||||
if (nodep == NULL) {
|
||||
php_dom_throw_error(INVALID_STATE_ERR, 0);
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
if (dom_node_children_valid(nodep) == SUCCESS) {
|
||||
first = nodep->children;
|
||||
|
||||
while (first && first->type != XML_ELEMENT_NODE) {
|
||||
first = first->next;
|
||||
}
|
||||
}
|
||||
|
||||
if (!first) {
|
||||
ZVAL_NULL(retval);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
php_dom_create_object(first, retval, obj);
|
||||
return SUCCESS;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ lastElementChild DomParentNode
|
||||
readonly=yes
|
||||
URL: https://www.w3.org/TR/dom/#dom-parentnode-lastelementchild
|
||||
*/
|
||||
int dom_parent_node_last_element_child_read(dom_object *obj, zval *retval)
|
||||
{
|
||||
xmlNode *nodep, *last = NULL;
|
||||
|
||||
nodep = dom_object_get_node(obj);
|
||||
|
||||
if (nodep == NULL) {
|
||||
php_dom_throw_error(INVALID_STATE_ERR, 0);
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
if (dom_node_children_valid(nodep) == SUCCESS) {
|
||||
last = nodep->last;
|
||||
|
||||
while (last && last->type != XML_ELEMENT_NODE) {
|
||||
last = last->prev;
|
||||
}
|
||||
}
|
||||
|
||||
if (!last) {
|
||||
ZVAL_NULL(retval);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
php_dom_create_object(last, retval, obj);
|
||||
return SUCCESS;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ childElementCount DomParentNode
|
||||
readonly=yes
|
||||
https://www.w3.org/TR/dom/#dom-parentnode-childelementcount
|
||||
*/
|
||||
int dom_parent_node_child_element_count(dom_object *obj, zval *retval)
|
||||
{
|
||||
xmlNode *nodep, *first = NULL;
|
||||
zend_long count = 0;
|
||||
|
||||
nodep = dom_object_get_node(obj);
|
||||
|
||||
if (nodep == NULL) {
|
||||
php_dom_throw_error(INVALID_STATE_ERR, 0);
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
if (dom_node_children_valid(nodep) == SUCCESS) {
|
||||
first = nodep->children;
|
||||
|
||||
while (first != NULL) {
|
||||
if (first->type == XML_ELEMENT_NODE) {
|
||||
count++;
|
||||
}
|
||||
|
||||
first = first->next;
|
||||
}
|
||||
}
|
||||
|
||||
ZVAL_LONG(retval, count);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
xmlNode* dom_zvals_to_fragment(php_libxml_ref_obj *document, xmlNode *contextNode, zval *nodes, int nodesc)
|
||||
{
|
||||
int i;
|
||||
xmlDoc *documentNode;
|
||||
xmlNode *fragment;
|
||||
xmlNode *newNode;
|
||||
zend_class_entry *ce;
|
||||
dom_object *newNodeObj;
|
||||
int stricterror;
|
||||
|
||||
if (contextNode->type == XML_DOCUMENT_NODE || contextNode->type == XML_HTML_DOCUMENT_NODE) {
|
||||
documentNode = (xmlDoc *) contextNode;
|
||||
} else {
|
||||
documentNode = contextNode->doc;
|
||||
}
|
||||
|
||||
fragment = xmlNewDocFragment(documentNode);
|
||||
|
||||
if (!fragment) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
stricterror = dom_get_strict_error(document);
|
||||
|
||||
for (i = 0; i < nodesc; i++) {
|
||||
if (Z_TYPE(nodes[i]) == IS_OBJECT) {
|
||||
ce = Z_OBJCE(nodes[i]);
|
||||
|
||||
if (instanceof_function(ce, dom_node_class_entry)) {
|
||||
newNodeObj = Z_DOMOBJ_P(&nodes[i]);
|
||||
newNode = dom_object_get_node(newNodeObj);
|
||||
|
||||
if (newNode->doc != documentNode) {
|
||||
php_dom_throw_error(WRONG_DOCUMENT_ERR, stricterror);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (newNode->parent != NULL) {
|
||||
xmlUnlinkNode(newNode);
|
||||
}
|
||||
|
||||
newNodeObj->document = document;
|
||||
xmlSetTreeDoc(newNode, documentNode);
|
||||
|
||||
if (!xmlAddChild(fragment, newNode)) {
|
||||
xmlFree(fragment);
|
||||
|
||||
php_dom_throw_error(HIERARCHY_REQUEST_ERR, stricterror);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
continue;
|
||||
} else {
|
||||
xmlFree(fragment);
|
||||
|
||||
zend_type_error("Invalid argument type must be either DOMNode or string");
|
||||
return NULL;
|
||||
}
|
||||
} else if (Z_TYPE(nodes[i]) == IS_STRING) {
|
||||
newNode = xmlNewDocText(documentNode, (xmlChar *) Z_STRVAL(nodes[i]));
|
||||
|
||||
xmlSetTreeDoc(newNode, documentNode);
|
||||
|
||||
if (!xmlAddChild(fragment, newNode)) {
|
||||
xmlFree(fragment);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
xmlFree(fragment);
|
||||
|
||||
zend_type_error("Invalid argument type must be either DOMNode or string");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return fragment;
|
||||
}
|
||||
|
||||
static void dom_fragment_assign_parent_node(xmlNodePtr parentNode, xmlNodePtr fragment)
|
||||
{
|
||||
xmlNodePtr node = fragment->children;
|
||||
|
||||
while (node != NULL) {
|
||||
node->parent = parentNode;
|
||||
|
||||
if (node == fragment->last) {
|
||||
break;
|
||||
}
|
||||
node = node->next;
|
||||
}
|
||||
|
||||
fragment->children = NULL;
|
||||
fragment->last = NULL;
|
||||
}
|
||||
|
||||
void dom_parent_node_append(dom_object *context, zval *nodes, int nodesc)
|
||||
{
|
||||
xmlNode *parentNode = dom_object_get_node(context);
|
||||
xmlNodePtr newchild, prevsib;
|
||||
xmlNode *fragment = dom_zvals_to_fragment(context->document, parentNode, nodes, nodesc);
|
||||
|
||||
if (fragment == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
newchild = fragment->children;
|
||||
prevsib = parentNode->last;
|
||||
|
||||
if (newchild) {
|
||||
if (prevsib != NULL) {
|
||||
prevsib->next = newchild;
|
||||
} else {
|
||||
parentNode->children = newchild;
|
||||
}
|
||||
|
||||
parentNode->last = fragment->last;
|
||||
|
||||
newchild->prev = prevsib;
|
||||
|
||||
dom_fragment_assign_parent_node(parentNode, fragment);
|
||||
|
||||
dom_reconcile_ns(parentNode->doc, newchild);
|
||||
}
|
||||
|
||||
xmlFree(fragment);
|
||||
}
|
||||
|
||||
void dom_parent_node_prepend(dom_object *context, zval *nodes, int nodesc)
|
||||
{
|
||||
xmlNode *parentNode = dom_object_get_node(context);
|
||||
|
||||
if (parentNode->children == NULL) {
|
||||
dom_parent_node_append(context, nodes, nodesc);
|
||||
return;
|
||||
}
|
||||
|
||||
xmlNodePtr newchild, nextsib;
|
||||
xmlNode *fragment = dom_zvals_to_fragment(context->document, parentNode, nodes, nodesc);
|
||||
|
||||
if (fragment == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
newchild = fragment->children;
|
||||
nextsib = parentNode->children;
|
||||
|
||||
if (newchild) {
|
||||
parentNode->children = newchild;
|
||||
fragment->last->next = nextsib;
|
||||
nextsib->prev = fragment->last;
|
||||
|
||||
dom_fragment_assign_parent_node(parentNode, fragment);
|
||||
|
||||
dom_reconcile_ns(parentNode->doc, newchild);
|
||||
}
|
||||
|
||||
xmlFree(fragment);
|
||||
}
|
||||
|
||||
void dom_parent_node_after(dom_object *context, zval *nodes, int nodesc)
|
||||
{
|
||||
xmlNode *prevsib = dom_object_get_node(context);
|
||||
xmlNodePtr newchild, parentNode;
|
||||
xmlNode *fragment;
|
||||
|
||||
int stricterror = dom_get_strict_error(context->document);
|
||||
|
||||
if (!prevsib->parent) {
|
||||
php_dom_throw_error(NO_MODIFICATION_ALLOWED_ERR, stricterror);
|
||||
return;
|
||||
}
|
||||
|
||||
parentNode = prevsib->parent;
|
||||
fragment = dom_zvals_to_fragment(context->document, parentNode, nodes, nodesc);
|
||||
|
||||
if (fragment == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
newchild = fragment->children;
|
||||
|
||||
if (newchild) {
|
||||
fragment->last->next = prevsib->next;
|
||||
prevsib->next = newchild;
|
||||
|
||||
newchild->prev = prevsib;
|
||||
|
||||
dom_fragment_assign_parent_node(parentNode, fragment);
|
||||
dom_reconcile_ns(prevsib->doc, newchild);
|
||||
}
|
||||
|
||||
xmlFree(fragment);
|
||||
}
|
||||
|
||||
void dom_parent_node_before(dom_object *context, zval *nodes, int nodesc)
|
||||
{
|
||||
xmlNode *nextsib = dom_object_get_node(context);
|
||||
xmlNodePtr newchild, prevsib, parentNode;
|
||||
xmlNode *fragment;
|
||||
|
||||
prevsib = nextsib->prev;
|
||||
parentNode = nextsib->parent;
|
||||
fragment = dom_zvals_to_fragment(context->document, parentNode, nodes, nodesc);
|
||||
|
||||
if (fragment == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
newchild = fragment->children;
|
||||
|
||||
if (newchild) {
|
||||
if (parentNode->children == nextsib) {
|
||||
parentNode->children = newchild;
|
||||
} else {
|
||||
prevsib->next = newchild;
|
||||
}
|
||||
fragment->last->next = nextsib;
|
||||
nextsib->prev = fragment->last;
|
||||
|
||||
newchild->prev = prevsib;
|
||||
|
||||
dom_fragment_assign_parent_node(parentNode, fragment);
|
||||
|
||||
dom_reconcile_ns(nextsib->doc, newchild);
|
||||
}
|
||||
|
||||
xmlFree(fragment);
|
||||
}
|
||||
|
||||
void dom_child_node_remove(dom_object *context)
|
||||
{
|
||||
xmlNode *child = dom_object_get_node(context);
|
||||
xmlNodePtr children;
|
||||
int stricterror;
|
||||
|
||||
if (dom_node_children_valid(child) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
stricterror = dom_get_strict_error(context->document);
|
||||
|
||||
if (dom_node_is_read_only(child) == SUCCESS ||
|
||||
(child->parent != NULL && dom_node_is_read_only(child->parent) == SUCCESS)) {
|
||||
php_dom_throw_error(NO_MODIFICATION_ALLOWED_ERR, stricterror);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!child->parent) {
|
||||
php_dom_throw_error(NOT_FOUND_ERR, stricterror);
|
||||
return;
|
||||
}
|
||||
|
||||
children = child->parent->children;
|
||||
if (!children) {
|
||||
php_dom_throw_error(NOT_FOUND_ERR, stricterror);
|
||||
return;
|
||||
}
|
||||
|
||||
while (children) {
|
||||
if (children == child) {
|
||||
xmlUnlinkNode(child);
|
||||
return;
|
||||
}
|
||||
children = children->next;
|
||||
}
|
||||
|
||||
php_dom_throw_error(NOT_FOUND_ERR, stricterror);
|
||||
}
|
||||
|
||||
#endif
|
|
@ -35,6 +35,8 @@
|
|||
/* {{{ class entries */
|
||||
PHP_DOM_EXPORT zend_class_entry *dom_node_class_entry;
|
||||
PHP_DOM_EXPORT zend_class_entry *dom_domexception_class_entry;
|
||||
PHP_DOM_EXPORT zend_class_entry *dom_parentnode_class_entry;
|
||||
PHP_DOM_EXPORT zend_class_entry *dom_childnode_class_entry;
|
||||
PHP_DOM_EXPORT zend_class_entry *dom_domimplementation_class_entry;
|
||||
PHP_DOM_EXPORT zend_class_entry *dom_documentfragment_class_entry;
|
||||
PHP_DOM_EXPORT zend_class_entry *dom_document_class_entry;
|
||||
|
@ -66,6 +68,7 @@ zend_object_handlers dom_xpath_object_handlers;
|
|||
static HashTable classes;
|
||||
/* {{{ prop handler tables */
|
||||
static HashTable dom_document_prop_handlers;
|
||||
static HashTable dom_documentfragment_prop_handlers;
|
||||
static HashTable dom_node_prop_handlers;
|
||||
static HashTable dom_nodelist_prop_handlers;
|
||||
static HashTable dom_namednodemap_prop_handlers;
|
||||
|
@ -585,6 +588,12 @@ PHP_MINIT_FUNCTION(dom)
|
|||
dom_domexception_class_entry->ce_flags |= ZEND_ACC_FINAL;
|
||||
zend_declare_property_long(dom_domexception_class_entry, "code", sizeof("code")-1, 0, ZEND_ACC_PUBLIC);
|
||||
|
||||
INIT_CLASS_ENTRY(ce, "DOMParentNode", php_dom_parent_node_class_functions);
|
||||
dom_parentnode_class_entry = zend_register_internal_interface(&ce);
|
||||
|
||||
INIT_CLASS_ENTRY(ce, "DOMChildNode", php_dom_child_node_class_functions);
|
||||
dom_childnode_class_entry = zend_register_internal_interface(&ce);
|
||||
|
||||
REGISTER_DOM_CLASS(ce, "DOMImplementation", NULL, php_dom_domimplementation_class_functions, dom_domimplementation_class_entry);
|
||||
|
||||
REGISTER_DOM_CLASS(ce, "DOMNode", NULL, php_dom_node_class_functions, dom_node_class_entry);
|
||||
|
@ -622,7 +631,15 @@ PHP_MINIT_FUNCTION(dom)
|
|||
zend_hash_add_ptr(&classes, ce.name, &dom_namespace_node_prop_handlers);
|
||||
|
||||
REGISTER_DOM_CLASS(ce, "DOMDocumentFragment", dom_node_class_entry, php_dom_documentfragment_class_functions, dom_documentfragment_class_entry);
|
||||
zend_hash_add_ptr(&classes, ce.name, &dom_node_prop_handlers);
|
||||
zend_hash_init(&dom_documentfragment_prop_handlers, 0, NULL, dom_dtor_prop_handler, 1);
|
||||
|
||||
dom_register_prop_handler(&dom_documentfragment_prop_handlers, "firstElementChild", sizeof("firstElementChild")-1, dom_parent_node_first_element_child_read, NULL);
|
||||
dom_register_prop_handler(&dom_documentfragment_prop_handlers, "lastElementChild", sizeof("lastElementChild")-1, dom_parent_node_last_element_child_read, NULL);
|
||||
dom_register_prop_handler(&dom_documentfragment_prop_handlers, "childElementCount", sizeof("childElementCount")-1, dom_parent_node_child_element_count, NULL);
|
||||
|
||||
zend_hash_merge(&dom_documentfragment_prop_handlers, &dom_node_prop_handlers, dom_copy_prop_handler, 0);
|
||||
zend_hash_add_ptr(&classes, ce.name, &dom_documentfragment_prop_handlers);
|
||||
zend_class_implements(dom_documentfragment_class_entry, 1, dom_parentnode_class_entry);
|
||||
|
||||
REGISTER_DOM_CLASS(ce, "DOMDocument", dom_node_class_entry, php_dom_document_class_functions, dom_document_class_entry);
|
||||
zend_hash_init(&dom_document_prop_handlers, 0, NULL, dom_dtor_prop_handler, 1);
|
||||
|
@ -646,8 +663,13 @@ PHP_MINIT_FUNCTION(dom)
|
|||
dom_register_prop_handler(&dom_document_prop_handlers, "recover", sizeof("recover")-1, dom_document_recover_read, dom_document_recover_write);
|
||||
dom_register_prop_handler(&dom_document_prop_handlers, "substituteEntities", sizeof("substituteEntities")-1, dom_document_substitue_entities_read, dom_document_substitue_entities_write);
|
||||
|
||||
dom_register_prop_handler(&dom_document_prop_handlers, "firstElementChild", sizeof("firstElementChild")-1, dom_parent_node_first_element_child_read, NULL);
|
||||
dom_register_prop_handler(&dom_document_prop_handlers, "lastElementChild", sizeof("lastElementChild")-1, dom_parent_node_last_element_child_read, NULL);
|
||||
dom_register_prop_handler(&dom_document_prop_handlers, "childElementCount", sizeof("childElementCount")-1, dom_parent_node_child_element_count, NULL);
|
||||
|
||||
zend_hash_merge(&dom_document_prop_handlers, &dom_node_prop_handlers, dom_copy_prop_handler, 0);
|
||||
zend_hash_add_ptr(&classes, ce.name, &dom_document_prop_handlers);
|
||||
zend_class_implements(dom_document_class_entry, 1, dom_parentnode_class_entry);
|
||||
|
||||
INIT_CLASS_ENTRY(ce, "DOMNodeList", php_dom_nodelist_class_functions);
|
||||
ce.create_object = dom_nnodemap_objects_new;
|
||||
|
@ -674,9 +696,13 @@ PHP_MINIT_FUNCTION(dom)
|
|||
zend_hash_init(&dom_characterdata_prop_handlers, 0, NULL, dom_dtor_prop_handler, 1);
|
||||
dom_register_prop_handler(&dom_characterdata_prop_handlers, "data", sizeof("data")-1, dom_characterdata_data_read, dom_characterdata_data_write);
|
||||
dom_register_prop_handler(&dom_characterdata_prop_handlers, "length", sizeof("length")-1, dom_characterdata_length_read, NULL);
|
||||
dom_register_prop_handler(&dom_characterdata_prop_handlers, "previousElementSibling", sizeof("previousElementSibling")-1, dom_node_previous_element_sibling_read, NULL);
|
||||
dom_register_prop_handler(&dom_characterdata_prop_handlers, "nextElementSibling", sizeof("nextElementSibling")-1, dom_node_next_element_sibling_read, NULL);
|
||||
zend_hash_merge(&dom_characterdata_prop_handlers, &dom_node_prop_handlers, dom_copy_prop_handler, 0);
|
||||
zend_hash_add_ptr(&classes, ce.name, &dom_characterdata_prop_handlers);
|
||||
|
||||
zend_class_implements(dom_characterdata_class_entry, 1, dom_childnode_class_entry);
|
||||
|
||||
REGISTER_DOM_CLASS(ce, "DOMAttr", dom_node_class_entry, php_dom_attr_class_functions, dom_attr_class_entry);
|
||||
|
||||
zend_hash_init(&dom_attr_prop_handlers, 0, NULL, dom_dtor_prop_handler, 1);
|
||||
|
@ -693,9 +719,16 @@ PHP_MINIT_FUNCTION(dom)
|
|||
zend_hash_init(&dom_element_prop_handlers, 0, NULL, dom_dtor_prop_handler, 1);
|
||||
dom_register_prop_handler(&dom_element_prop_handlers, "tagName", sizeof("tagName")-1, dom_element_tag_name_read, NULL);
|
||||
dom_register_prop_handler(&dom_element_prop_handlers, "schemaTypeInfo", sizeof("schemaTypeInfo")-1, dom_element_schema_type_info_read, NULL);
|
||||
dom_register_prop_handler(&dom_element_prop_handlers, "firstElementChild", sizeof("firstElementChild")-1, dom_parent_node_first_element_child_read, NULL);
|
||||
dom_register_prop_handler(&dom_element_prop_handlers, "lastElementChild", sizeof("lastElementChild")-1, dom_parent_node_last_element_child_read, NULL);
|
||||
dom_register_prop_handler(&dom_element_prop_handlers, "childElementCount", sizeof("childElementCount")-1, dom_parent_node_child_element_count, NULL);
|
||||
dom_register_prop_handler(&dom_element_prop_handlers, "previousElementSibling", sizeof("previousElementSibling")-1, dom_node_previous_element_sibling_read, NULL);
|
||||
dom_register_prop_handler(&dom_element_prop_handlers, "nextElementSibling", sizeof("nextElementSibling")-1, dom_node_next_element_sibling_read, NULL);
|
||||
zend_hash_merge(&dom_element_prop_handlers, &dom_node_prop_handlers, dom_copy_prop_handler, 0);
|
||||
zend_hash_add_ptr(&classes, ce.name, &dom_element_prop_handlers);
|
||||
|
||||
zend_class_implements(dom_element_class_entry, 2, dom_parentnode_class_entry, dom_childnode_class_entry);
|
||||
|
||||
REGISTER_DOM_CLASS(ce, "DOMText", dom_characterdata_class_entry, php_dom_text_class_functions, dom_text_class_entry);
|
||||
|
||||
zend_hash_init(&dom_text_prop_handlers, 0, NULL, dom_dtor_prop_handler, 1);
|
||||
|
@ -851,6 +884,7 @@ PHP_MINFO_FUNCTION(dom)
|
|||
PHP_MSHUTDOWN_FUNCTION(dom) /* {{{ */
|
||||
{
|
||||
zend_hash_destroy(&dom_document_prop_handlers);
|
||||
zend_hash_destroy(&dom_documentfragment_prop_handlers);
|
||||
zend_hash_destroy(&dom_node_prop_handlers);
|
||||
zend_hash_destroy(&dom_namespace_node_prop_handlers);
|
||||
zend_hash_destroy(&dom_nodelist_prop_handlers);
|
||||
|
@ -1344,6 +1378,38 @@ void dom_set_old_ns(xmlDoc *doc, xmlNs *ns) {
|
|||
}
|
||||
/* }}} end dom_set_old_ns */
|
||||
|
||||
void dom_reconcile_ns(xmlDocPtr doc, xmlNodePtr nodep) /* {{{ */
|
||||
{
|
||||
xmlNsPtr nsptr, nsdftptr, curns, prevns = NULL;
|
||||
|
||||
if (nodep->type == XML_ELEMENT_NODE) {
|
||||
/* Following if block primarily used for inserting nodes created via createElementNS */
|
||||
if (nodep->nsDef != NULL) {
|
||||
curns = nodep->nsDef;
|
||||
while (curns) {
|
||||
nsdftptr = curns->next;
|
||||
if (curns->href != NULL) {
|
||||
if((nsptr = xmlSearchNsByHref(doc, nodep->parent, curns->href)) &&
|
||||
(curns->prefix == NULL || xmlStrEqual(nsptr->prefix, curns->prefix))) {
|
||||
curns->next = NULL;
|
||||
if (prevns == NULL) {
|
||||
nodep->nsDef = nsdftptr;
|
||||
} else {
|
||||
prevns->next = nsdftptr;
|
||||
}
|
||||
dom_set_old_ns(doc, curns);
|
||||
curns = prevns;
|
||||
}
|
||||
}
|
||||
prevns = curns;
|
||||
curns = nsdftptr;
|
||||
}
|
||||
}
|
||||
xmlReconciliateNs(doc, nodep);
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/*
|
||||
http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/core.html#ID-DocCrElNS
|
||||
|
||||
|
|
|
@ -109,6 +109,7 @@ void node_list_unlink(xmlNodePtr node);
|
|||
int dom_check_qname(char *qname, char **localname, char **prefix, int uri_len, int name_len);
|
||||
xmlNsPtr dom_get_ns(xmlNodePtr node, char *uri, int *errorcode, char *prefix);
|
||||
void dom_set_old_ns(xmlDoc *doc, xmlNs *ns);
|
||||
void dom_reconcile_ns(xmlDocPtr doc, xmlNodePtr nodep);
|
||||
xmlNsPtr dom_get_nsdecl(xmlNode *node, xmlChar *localName);
|
||||
void dom_normalize (xmlNodePtr nodep);
|
||||
xmlNode *dom_get_elements_by_tag_name_ns_raw(xmlNodePtr nodep, char *ns, char *local, int *cur, int index);
|
||||
|
@ -125,6 +126,12 @@ xmlNode *php_dom_libxml_notation_iter(xmlHashTable *ht, int index);
|
|||
zend_object_iterator *php_dom_get_iterator(zend_class_entry *ce, zval *object, int by_ref);
|
||||
void dom_set_doc_classmap(php_libxml_ref_obj *document, zend_class_entry *basece, zend_class_entry *ce);
|
||||
|
||||
void dom_parent_node_prepend(dom_object *context, zval *nodes, int nodesc);
|
||||
void dom_parent_node_append(dom_object *context, zval *nodes, int nodesc);
|
||||
void dom_parent_node_after(dom_object *context, zval *nodes, int nodesc);
|
||||
void dom_parent_node_before(dom_object *context, zval *nodes, int nodesc);
|
||||
void dom_child_node_remove(dom_object *context);
|
||||
|
||||
#define REGISTER_DOM_CLASS(ce, name, parent_ce, funcs, entry) \
|
||||
INIT_CLASS_ENTRY(ce, name, funcs); \
|
||||
ce.create_object = dom_objects_new; \
|
||||
|
|
41
ext/dom/tests/DOM4_ChildNode_wrong_document.phpt
Normal file
41
ext/dom/tests/DOM4_ChildNode_wrong_document.phpt
Normal file
|
@ -0,0 +1,41 @@
|
|||
--TEST--
|
||||
DOMChildNode::after(), before, replaceWith with DOMNode from wrong document throws exception
|
||||
--SKIPIF--
|
||||
<?php require_once('skipif.inc'); ?>
|
||||
--FILE--
|
||||
<?php
|
||||
require_once("dom_test.inc");
|
||||
|
||||
$dom1 = new DOMDocument;
|
||||
$dom1->loadXML('<test/>');
|
||||
|
||||
$dom2 = new DOMDocument;
|
||||
$dom2->loadXML('<test><foo /></test>');
|
||||
|
||||
$element = $dom1->documentElement;
|
||||
|
||||
try {
|
||||
$element->after($dom2->documentElement->firstChild);
|
||||
echo "FAIL";
|
||||
} catch (DOMException $e) {
|
||||
echo $e->getMessage() . "\n";
|
||||
}
|
||||
|
||||
try {
|
||||
$element->before($dom2->documentElement->firstChild);
|
||||
echo "FAIL";
|
||||
} catch (DOMException $e) {
|
||||
echo $e->getMessage() . "\n";
|
||||
}
|
||||
|
||||
try {
|
||||
$element->replaceWith($dom2->documentElement->firstChild);
|
||||
echo "FAIL";
|
||||
} catch (DOMException $e) {
|
||||
echo $e->getMessage();
|
||||
}
|
||||
?>
|
||||
--EXPECT--
|
||||
Wrong Document Error
|
||||
Wrong Document Error
|
||||
Wrong Document Error
|
25
ext/dom/tests/DOM4_DOMNode_ElementSiblings.phpt
Normal file
25
ext/dom/tests/DOM4_DOMNode_ElementSiblings.phpt
Normal file
|
@ -0,0 +1,25 @@
|
|||
--TEST--
|
||||
DOMNode: Element Siblings
|
||||
--SKIPIF--
|
||||
<?php require_once('skipif.inc'); ?>
|
||||
--FILE--
|
||||
<?php
|
||||
require_once("dom_test.inc");
|
||||
|
||||
$dom = new DOMDocument;
|
||||
$dom->loadXML('<test>foo<bar>FirstElement</bar><bar>LastElement</bar>bar</test>');
|
||||
|
||||
$element = $dom->documentElement;
|
||||
print_node($element->firstElementChild->nextElementSibling);
|
||||
print_node($element->lastElementChild->previousElementSibling);
|
||||
?>
|
||||
--EXPECT--
|
||||
Node Name: bar
|
||||
Node Type: 1
|
||||
Num Children: 1
|
||||
Node Content: LastElement
|
||||
|
||||
Node Name: bar
|
||||
Node Type: 1
|
||||
Num Children: 1
|
||||
Node Content: FirstElement
|
35
ext/dom/tests/DOM4_DOMNode_after.phpt
Normal file
35
ext/dom/tests/DOM4_DOMNode_after.phpt
Normal file
|
@ -0,0 +1,35 @@
|
|||
--TEST--
|
||||
DOMNode::after()
|
||||
--SKIPIF--
|
||||
<?php require_once('skipif.inc'); ?>
|
||||
--FILE--
|
||||
<?php
|
||||
require_once("dom_test.inc");
|
||||
|
||||
$dom = new DOMDocument;
|
||||
$dom->loadXML('<test><mark>first</mark><mark>second</mark></test>');
|
||||
|
||||
$element = $dom->documentElement->firstElementChild;
|
||||
$secondMark = $dom->documentElement->lastElementChild;
|
||||
|
||||
$element->after(
|
||||
'text inserted after',
|
||||
$dom->createElement('inserted-after', 'content')
|
||||
);
|
||||
|
||||
$secondMark->after('text inserted after second');
|
||||
|
||||
print_node_list_compact($dom->documentElement->childNodes);
|
||||
?>
|
||||
--EXPECT--
|
||||
<mark>
|
||||
first
|
||||
</mark>
|
||||
text inserted after
|
||||
<inserted-after>
|
||||
content
|
||||
</inserted-after>
|
||||
<mark>
|
||||
second
|
||||
</mark>
|
||||
text inserted after second
|
29
ext/dom/tests/DOM4_DOMNode_after_ns.phpt
Normal file
29
ext/dom/tests/DOM4_DOMNode_after_ns.phpt
Normal file
|
@ -0,0 +1,29 @@
|
|||
--TEST--
|
||||
DOMNode::after() with namespace
|
||||
--SKIPIF--
|
||||
<?php require_once('skipif.inc'); ?>
|
||||
--FILE--
|
||||
<?php
|
||||
require_once("dom_test.inc");
|
||||
|
||||
$doc = new DOMDocument('1.0', 'utf-8');
|
||||
$doc->formatOutput = true;
|
||||
|
||||
$root = $doc->createElementNS('http://www.w3.org/2005/Atom', 'element');
|
||||
$doc->appendChild($root);
|
||||
$root->setAttributeNS('http://www.w3.org/2000/xmlns/' ,'xmlns:g', 'http://base.google.com/ns/1.0');
|
||||
|
||||
$item = $doc->createElementNS('http://base.google.com/ns/1.0', 'g:item_type', 'house');
|
||||
$root->append($item);
|
||||
|
||||
$item2 = $doc->createElementNS('http://base.google.com/ns/1.0', 'g:item_type', 'street');
|
||||
$item->after($item2);
|
||||
|
||||
echo $doc->saveXML(), "\n";
|
||||
?>
|
||||
--EXPECT--
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<element xmlns="http://www.w3.org/2005/Atom" xmlns:g="http://base.google.com/ns/1.0">
|
||||
<g:item_type>house</g:item_type>
|
||||
<g:item_type>street</g:item_type>
|
||||
</element>
|
25
ext/dom/tests/DOM4_DOMNode_append_ns.phpt
Normal file
25
ext/dom/tests/DOM4_DOMNode_append_ns.phpt
Normal file
|
@ -0,0 +1,25 @@
|
|||
--TEST--
|
||||
DOMNode::append() with namespace
|
||||
--SKIPIF--
|
||||
<?php require_once('skipif.inc'); ?>
|
||||
--FILE--
|
||||
<?php
|
||||
require_once("dom_test.inc");
|
||||
|
||||
$doc = new DOMDocument('1.0', 'utf-8');
|
||||
$doc->formatOutput = true;
|
||||
|
||||
$root = $doc->createElementNS('http://www.w3.org/2005/Atom', 'element');
|
||||
$doc->appendChild($root);
|
||||
$root->setAttributeNS('http://www.w3.org/2000/xmlns/' ,'xmlns:g', 'http://base.google.com/ns/1.0');
|
||||
|
||||
$item = $doc->createElementNS('http://base.google.com/ns/1.0', 'g:item_type', 'house');
|
||||
$root->append($item);
|
||||
|
||||
echo $doc->saveXML(), "\n";
|
||||
?>
|
||||
--EXPECT--
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<element xmlns="http://www.w3.org/2005/Atom" xmlns:g="http://base.google.com/ns/1.0">
|
||||
<g:item_type>house</g:item_type>
|
||||
</element>
|
35
ext/dom/tests/DOM4_DOMNode_before.phpt
Normal file
35
ext/dom/tests/DOM4_DOMNode_before.phpt
Normal file
|
@ -0,0 +1,35 @@
|
|||
--TEST--
|
||||
DOMNode::before()
|
||||
--SKIPIF--
|
||||
<?php require_once('skipif.inc'); ?>
|
||||
--FILE--
|
||||
<?php
|
||||
require_once("dom_test.inc");
|
||||
|
||||
$dom = new DOMDocument;
|
||||
$dom->loadXML('<test><mark>first</mark><mark>second</mark></test>');
|
||||
|
||||
$element = $dom->documentElement->firstElementChild;
|
||||
$secondMark = $dom->documentElement->lastElementChild;
|
||||
|
||||
$element->before(
|
||||
$dom->createElement('inserted-before', 'content'),
|
||||
'text inserted before'
|
||||
);
|
||||
|
||||
$secondMark->before('text inserted before second');
|
||||
|
||||
print_node_list_compact($dom->documentElement->childNodes);
|
||||
?>
|
||||
--EXPECT--
|
||||
<inserted-before>
|
||||
content
|
||||
</inserted-before>
|
||||
text inserted before
|
||||
<mark>
|
||||
first
|
||||
</mark>
|
||||
text inserted before second
|
||||
<mark>
|
||||
second
|
||||
</mark>
|
29
ext/dom/tests/DOM4_DOMNode_before_ns.phpt
Normal file
29
ext/dom/tests/DOM4_DOMNode_before_ns.phpt
Normal file
|
@ -0,0 +1,29 @@
|
|||
--TEST--
|
||||
DOMNode::before() with namespace
|
||||
--SKIPIF--
|
||||
<?php require_once('skipif.inc'); ?>
|
||||
--FILE--
|
||||
<?php
|
||||
require_once("dom_test.inc");
|
||||
|
||||
$doc = new DOMDocument('1.0', 'utf-8');
|
||||
$doc->formatOutput = true;
|
||||
|
||||
$root = $doc->createElementNS('http://www.w3.org/2005/Atom', 'element');
|
||||
$doc->appendChild($root);
|
||||
$root->setAttributeNS('http://www.w3.org/2000/xmlns/' ,'xmlns:g', 'http://base.google.com/ns/1.0');
|
||||
|
||||
$item = $doc->createElementNS('http://base.google.com/ns/1.0', 'g:item_type', 'house');
|
||||
$root->append($item);
|
||||
|
||||
$item2 = $doc->createElementNS('http://base.google.com/ns/1.0', 'g:item_type', 'street');
|
||||
$item->before($item2);
|
||||
|
||||
echo $doc->saveXML(), "\n";
|
||||
?>
|
||||
--EXPECT--
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<element xmlns="http://www.w3.org/2005/Atom" xmlns:g="http://base.google.com/ns/1.0">
|
||||
<g:item_type>street</g:item_type>
|
||||
<g:item_type>house</g:item_type>
|
||||
</element>
|
25
ext/dom/tests/DOM4_DOMNode_prepend_ns.phpt
Normal file
25
ext/dom/tests/DOM4_DOMNode_prepend_ns.phpt
Normal file
|
@ -0,0 +1,25 @@
|
|||
--TEST--
|
||||
DOMNode::prepend() with namespace
|
||||
--SKIPIF--
|
||||
<?php require_once('skipif.inc'); ?>
|
||||
--FILE--
|
||||
<?php
|
||||
require_once("dom_test.inc");
|
||||
|
||||
$doc = new DOMDocument('1.0', 'utf-8');
|
||||
$doc->formatOutput = true;
|
||||
|
||||
$root = $doc->createElementNS('http://www.w3.org/2005/Atom', 'element');
|
||||
$doc->appendChild($root);
|
||||
$root->setAttributeNS('http://www.w3.org/2000/xmlns/' ,'xmlns:g', 'http://base.google.com/ns/1.0');
|
||||
|
||||
$item = $doc->createElementNS('http://base.google.com/ns/1.0', 'g:item_type', 'house');
|
||||
$root->prepend($item);
|
||||
|
||||
echo $doc->saveXML(), "\n";
|
||||
?>
|
||||
--EXPECT--
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<element xmlns="http://www.w3.org/2005/Atom" xmlns:g="http://base.google.com/ns/1.0">
|
||||
<g:item_type>house</g:item_type>
|
||||
</element>
|
30
ext/dom/tests/DOM4_DOMNode_remove.phpt
Normal file
30
ext/dom/tests/DOM4_DOMNode_remove.phpt
Normal file
|
@ -0,0 +1,30 @@
|
|||
--TEST--
|
||||
DOMNode::remove()
|
||||
--SKIPIF--
|
||||
<?php require_once('skipif.inc'); ?>
|
||||
--FILE--
|
||||
<?php
|
||||
require_once("dom_test.inc");
|
||||
|
||||
$dom = new DOMDocument;
|
||||
$dom->loadXML('<test><one>first</one><two>second</two></test>');
|
||||
|
||||
$element = $dom->documentElement;
|
||||
print_node($element->firstChild);
|
||||
$returnValue = $element->firstChild->remove();
|
||||
print_node($element->firstChild);
|
||||
var_dump($returnValue);
|
||||
?>
|
||||
--EXPECT--
|
||||
Node Name: one
|
||||
Node Type: 1
|
||||
Num Children: 1
|
||||
Node Content: first
|
||||
|
||||
Node Name: two
|
||||
Node Type: 1
|
||||
Num Children: 1
|
||||
Node Content: second
|
||||
|
||||
NULL
|
||||
|
18
ext/dom/tests/DOM4_DOMNode_removeDanglingElement.phpt
Normal file
18
ext/dom/tests/DOM4_DOMNode_removeDanglingElement.phpt
Normal file
|
@ -0,0 +1,18 @@
|
|||
--TEST--
|
||||
DOMNode::remove() dangling element
|
||||
--SKIPIF--
|
||||
<?php require_once('skipif.inc'); ?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$dom = new DOMDocument();
|
||||
|
||||
$element = $dom->createElement('test');
|
||||
|
||||
try {
|
||||
$element->remove();
|
||||
} catch (DOMException $e) {
|
||||
echo $e->getMessage();
|
||||
}
|
||||
--EXPECT--
|
||||
Not Found Error
|
27
ext/dom/tests/DOM4_DOMNode_replaceWith.phpt
Normal file
27
ext/dom/tests/DOM4_DOMNode_replaceWith.phpt
Normal file
|
@ -0,0 +1,27 @@
|
|||
--TEST--
|
||||
DOMNode::replaceWith()
|
||||
--SKIPIF--
|
||||
<?php require_once('skipif.inc'); ?>
|
||||
--FILE--
|
||||
<?php
|
||||
require_once("dom_test.inc");
|
||||
|
||||
$dom = new DOMDocument;
|
||||
$dom->loadXML('<test><mark>first</mark><mark>second</mark></test>');
|
||||
|
||||
$element = $dom->documentElement->firstChild;
|
||||
$element->replaceWith(
|
||||
$dom->createElement('element', 'content'),
|
||||
'content'
|
||||
);
|
||||
|
||||
print_node_list_compact($dom->documentElement->childNodes);
|
||||
?>
|
||||
--EXPECT--
|
||||
<element>
|
||||
content
|
||||
</element>
|
||||
content
|
||||
<mark>
|
||||
second
|
||||
</mark>
|
51
ext/dom/tests/DOM4_ParentNode.phpt
Normal file
51
ext/dom/tests/DOM4_ParentNode.phpt
Normal file
|
@ -0,0 +1,51 @@
|
|||
--TEST--
|
||||
DOMParentNode: Child Element Handling
|
||||
--SKIPIF--
|
||||
<?php require_once('skipif.inc'); ?>
|
||||
--FILE--
|
||||
<?php
|
||||
require_once("dom_test.inc");
|
||||
|
||||
$dom = new DOMDocument;
|
||||
$dom->loadXML('<test>foo<bar>FirstElement</bar><bar>LastElement</bar>bar</test>');
|
||||
|
||||
var_dump($dom instanceof DOMParentNode);
|
||||
print_node($dom->firstElementChild);
|
||||
print_node($dom->lastElementChild);
|
||||
var_dump($dom->childElementCount);
|
||||
|
||||
$element = $dom->documentElement;
|
||||
var_dump($element instanceof DOMParentNode);
|
||||
print_node($element->firstElementChild);
|
||||
print_node($element->lastElementChild);
|
||||
var_dump($element->childElementCount);
|
||||
var_dump($element->lastElementChild->firstElementChild);
|
||||
var_dump($element->lastElementChild->lastElementChild);
|
||||
var_dump($element->lastElementChild->childElementCount);
|
||||
?>
|
||||
--EXPECT--
|
||||
bool(true)
|
||||
Node Name: test
|
||||
Node Type: 1
|
||||
Num Children: 4
|
||||
|
||||
Node Name: test
|
||||
Node Type: 1
|
||||
Num Children: 4
|
||||
|
||||
int(1)
|
||||
bool(true)
|
||||
Node Name: bar
|
||||
Node Type: 1
|
||||
Num Children: 1
|
||||
Node Content: FirstElement
|
||||
|
||||
Node Name: bar
|
||||
Node Type: 1
|
||||
Num Children: 1
|
||||
Node Content: LastElement
|
||||
|
||||
int(2)
|
||||
NULL
|
||||
NULL
|
||||
int(0)
|
41
ext/dom/tests/DOM4_ParentNode_Fragment.phpt
Normal file
41
ext/dom/tests/DOM4_ParentNode_Fragment.phpt
Normal file
|
@ -0,0 +1,41 @@
|
|||
--TEST--
|
||||
DOMParentNode: Child Element Handling
|
||||
--SKIPIF--
|
||||
<?php require_once('skipif.inc'); ?>
|
||||
--FILE--
|
||||
<?php
|
||||
require_once("dom_test.inc");
|
||||
|
||||
$dom = new DOMDocument;
|
||||
$dom->loadXML('<test></test>');
|
||||
|
||||
$fragment = $dom->createDocumentFragment();
|
||||
$fragment->appendChild($dom->createTextNode('foo'));
|
||||
$fragment->appendChild($dom->createElement('bar', 'FirstElement'));
|
||||
$fragment->appendChild($dom->createElement('bar', 'LastElement'));
|
||||
$fragment->appendChild($dom->createTextNode('bar'));
|
||||
|
||||
var_dump($fragment instanceof DOMParentNode);
|
||||
print_node($fragment->firstElementChild);
|
||||
print_node($fragment->lastElementChild);
|
||||
var_dump($fragment->childElementCount);
|
||||
var_dump($fragment->lastElementChild->firstElementChild);
|
||||
var_dump($fragment->lastElementChild->lastElementChild);
|
||||
var_dump($fragment->lastElementChild->childElementCount);
|
||||
?>
|
||||
--EXPECT--
|
||||
bool(true)
|
||||
Node Name: bar
|
||||
Node Type: 1
|
||||
Num Children: 1
|
||||
Node Content: FirstElement
|
||||
|
||||
Node Name: bar
|
||||
Node Type: 1
|
||||
Num Children: 1
|
||||
Node Content: LastElement
|
||||
|
||||
int(2)
|
||||
NULL
|
||||
NULL
|
||||
int(0)
|
41
ext/dom/tests/DOM4_ParentNode_append.phpt
Normal file
41
ext/dom/tests/DOM4_ParentNode_append.phpt
Normal file
|
@ -0,0 +1,41 @@
|
|||
--TEST--
|
||||
DOMParentNode::append()
|
||||
--SKIPIF--
|
||||
<?php require_once('skipif.inc'); ?>
|
||||
--FILE--
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
require_once("dom_test.inc");
|
||||
|
||||
$dom = new DOMDocument;
|
||||
$dom->loadXML('<test><mark/><mark /><mark /></test>');
|
||||
|
||||
$element = $dom->documentElement;
|
||||
$element->append(
|
||||
$dom->createElement('element', 'content'),
|
||||
'content'
|
||||
);
|
||||
|
||||
var_dump($dom->documentElement->childElementCount);
|
||||
print_node_list_compact($element->childNodes);
|
||||
|
||||
$element->append(
|
||||
$dom->createElement('element', 'content'),
|
||||
'content'
|
||||
);
|
||||
var_dump($dom->documentElement->childElementCount);
|
||||
?>
|
||||
--EXPECT--
|
||||
int(4)
|
||||
<mark>
|
||||
</mark>
|
||||
<mark>
|
||||
</mark>
|
||||
<mark>
|
||||
</mark>
|
||||
<element>
|
||||
content
|
||||
</element>
|
||||
content
|
||||
int(5)
|
18
ext/dom/tests/DOM4_ParentNode_append_invalidtypes.phpt
Normal file
18
ext/dom/tests/DOM4_ParentNode_append_invalidtypes.phpt
Normal file
|
@ -0,0 +1,18 @@
|
|||
--TEST--
|
||||
DOMParentNode::append() exception on invalid argument
|
||||
--SKIPIF--
|
||||
<?php require_once('skipif.inc'); ?>
|
||||
--FILE--
|
||||
<?php
|
||||
require_once("dom_test.inc");
|
||||
|
||||
$dom = new DOMDocument;
|
||||
$dom->loadXML('<test />');
|
||||
|
||||
try {
|
||||
$dom->documentElement->append(array());
|
||||
} catch(TypeError $e) {
|
||||
echo "OK! {$e->getMessage()}";
|
||||
}
|
||||
--EXPECT--
|
||||
OK! Invalid argument type must be either DOMNode or string
|
26
ext/dom/tests/DOM4_ParentNode_append_with_attributes.phpt
Normal file
26
ext/dom/tests/DOM4_ParentNode_append_with_attributes.phpt
Normal file
|
@ -0,0 +1,26 @@
|
|||
--TEST--
|
||||
DOMParentNode::append() with attributes
|
||||
--SKIPIF--
|
||||
<?php require_once('skipif.inc'); ?>
|
||||
--FILE--
|
||||
<?php
|
||||
require_once("dom_test.inc");
|
||||
|
||||
$dom = new DOMDocument;
|
||||
$dom->loadXML('<test attr-one="21"/>');
|
||||
|
||||
$replacement = $dom->createAttribute('attr-one');
|
||||
$replacement->value ='42';
|
||||
$addition = $dom->createAttribute('attr-two');
|
||||
$addition->value = '23';
|
||||
|
||||
$element = $dom->documentElement;
|
||||
|
||||
try {
|
||||
$element->append($replacement, $addition);
|
||||
} catch (DOMException $e) {
|
||||
echo $e->getMessage();
|
||||
}
|
||||
?>
|
||||
--EXPECT--
|
||||
Hierarchy Request Error
|
33
ext/dom/tests/DOM4_ParentNode_append_wrong_document.phpt
Normal file
33
ext/dom/tests/DOM4_ParentNode_append_wrong_document.phpt
Normal file
|
@ -0,0 +1,33 @@
|
|||
--TEST--
|
||||
DOMParentNode::append() with DOMNode from wrong document throws exception
|
||||
--SKIPIF--
|
||||
<?php require_once('skipif.inc'); ?>
|
||||
--FILE--
|
||||
<?php
|
||||
require_once("dom_test.inc");
|
||||
|
||||
$dom1 = new DOMDocument;
|
||||
$dom1->loadXML('<test/>');
|
||||
|
||||
$dom2 = new DOMDocument;
|
||||
$dom2->loadXML('<test><foo /></test>');
|
||||
|
||||
$element = $dom1->documentElement;
|
||||
|
||||
try {
|
||||
$element->append($dom2->documentElement->firstChild);
|
||||
echo "FAIL";
|
||||
} catch (DOMException $e) {
|
||||
echo $e->getMessage() . "\n";
|
||||
}
|
||||
|
||||
try {
|
||||
$element->prepend($dom2->documentElement->firstChild);
|
||||
echo "FAIL";
|
||||
} catch (DOMException $e) {
|
||||
echo $e->getMessage();
|
||||
}
|
||||
?>
|
||||
--EXPECT--
|
||||
Wrong Document Error
|
||||
Wrong Document Error
|
49
ext/dom/tests/DOM4_ParentNode_prepend.phpt
Normal file
49
ext/dom/tests/DOM4_ParentNode_prepend.phpt
Normal file
|
@ -0,0 +1,49 @@
|
|||
--TEST--
|
||||
DOMParentNode::prepend()
|
||||
--SKIPIF--
|
||||
<?php require_once('skipif.inc'); ?>
|
||||
--FILE--
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
require_once("dom_test.inc");
|
||||
|
||||
$dom = new DOMDocument;
|
||||
$dom->loadXML('<test><mark/><mark><nested /></mark><mark/></test>');
|
||||
|
||||
$element = $dom->documentElement;
|
||||
$firstMark = $element->childNodes[0];
|
||||
$element->prepend(
|
||||
$dom->createElement('element', 'content'),
|
||||
'content'
|
||||
);
|
||||
|
||||
var_dump($element->childElementCount);
|
||||
print_node_list_compact($element->childNodes);
|
||||
|
||||
$element = $dom->documentElement;
|
||||
$element->prepend(
|
||||
$dom->createElement('element', 'content'),
|
||||
'content'
|
||||
);
|
||||
var_dump($element->childElementCount);
|
||||
|
||||
$firstMark->prepend('content');
|
||||
print_node_list_compact($firstMark->childNodes);
|
||||
?>
|
||||
--EXPECT--
|
||||
int(4)
|
||||
<element>
|
||||
content
|
||||
</element>
|
||||
content
|
||||
<mark>
|
||||
</mark>
|
||||
<mark>
|
||||
<nested>
|
||||
</nested>
|
||||
</mark>
|
||||
<mark>
|
||||
</mark>
|
||||
int(5)
|
||||
content
|
|
@ -30,7 +30,7 @@ foreach ($dataNodes AS $node) {
|
|||
?>
|
||||
--EXPECTF--
|
||||
int(3)
|
||||
object(DOMText)#%d (19) {
|
||||
object(DOMText)#%d (21) {
|
||||
["wholeText"]=>
|
||||
string(3) "
|
||||
"
|
||||
|
@ -39,6 +39,10 @@ object(DOMText)#%d (19) {
|
|||
"
|
||||
["length"]=>
|
||||
int(3)
|
||||
["previousElementSibling"]=>
|
||||
NULL
|
||||
["nextElementSibling"]=>
|
||||
NULL
|
||||
["nodeName"]=>
|
||||
string(5) "#text"
|
||||
["nodeValue"]=>
|
||||
|
@ -74,11 +78,21 @@ object(DOMText)#%d (19) {
|
|||
string(3) "
|
||||
"
|
||||
}
|
||||
object(DOMElement)#%d (18) {
|
||||
object(DOMElement)#%d (23) {
|
||||
["tagName"]=>
|
||||
string(5) "form1"
|
||||
["schemaTypeInfo"]=>
|
||||
NULL
|
||||
["firstElementChild"]=>
|
||||
string(22) "(object value omitted)"
|
||||
["lastElementChild"]=>
|
||||
string(22) "(object value omitted)"
|
||||
["childElementCount"]=>
|
||||
int(3)
|
||||
["previousElementSibling"]=>
|
||||
NULL
|
||||
["nextElementSibling"]=>
|
||||
NULL
|
||||
["nodeName"]=>
|
||||
string(5) "form1"
|
||||
["nodeValue"]=>
|
||||
|
@ -120,7 +134,7 @@ object(DOMElement)#%d (18) {
|
|||
Value C
|
||||
"
|
||||
}
|
||||
object(DOMText)#%d (19) {
|
||||
object(DOMText)#%d (21) {
|
||||
["wholeText"]=>
|
||||
string(1) "
|
||||
"
|
||||
|
@ -129,6 +143,10 @@ object(DOMText)#%d (19) {
|
|||
"
|
||||
["length"]=>
|
||||
int(1)
|
||||
["previousElementSibling"]=>
|
||||
NULL
|
||||
["nextElementSibling"]=>
|
||||
NULL
|
||||
["nodeName"]=>
|
||||
string(5) "#text"
|
||||
["nodeValue"]=>
|
||||
|
|
|
@ -48,4 +48,22 @@ function print_node_list($nodelist)
|
|||
}
|
||||
}
|
||||
|
||||
function print_node_compact($node, $spaces)
|
||||
{
|
||||
if ($node->nodeType == 3) {
|
||||
print str_repeat(" ", $spaces) . trim($node->nodeValue) . "\n";
|
||||
} else {
|
||||
print str_repeat(" ", $spaces) . "<" . $node->nodeName . ">\n";
|
||||
print_node_list_compact($node->childNodes, $spaces + 2);
|
||||
print str_repeat(" ", $spaces) . "</" . $node->nodeName . ">\n";
|
||||
}
|
||||
}
|
||||
|
||||
function print_node_list_compact($nodelist, $spaces = 0)
|
||||
{
|
||||
foreach ($nodelist as $node) {
|
||||
print_node_compact($node, $spaces);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
|
|
|
@ -39,6 +39,9 @@ DOMDocument Object
|
|||
[preserveWhiteSpace] => 1
|
||||
[recover] =>
|
||||
[substituteEntities] =>
|
||||
[firstElementChild] => (object value omitted)
|
||||
[lastElementChild] => (object value omitted)
|
||||
[childElementCount] => 1
|
||||
[nodeName] => #document
|
||||
[nodeValue] =>
|
||||
[nodeType] => 9
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue