public static function PHPUnit_Util_XML::findNodes in Zircon Profile 8
Same name and namespace in other branches
- 8.0 vendor/phpunit/phpunit/src/Util/XML.php \PHPUnit_Util_XML::findNodes()
Parse out the options from the tag using DOM object tree.
@since Method available since Release 3.3.0
Parameters
DOMDocument $dom:
array $options:
bool $isHtml:
Return value
array
3 calls to PHPUnit_Util_XML::findNodes()
- PHPUnit_Framework_Assert::assertNotTag in vendor/
phpunit/ phpunit/ src/ Framework/ Assert.php - This assertion is the exact opposite of assertTag().
- PHPUnit_Framework_Assert::assertTag in vendor/
phpunit/ phpunit/ src/ Framework/ Assert.php - Evaluate an HTML or XML string and assert its structure and/or contents.
- PHPUnit_Util_XML::cssSelect in vendor/
phpunit/ phpunit/ src/ Util/ XML.php - Parse an $actual document and return an array of DOMNodes matching the CSS $selector. If an error occurs, it will return false.
File
- vendor/
phpunit/ phpunit/ src/ Util/ XML.php, line 463
Class
- PHPUnit_Util_XML
- XML helpers.
Code
public static function findNodes(DOMDocument $dom, array $options, $isHtml = true) {
$valid = array(
'id',
'class',
'tag',
'content',
'attributes',
'parent',
'child',
'ancestor',
'descendant',
'children',
'adjacent-sibling',
);
$filtered = array();
$options = self::assertValidKeys($options, $valid);
// find the element by id
if ($options['id']) {
$options['attributes']['id'] = $options['id'];
}
if ($options['class']) {
$options['attributes']['class'] = $options['class'];
}
$nodes = array();
// find the element by a tag type
if ($options['tag']) {
if ($isHtml) {
$elements = self::getElementsByCaseInsensitiveTagName($dom, $options['tag']);
}
else {
$elements = $dom
->getElementsByTagName($options['tag']);
}
foreach ($elements as $element) {
$nodes[] = $element;
}
if (empty($nodes)) {
return false;
}
}
else {
$tags = array(
'a',
'abbr',
'acronym',
'address',
'area',
'b',
'base',
'bdo',
'big',
'blockquote',
'body',
'br',
'button',
'caption',
'cite',
'code',
'col',
'colgroup',
'dd',
'del',
'div',
'dfn',
'dl',
'dt',
'em',
'fieldset',
'form',
'frame',
'frameset',
'h1',
'h2',
'h3',
'h4',
'h5',
'h6',
'head',
'hr',
'html',
'i',
'iframe',
'img',
'input',
'ins',
'kbd',
'label',
'legend',
'li',
'link',
'map',
'meta',
'noframes',
'noscript',
'object',
'ol',
'optgroup',
'option',
'p',
'param',
'pre',
'q',
'samp',
'script',
'select',
'small',
'span',
'strong',
'style',
'sub',
'sup',
'table',
'tbody',
'td',
'textarea',
'tfoot',
'th',
'thead',
'title',
'tr',
'tt',
'ul',
'var',
// HTML5
'article',
'aside',
'audio',
'bdi',
'canvas',
'command',
'datalist',
'details',
'dialog',
'embed',
'figure',
'figcaption',
'footer',
'header',
'hgroup',
'keygen',
'mark',
'meter',
'nav',
'output',
'progress',
'ruby',
'rt',
'rp',
'track',
'section',
'source',
'summary',
'time',
'video',
'wbr',
);
foreach ($tags as $tag) {
if ($isHtml) {
$elements = self::getElementsByCaseInsensitiveTagName($dom, $tag);
}
else {
$elements = $dom
->getElementsByTagName($tag);
}
foreach ($elements as $element) {
$nodes[] = $element;
}
}
if (empty($nodes)) {
return false;
}
}
// filter by attributes
if ($options['attributes']) {
foreach ($nodes as $node) {
$invalid = false;
foreach ($options['attributes'] as $name => $value) {
// match by regexp if like "regexp:/foo/i"
if (preg_match('/^regexp\\s*:\\s*(.*)/i', $value, $matches)) {
if (!preg_match($matches[1], $node
->getAttribute($name))) {
$invalid = true;
}
}
elseif ($name == 'class') {
// split to individual classes
$findClasses = explode(' ', preg_replace("/\\s+/", ' ', $value));
$allClasses = explode(' ', preg_replace("/\\s+/", ' ', $node
->getAttribute($name)));
// make sure each class given is in the actual node
foreach ($findClasses as $findClass) {
if (!in_array($findClass, $allClasses)) {
$invalid = true;
}
}
}
else {
if ($node
->getAttribute($name) != $value) {
$invalid = true;
}
}
}
// if every attribute given matched
if (!$invalid) {
$filtered[] = $node;
}
}
$nodes = $filtered;
$filtered = array();
if (empty($nodes)) {
return false;
}
}
// filter by content
if ($options['content'] !== null) {
foreach ($nodes as $node) {
$invalid = false;
// match by regexp if like "regexp:/foo/i"
if (preg_match('/^regexp\\s*:\\s*(.*)/i', $options['content'], $matches)) {
if (!preg_match($matches[1], self::getNodeText($node))) {
$invalid = true;
}
}
elseif ($options['content'] === '') {
if (self::getNodeText($node) !== '') {
$invalid = true;
}
}
elseif (strstr(self::getNodeText($node), $options['content']) === false) {
$invalid = true;
}
if (!$invalid) {
$filtered[] = $node;
}
}
$nodes = $filtered;
$filtered = array();
if (empty($nodes)) {
return false;
}
}
// filter by parent node
if ($options['parent']) {
$parentNodes = self::findNodes($dom, $options['parent'], $isHtml);
$parentNode = isset($parentNodes[0]) ? $parentNodes[0] : null;
foreach ($nodes as $node) {
if ($parentNode !== $node->parentNode) {
continue;
}
$filtered[] = $node;
}
$nodes = $filtered;
$filtered = array();
if (empty($nodes)) {
return false;
}
}
// filter by child node
if ($options['child']) {
$childNodes = self::findNodes($dom, $options['child'], $isHtml);
$childNodes = !empty($childNodes) ? $childNodes : array();
foreach ($nodes as $node) {
foreach ($node->childNodes as $child) {
foreach ($childNodes as $childNode) {
if ($childNode === $child) {
$filtered[] = $node;
}
}
}
}
$nodes = $filtered;
$filtered = array();
if (empty($nodes)) {
return false;
}
}
// filter by adjacent-sibling
if ($options['adjacent-sibling']) {
$adjacentSiblingNodes = self::findNodes($dom, $options['adjacent-sibling'], $isHtml);
$adjacentSiblingNodes = !empty($adjacentSiblingNodes) ? $adjacentSiblingNodes : array();
foreach ($nodes as $node) {
$sibling = $node;
while ($sibling = $sibling->nextSibling) {
if ($sibling->nodeType !== XML_ELEMENT_NODE) {
continue;
}
foreach ($adjacentSiblingNodes as $adjacentSiblingNode) {
if ($sibling === $adjacentSiblingNode) {
$filtered[] = $node;
break;
}
}
break;
}
}
$nodes = $filtered;
$filtered = array();
if (empty($nodes)) {
return false;
}
}
// filter by ancestor
if ($options['ancestor']) {
$ancestorNodes = self::findNodes($dom, $options['ancestor'], $isHtml);
$ancestorNode = isset($ancestorNodes[0]) ? $ancestorNodes[0] : null;
foreach ($nodes as $node) {
$parent = $node->parentNode;
while ($parent && $parent->nodeType != XML_HTML_DOCUMENT_NODE) {
if ($parent === $ancestorNode) {
$filtered[] = $node;
}
$parent = $parent->parentNode;
}
}
$nodes = $filtered;
$filtered = array();
if (empty($nodes)) {
return false;
}
}
// filter by descendant
if ($options['descendant']) {
$descendantNodes = self::findNodes($dom, $options['descendant'], $isHtml);
$descendantNodes = !empty($descendantNodes) ? $descendantNodes : array();
foreach ($nodes as $node) {
foreach (self::getDescendants($node) as $descendant) {
foreach ($descendantNodes as $descendantNode) {
if ($descendantNode === $descendant) {
$filtered[] = $node;
}
}
}
}
$nodes = $filtered;
$filtered = array();
if (empty($nodes)) {
return false;
}
}
// filter by children
if ($options['children']) {
$validChild = array(
'count',
'greater_than',
'less_than',
'only',
);
$childOptions = self::assertValidKeys($options['children'], $validChild);
foreach ($nodes as $node) {
$childNodes = $node->childNodes;
foreach ($childNodes as $childNode) {
if ($childNode->nodeType !== XML_CDATA_SECTION_NODE && $childNode->nodeType !== XML_TEXT_NODE) {
$children[] = $childNode;
}
}
// we must have children to pass this filter
if (!empty($children)) {
// exact count of children
if ($childOptions['count'] !== null) {
if (count($children) !== $childOptions['count']) {
break;
}
}
elseif ($childOptions['less_than'] !== null && $childOptions['greater_than'] !== null) {
if (count($children) >= $childOptions['less_than'] || count($children) <= $childOptions['greater_than']) {
break;
}
}
elseif ($childOptions['less_than'] !== null) {
if (count($children) >= $childOptions['less_than']) {
break;
}
}
elseif ($childOptions['greater_than'] !== null) {
if (count($children) <= $childOptions['greater_than']) {
break;
}
}
// match each child against a specific tag
if ($childOptions['only']) {
$onlyNodes = self::findNodes($dom, $childOptions['only'], $isHtml);
// try to match each child to one of the 'only' nodes
foreach ($children as $child) {
$matched = false;
foreach ($onlyNodes as $onlyNode) {
if ($onlyNode === $child) {
$matched = true;
}
}
if (!$matched) {
break 2;
}
}
}
$filtered[] = $node;
}
}
$nodes = $filtered;
if (empty($nodes)) {
return;
}
}
// return the first node that matches all criteria
return !empty($nodes) ? $nodes : array();
}