Объяснение для странных строк #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наконец, ответьте на свой вопрос, посмотрите на первый тестовый код.Все, что вам нужно, там.И, конечно, к настоящему моменту вы получили и другие прекрасные ответы.