У меня есть простой XML-документ:
<?xml version="1.0"?> <cellphones> <telefon> <model>Easy DB</model> <proizvodjac>Alcatel</proizvodjac> <cena>25</cena> </telefon> <telefon> <model>3310</model> <proizvodjac>Nokia</proizvodjac> <cena>30</cena> </telefon> <telefon> <model>GF768</model> <proizvodjac>Ericsson</proizvodjac> <cena>15</cena> </telefon> <telefon> <model>Skeleton</model> <proizvodjac>Panasonic</proizvodjac> <cena>45</cena> </telefon> <telefon> <model>Earl</model> <proizvodjac>Sharp</proizvodjac> <cena>60</cena> </telefon> </cellphones>
Мне нужно распечатать содержимое этого файла с помощью XML DOM, и его необходимо структурировать следующим образом:
"model: Easy DB proizvodjac: Alcatel cena: 25"
для каждого узла внутри XML.
ЭТО ДОЛЖНО СДЕЛАТЬ, используя XML DOM. Это проблема. Я могу сделать это обычным, простым способом. Но это беспокоит меня, потому что я не могу найти какое-либо решение в Интернете.
Это насколько я могу идти, но мне нужно получить доступ к внутренним узлам (дочерние узлы) и получить значения узлов. Я также хочу избавиться от какой-то странной строки «#text», которая появляется неожиданно.
<?php //kreira se DOMDocument objekat $xmlDoc = new DOMDocument(); //u xml objekat se ucitava xml fajl $xmlDoc->load("poruke.xml"); //dodeljuje se promenljivoj koreni element $x = $xmlDoc->documentElement; //prolazi se kroz petlju tako sto se ispisuje informacija o podelementima foreach ($x->childNodes AS $item){ print $item->nodeName . " = " . $item->nodeValue . "<br />"; } ?>
благодаря
Объяснение для странных строк #text
Странные строки #text не выходят из синего цвета, но являются реальными текстовыми узлами. Когда вы загружаете форматированный XML-документ с DOM
любыми пробелами, например, отступы, DOMText
и значения узлов будут являться частью DOM как экземпляры DOMText
по умолчанию, например
<cellphones>\n\t<telefon>\n\t\t<model>Easy DB… ETETET
где E – DOMElement
а T – DOMText
.
Чтобы обойти это, загрузите документ следующим образом:
$dom = new DOMDocument; $dom->preserveWhiteSpace = FALSE; $dom->load('file.xml');
Затем ваш документ будет структурирован следующим образом
<cellphones><telefon><model>Easy DB… EEET
Обратите внимание, что отдельные узлы, представляющие значение DOMElement
все равно будут экземплярами DOMText
, но узлы, которые управляют форматированием, исчезли. Об этом позже.
доказательство
Вы можете легко проверить это с помощью этого кода:
$dom = new DOMDocument; $dom->preserveWhiteSpace = TRUE; // change to FALSE to see the difference $dom->load('file.xml'); foreach ($dom->getElementsByTagName('telefon') as $telefon) { foreach($telefon->childNodes as $node) { printf( "Name: %s - Type: %s - Value: %s\n", $node->nodeName, $node->nodeType, urlencode($node->nodeValue) ); } }
Этот код проходит через все элементы телефона в вашем XML и печатает имя узла, тип и значение urlencoded node его дочерних узлов. Когда вы сохраните пробелы, вы получите что-то вроде
Name: #text - Type: 3 - Value: %0A++++ Name: model - Type: 1 - Value: Easy+DB Name: #text - Type: 3 - Value: %0A++++ Name: proizvodjac - Type: 1 - Value: Alcatel Name: #text - Type: 3 - Value: %0A++++ Name: cena - Type: 1 - Value: 25 Name: #text - Type: 3 - Value: %0A++ …
Причина, по которой я присвоил значение, – показать, что на самом деле DOMText
узлы DOMText
содержащие отступы и DOMDocument
в вашем DOMDocument
. %0A
– это разрыв линии, а каждый +
– это пробел.
Когда вы сравните это с вашим XML, вы увидите, что после каждого элемента <telefon>
происходит разрыв строки, за которым следуют четыре пробела, пока не начнется элемент <model>
. Аналогично, между закрывающей <cena>
и открытием <telefon>
есть только новая строка и два пробела.
Данный тип для этих узлов равен 3, что – согласно списку предопределенных констант – это XML_TEXT_NODE
, например узел DOMText
. При отсутствии правильного имени элемента эти узлы имеют имя #text.
Пренебрежение пробелами
Теперь, когда вы отключите сохранение пробелов, вышесказанное выведет:
Name: model - Type: 1 - Value: Easy+DB Name: proizvodjac - Type: 1 - Value: Alcatel Name: cena - Type: 1 - Value: 25 Name: model - Type: 1 - Value: 3310 …
Как вы можете видеть, больше нет узлов #text, а только узлов типа 1, что означает XML_ELEMENT_NODE
, например DOMElement
.
DOMElements содержат узлы DOMText
В начале я сказал, что значения DOMElements
являются экземплярами DOMText
. Но в выводе выше их нигде не видно. Это потому, что мы получаем доступ к свойству nodeValue
, которое возвращает значение DOMText
как строку. Мы можем доказать, что это значение DOMText
легко, хотя:
$dom = new DOMDocument; $dom->preserveWhiteSpace = FALSE; $dom->loadXML($xml); foreach ($dom->getElementsByTagName('telefon') as $telefon) { $node = $telefon->firstChild->firstChild; // 1st child of model printf( "Name: %s - Type: %s - Value: %s\n", $node->nodeName, $node->nodeType, urlencode($node->nodeValue) ); }
выйдет
Name: #text - Type: 3 - Value: Easy+DB Name: #text - Type: 3 - Value: 3310 Name: #text - Type: 3 - Value: GF768 Name: #text - Type: 3 - Value: Skeleton Name: #text - Type: 3 - Value: Earl
И это доказывает, что DOMElement
содержит его значение как DOMText
а nodeValue
просто возвращает содержимое DOMText
напрямую.
Больше на nodeValue
На самом деле nodeValue
достаточно умен, чтобы DOMText
содержимое любых DOMText
:
$dom = new DOMDocument; $dom->loadXML('<root><p>Hello <em>World</em>!!!</p></root>'); $node = $dom->documentElement->firstChild; // p printf( "Name: %s - Type: %s - Value: %s\n", $node->nodeName, $node->nodeType, $node->nodeValue );
выйдет
Name: p - Type: 1 - Value: Hello World!!!
хотя это действительно совокупные значения
DOMText "Hello" DOMElement em with DOMText "World" DOMText "!!!"
Печать содержимого XML-файла с использованием XML DOM
Чтобы наконец ответить на ваш вопрос, посмотрите на первый тестовый код. Там вам нужно все, что вам нужно. И, конечно, к тому времени вам также дали хорошие ответы.
Мне кажется, что вы хотите что-то вроде этого:
<?php $dom = new DOMDocument(); $dom->load("poruke.xml"); $telefon = $dom->getElementsByTagName('telefon'); foreach ($telefon as $t) { print "model: " . $t->childNodes->item(0)->nodeValue . "\n" . "proizvodjac: " . $t->childNodes->item(1)->nodeValue . "\n" . "cena: " . $t->childNodes->item(2)->nodeValue; }
Это может быть не совсем то, что вам нужно с точки зрения форматирования, но оно должно показать вам примерно то, что вам нужно сделать.
Это решение, проверено и проверено.
<?php $xmlDoc = new DOMDocument(); $xmlDoc->load("mobiles.xml"); $x = $xmlDoc->documentElement; $telefons = $x->getElementsByTagName( "telefon" ); foreach( $telefons as $telefon ) { $model = $telefon->getElementsByTagName( "model" ); $proiz = $telefon->getElementsByTagName( "proizvodjac" ); $cena = $telefon->getElementsByTagName( "cena" ); echo $model->item(0)->nodeName .': '. $model->item(0)->nodeValue.' <br> '.$proiz->item(0)->nodeName .':'.$proiz->item(0)->nodeValue.'<br> '.$cena->item(0)->nodeName.':'.$cena->item(0)->nodeValue.' <br><br>'; } ?>
Попробуйте
$xmlDoc = new DOMDocument(); $dom->load("poruke.xml"); // Load the DomDoc into an Xpath object, you can then query it $xpath = new DOMXpath($xmlDoc); // Find all telefon elements $result = $xpath->query("//telefon"); // For each telefon item found foreach ($result AS $item){ // For each child node of the telefon element print the nodeName and nodeValue foreach($item->childNodes as $node){ echo $node->nodeName . " = " . $node->nodeValue . " <br />"; } }
Нашел довольно простой способ:
$xml = $domElement->ownerDocument->saveXML($domElement);
или если вы уже держите документ в переменной.
$xml = $document->saveXML($domElement);
решение найдено по адресу: http://php.net/manual/fr/class.domelement.php