Печать содержимого файла XML с использованием XML DOM - PullRequest
4 голосов
/ 05 января 2011

У меня есть простой 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 />";
    }
?>

Спасибо

Ответы [ 5 ]

6 голосов
/ 05 января 2011

Объяснение для странных строк #text

Странные строки #text не появляются на ровном месте, но являются фактическими текстовыми узлами.Когда вы загружаете отформатированный документ XML с DOM, любые пробелы, например, отступы, разрывы строк и значения узлов, будут частью DOM как DOMText экземпляры по умолчанию, например,

<cellphones>\n\t<telefon>\n\t\t<model>Easy DB…
E           T   E        T     E      T      

, где E - это DOMElement, а T - это DOMText.

Чтобы обойти это, загрузите документ следующим образом:

$dom = new DOMDocument;
$dom->preserveWhiteSpace = FALSE;
$dom->load('file.xml');

Тогда ваш документ будет структурирован следующим образом

<cellphones><telefon><model>Easy DB…
E           E        E      T

Обратите внимание, что отдельные узлы, представляющие значение 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-файле и выводит имя, тип и значение узла в его дочерних узлах.Когда вы сохраняете пробел, вы получите что-то вроде

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 узлов содержат отступ и разрывы строк в вашем 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.

Элементы DOME содержат узлы 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 потомков:

$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

Toнаконец, ответьте на свой вопрос, посмотрите на первый тестовый код.Все, что вам нужно, там.И, конечно, к настоящему моменту вы получили и другие прекрасные ответы.

2 голосов
/ 05 января 2011

Это решение, проверенное и опробованное.

<?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>';

  }


?>
2 голосов
/ 05 января 2011

Попробуй

$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 />";
    }
}
2 голосов
/ 05 января 2011

Мне кажется, что вы хотите что-то вроде этого:

<?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;
}

Это может быть не совсем то, что вам нужно с точки зрения форматирования, но оно должно показывать вам примерно то, что вам нужно сделать.

0 голосов
/ 14 августа 2014

Нашел довольно простой способ:

$xml = $domElement->ownerDocument->saveXML($domElement);

или если вы уже содержали документ в переменной.

$xml = $document->saveXML($domElement);

решение найдено по адресу: http://php.net/manual/fr/class.domelement.php

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...