[ Поиск ] - [ Пользователи ] - [ Календарь ]
Полная Версия: Разбор XML документа в PHP с помощью DOM
dosnsk
Хочу поделиться решением.
Долго искал по всему интернету как разобрать XML документ и получить массив его элементов, но так и не нашел ничего приемлемого. Пришлось писать самому.
Вот что у меня получилось:

/*преобразование XML документа в двумерный массив
1 строка: список тегов
2 и последующие: строки значений соответствующих элементов
*/
function XMLtoArray($tegArray,$xmlDoc){
$arEnt=array();
$arEnt['tegList']=array();

$dom = new DomDocument;
$doc->validateOnParse = true;
$dom->loadXML($xmlDoc);

for($i=0,$k=0;$i<count($tegArray);$i++){
$DOMNodeList=$dom->getElementsByTagName($tegArray[$i]);
if($DOMNodeList->length>0) $arEnt['tegList'][$k++]=$tegArray[$i];
for($j=0;$j<$DOMNodeList->length;$j++){
$arEnt[$tegArray[$i]][$j]=$DOMNodeList->item($j)->nodeValue;
}
}
return $arEnt;
}

Здесь нужно знать какие элементы содержатся в документе XML, передаваемом в параметре $xmlDoc. Массив названий элементов, которые нужно извлечь из XML документа передаются в параментре $tegArray.
Все отлично работает. Возможно кому-то это тоже поможет и он не будет столько времени терять на решение достаточно распространненной операции, сколько потерял я.



Спустя 2 года, 11 часов, 17 минут, 42 секунды (13.10.2010 - 06:22) GRean написал(а):
Если не хоешь терять времени с DOM, то используй SimpleXml

Спустя 2 часа, 32 секунды (13.10.2010 - 08:22) linker написал(а):
GRean
Это ты зря, ниже код написан за 2 минуты.

function XMLtoArray()
{
$Array = array();
$Xml = new DomDocument();
$Xml->load('file.xml');
$Array = ProcessNode($Xml->documentElement);
return $Array;
}

function ProcessNode($Node)
{
$Array = array();
$TagName = $Node->localName;
foreach($Node->childNodes as $ChildNode)
{
if ($ChildNode->nodeType != XML_ELEMENT_NODE) continue;
$Array[$TagName] = ProcessNode($ChildNode);
}
return $Array;
}

Спустя 2 часа, 33 минуты, 52 секунды (13.10.2010 - 10:56) GRean написал(а):
А этот за минуту!
(шучу)

Формирует одномерный массив:

$file = 'xml.xml';

$xmlstr = file_get_contents($file);

$xml = new SimpleXMLElement($xmlstr);



foreach($xml as $node){

$arr[$node->getName()] = $node;

}


Формирует двумерный массив:

$file = 'xml.xml';

$xmlstr = file_get_contents($file);

$xml = new SimpleXMLElement($xmlstr);
$i = 0;

foreach($xml as $node){

$arr[$i][$node->getName()] = $node->attributes();

foreach($node as $node2){

$arr[$i][$node2->getName()] = $node2;


}
$i++;
}



Спустя 7 минут, 42 секунды (13.10.2010 - 11:04) linker написал(а):
GRean
Я у тебя вижу массив узлов, а нужно ассоциативный массив, в котором ключ - название тэга, а значение либо ассоциативный массив дочерних элементов, либо значение самого узла. У меня там небольшая неточность, поправил
function XMLtoArray()
{
$Xml = new DomDocument();
$Xml->load('file.xml');
if ($Xml->documentElement->childNodes->length)
return ProcessNode($Xml->documentElement);
else
return
array($Xml->documentElement->localName => $Xml->documentElement->nodeValue);
}

function ProcessNode($Node)
{
if (!$Node->childNodes->length) return $Node->nodeValue;
$Array = array();
$TagName = $Node->localName;
foreach($Node->childNodes as $ChildNode)
{
if ($ChildNode->nodeType != XML_ELEMENT_NODE) continue;
$Array[$TagName] = ProcessNode($ChildNode);
}
return $Array;
}

Спустя 2 минуты, 25 секунд (13.10.2010 - 11:06) GRean написал(а):
to linker

Я переписал код smile.gif

Спустя 8 минут, 11 секунд (13.10.2010 - 11:15) linker написал(а):
GRean
Плюс твой код не разберет xml-вида
<root>
<child>
<subchild />
<child>
</root>
элемент subchild останется за кадром.

Спустя 10 минут, 34 секунды (13.10.2010 - 11:25) GRean написал(а):
Цитата (linker @ 13.10.2010 - 08:15)
GRean
Плюс твой код не разберет xml-вида
<root>
<child>
<subchild />
<child>
</root>
элемент subchild останется за кадром.

а два <child> это не ошибка ?

Спустя 4 минуты, 41 секунда (13.10.2010 - 11:30) linker написал(а):
Очепятка, конечно
<root>
<child>
<subchild />
</child>
</root>
Чет я сам намудрил smile.gif, почти конечный вариант моего решения
<?php

function
XMLtoArray()
{
$Xml = new DomDocument();
$Xml->load('file.xml');
$Root = $Xml->documentElement;
return ($Root->childNodes->length) ? array($Root->localName => ProcessNode($Root)) : array($Root->localName => $Root->nodeValue);
}

function ProcessNode($Node)
{
$Array = array();
foreach($Node->childNodes as $ChildNode)
{
if ($ChildNode->nodeType != XML_ELEMENT_NODE) continue;
$Array[$ChildNode->localName] = ($ChildNode->childNodes->length) ? ProcessNode($ChildNode) : $Node->nodeValue;
}
return $Array;
}

?>

Спустя 51 минута, 4 секунды (13.10.2010 - 12:21) GRean написал(а):
Сможет разобрать. Массив я точно получу, вот только что ты хочешь увидеть в массиве, в котором был пустой тег. Будет просто 'Array' писаться в такой ячейке.

Приведи конкретный пример, что simpleXml не сможет разобрать. Имею ввиду xml таблицу.

А вообще я не допускаю таких пустых тегов. Обычно пишу в значение 'empty'

Спустя 26 минут, 59 секунд (13.10.2010 - 12:48) linker написал(а):
Я говорю о вложенности, о дереве узлов XML. Один узел вложен в другой и т.д. до бесконечности, в твоем примере будут обработаны только узел ROOT и все его дочерние узлы, а то что в каждом из дочерних узлов могут быть еще свои, ты забыл. Этот как дерево каталогов и файлов, которое может иметь достаточно большой уровень вложенности. Во-вторых, если значение узла пустое, то таковым и должно оставаться, не надо писать туда ничего, ибо пустое значение - это тоже значение.

Спустя 6 месяцев, 3 дня, 10 часов, 4 минуты, 45 секунд (16.04.2011 - 22:53) Стас написал(а):
Цитата (linker @ 13.10.2010 - 08:30)
Очепятка, конечно
<root>
<child>
<subchild />
</child>
</root>
Чет я сам намудрил :), почти конечный вариант моего решения
<?[SPAN=darling]php[/SPAN]

function XMLtoArray()
{
$Xml = new DomDocument();
$Xml->load('file.xml');
$Root = $Xml->documentElement;
return ($Root->childNodes->length) ? array($Root->localName => ProcessNode($Root)) : array($Root->localName => $Root->nodeValue);
}

function ProcessNode($Node)
{
$Array = array();
foreach($Node->childNodes as $ChildNode)
{
if ($ChildNode->nodeType != XML_ELEMENT_NODE) continue;
$Array[$ChildNode->localName] = ($ChildNode->childNodes->length) ? ProcessNode($ChildNode) : $Node->nodeValue;
}
return $Array;
}

?>

Здравствуйте, очень неопытному новичку поскажите как эти дву фунцкии использовать. Искал то, что надо, но вот с массивами у меня беда biggrin.gif
Покажите, пожалуйста как испытать эти функции для работы с xml
Быстрый ответ:

 Графические смайлики |  Показывать подпись
Здесь расположена полная версия этой страницы.
Invision Power Board © 2001-2024 Invision Power Services, Inc.