• Модуль: main
  • Путь к файлу: ~/bitrix/modules/main/lib/web/dom/htmlparser.php
  • Класс: BitrixMainWebDOMHtmlParser
  • Вызов: HtmlParser::getNextNode
protected function getNextNode($tag, Node $parentNode)
{
	$node = null;
	$isSingleTag = true;

	static $tagsWithoutClose = array('INPUT'=>1, 'IMG'=>1, 'BR'=>1, 'HR'=>1, 'META'=>1, 'AREA'=>1, 'BASE'=>1, 'COL'=>1, 'EMBED'=>1, 'KEYGEN'=>1, 'LINK'=>1, 'PARAM'=>1, 'SOURCE'=>1, 'TRACK'=>1, 'WBR'=>1);
	$tagsCantHaveNestedTags = array();

	$document = $parentNode->getOwnerDocument();

	if($parentNode->getNodeType() === Node::COMMENT_NODE)
	{
		$commentClosePosition = mb_strpos($tag, '-->');
		if($commentClosePosition !== false)
		{
			$clean = mb_substr($tag, 0, $commentClosePosition);
			$parentNode->setNodeValue($parentNode->getNodeValue() . $clean);
			$parentNode->bxNodeFoundCloseTag = true;

			$tag = mb_substr($tag, $commentClosePosition + 3);
			if(!$tag)
			{
				return $parentNode->getParentNode();
			}
			else
			{
				$parentNode = $parentNode->getParentNode();
			}
		}
		else
		{
			$parentNode->setNodeValue($parentNode->getNodeValue() . $tag);
			return $parentNode;
		}
	}
	elseif(in_array($parentNode->getNodeName(), $this->tagsMustBeClosed))
	{
		if(mb_strtoupper(mb_substr($tag, -9)) == 'getNodeName().'>')
		{
			$parentNode->bxNodeFoundCloseTag = true;
			$parentNode = $parentNode->getParentNode();
		}
		else
		{
			$firstChild = $parentNode->getFirstChild();
			if(!$firstChild)
			{
				$parentNode->appendChild($document->createTextNode($tag));
			}
			else
			{
				$firstChild->setNodeValue($firstChild->getNodeValue() . $tag);
			}

			$parentNode->bxNodeFoundCloseTag = false;
			return $parentNode;
		}
	}

	if(mb_substr($tag, 0, 2) === '')));
		$searchableNode = $parentNode;
		$isSearchableNodeFound = false;

		$unclosedNodes = array();
		do
		{
			if(!$searchableNode->bxNodeFoundCloseTag)
			{
				$unclosedNodes[] = $searchableNode;
			}

			if($searchableNode->getNodeName() === $cleaned)
			{
				$isSearchableNodeFound = true;
				break;
			}
		}while($searchableNode = $searchableNode->getParentNode());

		if($isSearchableNodeFound)
		{
			foreach($unclosedNodes as $unclosedNode)
			{
				/* @var $unclosedNode Node */
				if(in_array($unclosedNode->getNodeName(), $tagsCantHaveNestedTags))
				{
					if($unclosedNode->hasChildNodes())
					{
						foreach ($unclosedNode->getChildNodesArray() as $childNode)
						{
							$unclosedNode->getParentNode()->appendChild($unclosedNode->removeChild($childNode));
						}
					}
				}

				$unclosedNode->bxNodeFoundCloseTag = true;
			}

			return $searchableNode->getParentNode();
		}
		else
		{
			if(false)
			{
				throw new DomException('Parser error. Find close tag, but can not find open tag ' . $cleaned);
			}
			else
			{
				if ($parentNode->getParentNode())
				{
					$parentNode->getParentNode()->bxNodeFoundCloseTag = true;
				}
				return $parentNode;
			}
		}
	}
	elseif(mb_substr($tag, 0, 4) === '')
		{
			$cleaned = mb_substr($cleaned, 0, -3);
			$parentNode->bxNodeFoundCloseTag = true;
		}
		else
		{
			$isSingleTag = false;
		}


		//$parentNode->bxNodeFoundCloseTag = false;
		$node = $document->createComment($cleaned);
	}
	elseif(mb_substr($tag, 0, 1) === '<')
	{

		// Element
		if(mb_substr($tag, -2) === '/>')
		{
			// empty tag
			$cleaned = mb_substr($tag, 1, -2);
			$bxNodeWithCloseTag = false;
		}
		else
		{
			$cleaned = mb_substr($tag, 1, -1);
			$isSingleTag = false;
			$bxNodeWithCloseTag = true;
		}

		$list = $this->parseElement($cleaned);

		$isDocType = mb_substr($list['NAME'], 0, mb_strlen('!DOCTYPE')) === '!DOCTYPE';

		if(isset($tagsWithoutClose[$list['NAME']]) || $isDocType)
		{
			$bxNodeWithCloseTag = false;
			$isSingleTag = true;
		}

		if($isDocType)
		{
			$list = $this->parseDocType($cleaned);
			//TODO: set doctype fields
		}
		else
		{
			$node = $document->createElement($list['NAME']);
			foreach($list['ATTRIBUTES'] as $attrName => $attrValue)
			{
				$nodeAttr = $document->createAttribute($attrName, $attrValue);
				$node->setAttributeNode($nodeAttr);
			}
			$node->bxNodeWithCloseTag = $bxNodeWithCloseTag;
		}
	}
	else
	{
		// Text
		$cleaned = html_entity_decode($tag, ENT_QUOTES, (defined("BX_UTF") ? "UTF-8" : "ISO-8859-1"));
		$node = $document->createTextNode($cleaned);
	}

	if($node && $parentNode)
	{
		$parentNode->appendChild($node);
		if(!$isSingleTag)
		{
			return $node;
		}
	}

	return $parentNode;
}