mirror of
https://github.com/php/php-src.git
synced 2025-08-15 21:48:51 +02:00
Implement HTMLCollection::namedItem()
This commit is contained in:
parent
5c69b2e86f
commit
ac039cf716
8 changed files with 137 additions and 4 deletions
|
@ -229,4 +229,15 @@ xmlChar *dom_attr_value(const xmlAttr *attr, bool *free)
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool dom_compare_value(const xmlAttr *attr, const xmlChar *value)
|
||||||
|
{
|
||||||
|
bool free;
|
||||||
|
xmlChar *attr_value = dom_attr_value(attr, &free);
|
||||||
|
bool result = xmlStrEqual(attr_value, value);
|
||||||
|
if (free) {
|
||||||
|
xmlFree(attr_value);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -32,7 +32,7 @@ if test "$PHP_DOM" != "no"; then
|
||||||
documentfragment.c domimplementation.c \
|
documentfragment.c domimplementation.c \
|
||||||
element.c node.c characterdata.c \
|
element.c node.c characterdata.c \
|
||||||
documenttype.c entity.c \
|
documenttype.c entity.c \
|
||||||
nodelist.c text.c comment.c \
|
nodelist.c html_collection.c text.c comment.c \
|
||||||
entityreference.c \
|
entityreference.c \
|
||||||
notation.c xpath.c dom_iterators.c \
|
notation.c xpath.c dom_iterators.c \
|
||||||
namednodemap.c xpath_callbacks.c \
|
namednodemap.c xpath_callbacks.c \
|
||||||
|
|
|
@ -12,7 +12,7 @@ if (PHP_DOM == "yes") {
|
||||||
domexception.c parentnode.c processinginstruction.c \
|
domexception.c parentnode.c processinginstruction.c \
|
||||||
cdatasection.c documentfragment.c domimplementation.c element.c \
|
cdatasection.c documentfragment.c domimplementation.c element.c \
|
||||||
node.c characterdata.c documenttype.c \
|
node.c characterdata.c documenttype.c \
|
||||||
entity.c nodelist.c text.c comment.c \
|
entity.c nodelist.c html_collection.c text.c comment.c \
|
||||||
entityreference.c \
|
entityreference.c \
|
||||||
notation.c xpath.c dom_iterators.c \
|
notation.c xpath.c dom_iterators.c \
|
||||||
namednodemap.c xpath_callbacks.c", null, "-Iext/dom/lexbor");
|
namednodemap.c xpath_callbacks.c", null, "-Iext/dom/lexbor");
|
||||||
|
|
74
ext/dom/html_collection.c
Normal file
74
ext/dom/html_collection.c
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
/*
|
||||||
|
+----------------------------------------------------------------------+
|
||||||
|
| 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: |
|
||||||
|
| https://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: Niels Dossche <nielsdos@php.net> |
|
||||||
|
+----------------------------------------------------------------------+
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "php.h"
|
||||||
|
#if defined(HAVE_LIBXML) && defined(HAVE_DOM)
|
||||||
|
#include "php_dom.h"
|
||||||
|
#include "namespace_compat.h"
|
||||||
|
|
||||||
|
/* https://dom.spec.whatwg.org/#dom-htmlcollection-nameditem-key */
|
||||||
|
PHP_METHOD(DOM_HTMLCollection, namedItem)
|
||||||
|
{
|
||||||
|
zend_string *key;
|
||||||
|
ZEND_PARSE_PARAMETERS_START(1, 1)
|
||||||
|
Z_PARAM_PATH_STR(key)
|
||||||
|
ZEND_PARSE_PARAMETERS_END();
|
||||||
|
|
||||||
|
/* 1. If key is the empty string, return null. */
|
||||||
|
if (ZSTR_LEN(key) == 0) {
|
||||||
|
RETURN_NULL();
|
||||||
|
}
|
||||||
|
|
||||||
|
dom_object *intern = Z_DOMOBJ_P(ZEND_THIS);
|
||||||
|
dom_nnodemap_object *objmap = intern->ptr;
|
||||||
|
|
||||||
|
/* 2. Return the first element in the collection for which at least one of the following is true: */
|
||||||
|
xmlNodePtr basep = dom_object_get_node(objmap->baseobj);
|
||||||
|
if (basep != NULL) {
|
||||||
|
int cur = 0;
|
||||||
|
int next = cur;
|
||||||
|
xmlNodePtr candidate = basep->children;
|
||||||
|
while (candidate != NULL) {
|
||||||
|
candidate = dom_get_elements_by_tag_name_ns_raw(basep, candidate, objmap->ns, objmap->local, objmap->local_lower, &cur, next);
|
||||||
|
if (candidate == NULL) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
xmlAttrPtr attr;
|
||||||
|
|
||||||
|
/* it has an ID which is key; */
|
||||||
|
if ((attr = xmlHasNsProp(candidate, BAD_CAST "id", NULL)) != NULL && dom_compare_value(attr, BAD_CAST ZSTR_VAL(key))) {
|
||||||
|
DOM_RET_OBJ(candidate, objmap->baseobj);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* it is in the HTML namespace and has a name attribute whose value is key; */
|
||||||
|
else if (php_dom_ns_is_fast(candidate, php_dom_ns_is_html_magic_token)) {
|
||||||
|
if ((attr = xmlHasNsProp(candidate, BAD_CAST "name", NULL)) != NULL && dom_compare_value(attr, BAD_CAST ZSTR_VAL(key))) {
|
||||||
|
DOM_RET_OBJ(candidate, objmap->baseobj);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
next = cur + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -175,6 +175,7 @@ dom_object *php_dom_instantiate_object_helper(zval *return_value, zend_class_ent
|
||||||
xmlDocPtr php_dom_create_html_doc(void);
|
xmlDocPtr php_dom_create_html_doc(void);
|
||||||
|
|
||||||
xmlChar *dom_attr_value(const xmlAttr *attr, bool *free);
|
xmlChar *dom_attr_value(const xmlAttr *attr, bool *free);
|
||||||
|
bool dom_compare_value(const xmlAttr *attr, const xmlChar *value);
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
DOM_LOAD_STRING = 0,
|
DOM_LOAD_STRING = 0,
|
||||||
|
|
|
@ -1279,7 +1279,7 @@ namespace DOM
|
||||||
/** @implementation-alias DOMNodeList::item */
|
/** @implementation-alias DOMNodeList::item */
|
||||||
public function item(int $index): ?Element {}
|
public function item(int $index): ?Element {}
|
||||||
|
|
||||||
/* TODO: implement namedItem */
|
public function namedItem(string $key): ?Element {}
|
||||||
|
|
||||||
/** @implementation-alias DOMNodeList::count */
|
/** @implementation-alias DOMNodeList::count */
|
||||||
public function count(): int {}
|
public function count(): int {}
|
||||||
|
|
8
ext/dom/php_dom_arginfo.h
generated
8
ext/dom/php_dom_arginfo.h
generated
|
@ -1,5 +1,5 @@
|
||||||
/* This is a generated file, edit the .stub.php file instead.
|
/* This is a generated file, edit the .stub.php file instead.
|
||||||
* Stub hash: f441c789fdce91e8fc71f450b294c11059999af1 */
|
* Stub hash: 37a1c811bfc8c611d686f0842d06fc327b54511f */
|
||||||
|
|
||||||
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_dom_import_simplexml, 0, 1, DOMElement, 0)
|
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_dom_import_simplexml, 0, 1, DOMElement, 0)
|
||||||
ZEND_ARG_TYPE_INFO(0, node, IS_OBJECT, 0)
|
ZEND_ARG_TYPE_INFO(0, node, IS_OBJECT, 0)
|
||||||
|
@ -721,6 +721,10 @@ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_class_DOM_HTMLCollection_item, 0,
|
||||||
ZEND_ARG_TYPE_INFO(0, index, IS_LONG, 0)
|
ZEND_ARG_TYPE_INFO(0, index, IS_LONG, 0)
|
||||||
ZEND_END_ARG_INFO()
|
ZEND_END_ARG_INFO()
|
||||||
|
|
||||||
|
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_class_DOM_HTMLCollection_namedItem, 0, 1, DOM\\Element, 1)
|
||||||
|
ZEND_ARG_TYPE_INFO(0, key, IS_STRING, 0)
|
||||||
|
ZEND_END_ARG_INFO()
|
||||||
|
|
||||||
#define arginfo_class_DOM_HTMLCollection_count arginfo_class_DOM_Node_getLineNo
|
#define arginfo_class_DOM_HTMLCollection_count arginfo_class_DOM_Node_getLineNo
|
||||||
|
|
||||||
#define arginfo_class_DOM_HTMLCollection_getIterator arginfo_class_DOMNodeList_getIterator
|
#define arginfo_class_DOM_HTMLCollection_getIterator arginfo_class_DOMNodeList_getIterator
|
||||||
|
@ -1256,6 +1260,7 @@ ZEND_METHOD(DOM_Node, appendChild);
|
||||||
ZEND_METHOD(DOM_Node, replaceChild);
|
ZEND_METHOD(DOM_Node, replaceChild);
|
||||||
ZEND_METHOD(DOM_Node, removeChild);
|
ZEND_METHOD(DOM_Node, removeChild);
|
||||||
ZEND_METHOD(DOM_Node, getNodePath);
|
ZEND_METHOD(DOM_Node, getNodePath);
|
||||||
|
ZEND_METHOD(DOM_HTMLCollection, namedItem);
|
||||||
ZEND_METHOD(DOM_Element, removeAttribute);
|
ZEND_METHOD(DOM_Element, removeAttribute);
|
||||||
ZEND_METHOD(DOM_Element, setAttributeNodeNS);
|
ZEND_METHOD(DOM_Element, setAttributeNodeNS);
|
||||||
ZEND_METHOD(DOM_Element, removeAttributeNode);
|
ZEND_METHOD(DOM_Element, removeAttributeNode);
|
||||||
|
@ -1620,6 +1625,7 @@ static const zend_function_entry class_DOM_DTDNamedNodeMap_methods[] = {
|
||||||
|
|
||||||
static const zend_function_entry class_DOM_HTMLCollection_methods[] = {
|
static const zend_function_entry class_DOM_HTMLCollection_methods[] = {
|
||||||
ZEND_RAW_FENTRY("item", zim_DOMNodeList_item, arginfo_class_DOM_HTMLCollection_item, ZEND_ACC_PUBLIC, NULL, NULL)
|
ZEND_RAW_FENTRY("item", zim_DOMNodeList_item, arginfo_class_DOM_HTMLCollection_item, ZEND_ACC_PUBLIC, NULL, NULL)
|
||||||
|
ZEND_ME(DOM_HTMLCollection, namedItem, arginfo_class_DOM_HTMLCollection_namedItem, ZEND_ACC_PUBLIC)
|
||||||
ZEND_RAW_FENTRY("count", zim_DOMNodeList_count, arginfo_class_DOM_HTMLCollection_count, ZEND_ACC_PUBLIC, NULL, NULL)
|
ZEND_RAW_FENTRY("count", zim_DOMNodeList_count, arginfo_class_DOM_HTMLCollection_count, ZEND_ACC_PUBLIC, NULL, NULL)
|
||||||
ZEND_RAW_FENTRY("getIterator", zim_DOMNodeList_getIterator, arginfo_class_DOM_HTMLCollection_getIterator, ZEND_ACC_PUBLIC, NULL, NULL)
|
ZEND_RAW_FENTRY("getIterator", zim_DOMNodeList_getIterator, arginfo_class_DOM_HTMLCollection_getIterator, ZEND_ACC_PUBLIC, NULL, NULL)
|
||||||
ZEND_FE_END
|
ZEND_FE_END
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
--TEST--
|
||||||
|
HTMLCollection::namedItem() and dimension handling for named accesses
|
||||||
|
--EXTENSIONS--
|
||||||
|
dom
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
$xml = <<<XML
|
||||||
|
<!DOCTYPE root [
|
||||||
|
<!ENTITY ent "test">
|
||||||
|
]>
|
||||||
|
<root>
|
||||||
|
<node name="foo">1</node>
|
||||||
|
<x id="foo">2</x>
|
||||||
|
<x id="foo&ent;">2 with entity</x>
|
||||||
|
<node test:id="foo" xmlns:test="http://example.com">3</node>
|
||||||
|
<node id="wrong">4</node>
|
||||||
|
<node id="foo">5</node>
|
||||||
|
<node name="bar">without html ns</node>
|
||||||
|
<node name="bar" xmlns="http://www.w3.org/1999/xhtml">with html ns</node>
|
||||||
|
</root>
|
||||||
|
XML;
|
||||||
|
|
||||||
|
$dom = DOM\XMLDocument::createFromString($xml);
|
||||||
|
var_dump($dom->getElementsByTagName('node')->namedItem('foo')?->textContent);
|
||||||
|
var_dump($dom->getElementsByTagName('node')->namedItem('')?->textContent);
|
||||||
|
var_dump($dom->getElementsByTagName('node')->namedItem('does not exist')?->textContent);
|
||||||
|
var_dump($dom->getElementsByTagName('node')->namedItem('wrong')?->textContent);
|
||||||
|
var_dump($dom->getElementsByTagName('node')->namedItem('bar')?->textContent);
|
||||||
|
var_dump($dom->getElementsByTagName('x')->namedItem('foo')?->textContent);
|
||||||
|
var_dump($dom->getElementsByTagName('x')->namedItem('footest')?->textContent);
|
||||||
|
|
||||||
|
?>
|
||||||
|
--EXPECT--
|
||||||
|
string(1) "5"
|
||||||
|
NULL
|
||||||
|
NULL
|
||||||
|
string(1) "4"
|
||||||
|
string(12) "with html ns"
|
||||||
|
string(1) "2"
|
||||||
|
string(13) "2 with entity"
|
Loading…
Add table
Add a link
Reference in a new issue