DOM в php 5. Помогите найти ошибку

Sparrow

Новичок
DOM в php 5. Помогите найти ошибку

Суть проблемы:

На входе есть non-well-formed html, порожденный визуальным редактором.

Требуется преобразовать его в формат NITF, а именно:

1. убрать все <br>, вместо них использовать форматирование параграфами
2. заменить все конструкции <img src="file.jpg"> на <media type="image">

Для решения используется класс, реализованный с помощью PHP 5 и библиотеки DOM.

Полный код парсера приведен в конце


Проблема возникает в ситуации, когда после обработки "запрещенного" тега i происходит переход к вложенному в него тексту. При присвоении $obElement=$obElement->firstChild методы и свойства $obElement становятся недоступны.

причем $this->DebugNode($firstChild) выдает правильную информацию, а $this->DebugNode($obElement) - нет.

Вывод вот этого куска кода:

PHP:
echo "First child:".$this->DebugNode($firstChild);
						echo "Real first child:".$this->DebugNode($obElement->firstChild);

						$obElement = $obElement->firstChild;
						var_dump($obElement);
						echo "Final first child:".$this->DebugNode($obElement);
First child:TAG=#text, TYPE=3, value=Традиционно Topman выпускает как классические вещи, так и неформальные.
Real first child:TAG=#text, TYPE=3, value=Традиционно Topman выпускает как классические вещи, так и неформальные.
object(DOMText)#40 (0) { } Final first child:TAG=, TYPE=, value=
Final first child: должно быть то эже, что и в First Child

Подскажите, где тут грабли

PHP:
	private function DebugNode($obElement)
	{
		if ($obElement == null)
			return 'NULL';
		elseif ($obElement instanceof DOMNode)
		 	return "TAG=".$obElement->nodeName.", TYPE=".$obElement->nodeType. ", value=".$this->toSiteEncoding($obElement->nodeValue)."<br/>";
		else
			return "Not a DOMNode or its descendant type";

	}
Версия php: 5.2.6
Версия Apache: 1.3.41, работает в режиме модуля Apache

PHP:
public function convertDetailText()
{


		if ($this->isDocLoaded)  /* Документ загружен методом loadHtml в $this->obDocument, при этомне возникло Exception */
		{


			// replace 'br' with 'p'
			$obBodyNodeList = $this->obDocument->GetElementsByTagName('body');
			$obBodyElement = $obBodyNodeList->item(0);

			// recursive walk
			try {
				//echo "walk";
				$obElement = $obBodyElement->firstChild;
				$obCurrentParagraph = $this->obDocument->CreateElement('p');
				//echo "sw";
				while(!$obBodyElement->isSameNode($obElement))
				{
					echo "initial dump: ";
					var_dump($obElement);
					print_r($obElement);
					echo "<br/><br/>";
					$bContinue = false;
					//echo "inw";
					echo $this->DebugNode($obElement);
					//echo "dbg";
					// save, as these may change thru' our actions
					$nextSibling = $obElement->nextSibling;
					$firstChild = $obElement->hasChildNodes() ? $obElement->firstChild : null;
					$parent = $obElement->parentNode;

					switch($obElement->nodeName)
					{
						case 'br':
							echo "Removing the break...";
							// remove the break
							if ($parent != null)
								$parent->removeChild($obElement);

							// complete current paragraph
							$obBodyElement->appendChild($obCurrentParagraph);

							// start a new paragraph
							$obCurrentParagraph = $this->obDocument->CreateElement('p');
							echo "done<br/>";
						break;
						case 'b':	// add more unwanted tags to the list here
						case 'i':
						case 'u':
						case 'strong':
						case 'em':
						case 'a':
							// remove a tag that is not allowed
							if ($parent != null)
							{
								echo "Removing the violating node: &lt;".$obElement->nodeName.'&gt;';
								$parent->removeChild($obElement);
								$returnToParent = $parent;
								echo "done<br/>";
							}

						break;

						case 'img':
							echo "Image conversion<br/>";
							// convert image
							$obConvertedNode = $this->convertImgNode($obElement);

							// remove img tag
							if ($parent != null)
								$parent->removeChild($obElement);

							// end current paragraph
							$obBodyElement->appendChild($obCurrentParagraph);

							// append the 'media' tag after it
							$obBodyElement->appendChild($obConvertedNode);

							// start a new paragraph
							$obCurrentParagraph = $this->obDocument->createElement('p');
						break;
						default:
						// add the element to the current paragraph
							if ($parent != null)
								$parent->removeChild($obElement);

							$obCurrentParagraph->appendChild($obElement);
						echo "appended to the current paragraph<br/>";



					} // switch

					if ($bContinue)
						continue;

					// goto next element in the tree;
					if($obElement->nodeType == XML_TEXT_NODE)
					{
						echo "This is a text node";
					}
					if (($firstChild !== null) && ($obElement->nodeType == XML_ELEMENT_NODE))
					{
						// no children accepted from text nodes, etc
						echo "Moving to first child<br/>";
						echo "First child:".$this->DebugNode($firstChild);
						echo "Real first child:".$this->DebugNode($obElement->firstChild);

						$obElement = $obElement->firstChild;
						var_dump($obElement);
						echo "Final first child:".$this->DebugNode($obElement);
					}
					elseif ($nextSibling !== null)
					{
						echo "Moving to next sibling<br/>";
						$obElement = $nextSibling;
					}
					else {
						echo "returning to the parent<br/>";
						// complete current paragraph
						$this->DebugNode($obElement);
						$obCurrentParagraph->appendChild($obElement);
						$obBodyElement->appendChild($obCurrentParagraph);

						if ($parent != null)
							$obElement = $parent;
						else
							$obElement = $returnToParent;
						// close paragraph
					}
				}	// while
				echo "end while<br/>";
				// complete the last paragraph
			}	// try
			catch (Exception $e)
			{
				echo "Exception caught on BR-remove: [".$e->code . '] '. $e->getMessage() . ' executing ' . $e->getFile() .'@' . $e->getLine() . '<br/>' . $e->getTraceAsString();
				return false;
			}

			//return result
			return true;
		}
		else // not ok
		{
			return false;
		}
	}
 

Sparrow

Новичок
Вы предлагаете самому переписывать библиотеки разбора тегов? Тут простая замена не работает, скорее тогда preg_replace. Но по моему опыту работы с преобразованиями html, проще отловить ошибку в структуре дерева, чем в регулярных выражениях. Вот только иногда бывают подобные странности.
 

JD

Новичок
Re: DOM в php 5. Помогите найти ошибку

Автор оригинала: Sparrow
Суть проблемы:

На входе есть non-well-formed html, порожденный визуальным редактором.
Может, стоит бороться с тем, что пораждает проблему? Т.е. с самим редактором: исправить существующий или заменить на другой, который будет давать на выходе нужный (или валидный для обработки) HTML.
 
Сверху