Только для читателей Lifeexample возможно открыть интернет-магазин на Moguta.CMS со скидкой в 15%
Работа с XML в PHP
Здравствуйте, уважаемые читатели блога LifeExample, в этой статье "Работа с XML в PHP" я расскажу о том, как считывать, перезаписывать, удалять и производить php запись в xml файл. А так же о том, как в принципе быстро и удобно создать и поместить данные в xml разметку. Будучи студентом работая над своими проектами, я самостоятельно писал библиотеки для обработки XML документов. Я очень рад, что теперь мне не приходится пользоваться своими велосипедами т.к. есть готовые решения присутствующие в PHP по умолчанию.
Работа с XML в PHP — PHP запись в XML
Инструмент XMLWriter был создан специально для записи в XML формате. Один из важных его методов это startDocument(), который позволяет задать кодировку версии XML.
Попробуем создать простенький XML следующего вида:
1 2 3 4 5 6 | <?xml version="1.0"?> <Customer> <id>1</id> <name>Марк</name> <address>Санкт-Петербург</address> </Customer> |
Получить такой формат можно с помощью XMLWriter таки вот образом:
1 2 3 4 5 6 7 8 9 10 11 12 | <?php //Простой пример $xml = new XMLWriter(); //создаем новый экземпляр класса XMLWriter $xml->openMemory(); //использование памяти для вывода строки $xml->startDocument(); //установка версии XML в первом теге документа $xml->startElement("Customer"); //создание корневого узла $xml->writeElement("id", "1"); $xml->writeElement("name", "Марк"); //запись элемента $xml->writeElement("address", "Санкт-Петербург"); $xml->endElement(); //закрытие корневого элемента echo $xml->outputMemory(); //завершение записи в XML ?> |
Как видите, Работа с XML в PHP, благодаря XMLWriter становится невероятно простой, и сильно облегчает задачи записи XML формата. Далее приведу маленький комплекс примеров о том, как осуществить, на php запись в xml. Например, задача поставлена — получить файл XML в следующем формате:
1 2 3 4 5 6 7 8 9 10 11 12 13 | <xml version="1.0"?> <purchase> <customer> <id>1</id> <time>2013-04-19 10:56:03</time> <total>$350</total> </customer> <customer> <id>2</id> <time>2013-04-23 13:43:41</time> <total>$1456</total> </customer> </purchase> |
Чтобы получить такую структуру нужно выполнить ряд не хитрых методов класса XMLWriter.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | <?php $xml = new XMLWriter(); $xml->openMemory(); $xml->startDocument(); $xml->startElement("purchase"); $xml->startElement("customer"); //открытие элемента первого покупателя с ID = 1 $xml->writeElement("id", 1); $xml->writeElement("time", "2013-04-19 10:56:03"); $xml->writeElement("total", "$350"); $xml->endElement(); //закрытие элемента первого покупателя с ID = 1 $xml->startElement("customer"); //Открытие элемента второго покупателя с ID = 2 $xml->writeElement("id", 2); $xml->writeElement("time", "2013-04-23 13:43:41"); $xml->writeElement("total", "$1456"); $xml->endElement(); //закрытие элемента первого покупателя с ID = 2 $xml->endElement(); echo $xml->outputMemory(); ?> |
Следующий пример покажет, как добавлять атрибуты к узлам XML дерева, согласитесь это довольно востребованная задача в проектах, где необходима работа с XML.
1 2 3 4 5 6 7 8 9 10 11 12 13 | <?xml version="1.0"?> <products> <product pid="314"> <name>Яблоко</name> <price>$1.00</price> <discount>3%</discount> </product> <product pid="315"> <name>Манго</name> <price>$0.90</price> <discount>3%</discount> </product> </products> |
С помощью XMLWriter, делается это так:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | <?php $xml = new XMLWriter(); $xml->openMemory(); $xml->startDocument(); $xml->startElement("products"); $xml->startElement("product"); $xml->writeAttribute("pid", 314); $xml->writeElement("name", "Яблоко"); $xml->writeElement("price", "$1.00"); $xml->writeElement("discount", "3%"); $xml->endElement(); $xml->startElement("product"); $xml->writeAttribute("pid", 315); $xml->writeElement("name", "Манго"); $xml->writeElement("price", "$0.90"); $xml->writeElement("discount", "3%"); $xml->endElement(); $xml->endElement(); echo $xml->outputMemory(); ?> |
Работа с XML в PHP — Чтение и получение данных из XML
Ниже будет приведен пример чтения и получения данных из XML с использованием классов XMLReader и SimpleXMLElement. Читать будем уже имеющийся XML объект, который мы создали в примере №1 при PHP записи в XML.
XMLReader используется для получения заданного узла из XML.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | // Чтение XML формата $rxml = new XMLReader(); //Создание элемента для чтения $rxml->xml($nXML); //Загрузка XML, $nXML - строка в формате XML //Переместиться к первому элементу customer while($rxml->read() && $rxml->name !== 'customer'); $amountSpent = 0; //Получим значение поля total у второго узла дерева while($rxml->name === 'customer'){ //Чтение текущего дочернего через SimpleXMLElement $node = new SimpleXMLElement($rxml->readOuterXML()); //Проверяем, номер элемента, если он равен 2 то это искомый элемент if($node->id == 2){ $amountSpent = $node->total; break; } //Переместиться к следующему элементу customer $rxml->next('customer'); } echo $amountSpent; |
Часто задача возникает в получении данных из XML по значению, какого либо атрибута. Давайте по примеру №2 из раздела PHP запись в XML, получим название, цену и скидку продукта по его атрибуту pid = 315.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | $rxml = new XMLReader(); $rxml->xml($nXML2); while($rxml->read() && $rxml->name !== 'product');//Перемещаемся к первому продукту $name = ""; $price = ""; $discount = ""; while($rxml->name === 'product'){ if($rxml->getAttribute("pid") == "315") //если pid = 315 то это искомый элемент { $node = new SimpleXMLElement($rxml->readOuterXML());//читаем значение элементов $name = $node->name; $price = $node->price; $discount = $node->discount; break; } $rxml->next('product'); //перемещаемся к следующему } echo "Продукт №315. Наименование: {$name}, цена: {$price} скидка: {$discount}"; |
Работа с XML в PHP — Добавление узлов дерева в существующий XML
Работая с XML в PHP, не редко приходится ломать голову над тем как добавить новый элемент в имеющуюся XML структуру. Используя XMLWriter и SimpleXMLElement сделать это очень легко:
1 2 3 4 5 6 7 8 9 | //Добавим новый узел в имеющийся XML $sXML = new SimpleXMLElement($nXML2); // загрузка в XML $newchild = $sXML->addChild("product"); //Добавление параметров записи $newchild->addAttribute("pid", 328); $newchild->addChild("name", "Банан"); $newchild->addChild("price", "$3.00"); $newchild->addChild("discount", "0.3%"); echo $sXML->asXML(); |
Работа с XML в PHP — Перезапись элементов существующего XML
При активной работе с XML в PHP, приходится не только считывать и записывать элементы, но и редактировать имеющиеся. Перезапись существующего узла дерева XML может быть реализована следующим образом:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | /** * Перезапись узлов дерева XML формата. */ $productId = 314; $parent = new DomDocument; // создаем новый элемент дома product $parent_node = $parent->createElement('product'); //Добавляем атрибут $attribute = $parent->createAttribute("pid"); //устанавливаем значение $attribute->value = $productId; $parent_node->appendChild($attribute); // Добавляем дочерний элементы $parent_node->appendChild($parent->createElement('name', "Яблоко")); $parent_node->appendChild($parent->createElement('price', "$2.00")); $parent_node->appendChild($parent->createElement('discount', "1%")); //Вставляем созданные элементы в создаваемый 'product' $parent->appendChild($parent_node); // Загружаем оригинальный XML формат $dom = new DomDocument; $dom->loadXML($nXML); // Находим имеющийся элемент с pid = 314 $xpath = new DOMXpath($dom); $nodelist = $xpath->query("/products/product[@pid={$productId}]"); $oldnode = $nodelist->item(0); // Импортируем созданый ранее элемент в текущее дерево $newnode = $dom->importNode($parent->documentElement, true); // заменяем страрый элемент на новый $oldnode->parentNode->replaceChild($newnode, $oldnode); // сохраняем XML echo $dom->saveXML(); |
Работа с XML в PHP — Удаление элементов XML
Из всего выше рассмотренного, осталась только одна операция, без которой данную статью о работе с XML в PHP , нельзя считать завершенной – это удаление элементов. Удаление элементов самое легкое из всей связки операций. Ну что же, ломать – не стоить, давайте удалим один из продуктов.
1 2 3 4 5 6 7 8 9 10 11 12 13 | //Удаление продукта Манго //загрузим оригинальный формат XML $productId = 315; $dom = new DomDocument; $dom->loadXML($nXML2); // Найдем элемент который необходимо удалить $xpath = new DOMXpath($dom); $nodelist = $xpath->query("/products/product[@pid={$productId}]"); $oldnode = $nodelist->item(0); // Удаляем элемент $oldnode->parentNode->removeChild($oldnode); echo $dom->saveXML(); |
Закрыть текущий элемент (тэг) в xmlwriter
1 | $xml->endDTDElement(); // закрыть текущий <tag attr='1' /> |
Найдя время и отвлекшись от основного своего проекта, я всё-таки опубликовал действительно полезную статью "Работа с XML в PHP", и надеюсь она пригодится в своих разработках. Пишите мне на e-mail, с какими задачами вы сталкиваетесь, и я попробую сформировать материал по их решению в следующих статьях
Читайте также похожие статьи:
Чтобы не пропустить публикацию следующей статьи подписывайтесь на рассылку по E-mail или RSS ленту блога.
Комментарии
К сожалению в моем рнр у провайдера nic.ru по умолчанию классы из вашей строки не существуют
Fatal error: Class ‘XMLReader’ not found in /home/smelloftea/smelloftea.ru/docs/subdmn/billing/ajax1.php on line 16
Где мне взять эти классы для помещения на свой сайт?
Задайте, данный вопрос своем хостинг-провайдеру. Насколько я знаю у nic.ru можно самостоятельно подключать необходимые библиотеки прямо из панели управления.
Такое впечатление, что у вас где-то опечатка.
Я сделал все по вашем рекомендациям, но выходит ошибка
мой XML файл
18533883886651968791782864205137
1019
№1-836
275123457
ошибка в этой строке (#19):
while($rxml->read() && $rxml->name !== ‘stb_item’);
сообщения:
Warning: XMLReader::read() [xmlreader.read]: /home/smelloftea/smelloftea.ru/docs/subdmn/billing/:1: parser error : Document is empty in /home/smelloftea/smelloftea.ru/docs/subdmn/billing/ajax1.php on line 19
Warning: XMLReader::read() [xmlreader.read]: <?xml version="1.0" encoding="utf-8"?> in /home/smelloftea/smelloftea.ru/docs/subdmn/billing/ajax1.php on line 19
Warning: XMLReader::read() [xmlreader.read]: ^ in /home/smelloftea/smelloftea.ru/docs/subdmn/billing/ajax1.php on line 19
Warning: XMLReader::read() [xmlreader.read]: An Error Occured while reading in /home/smelloftea/smelloftea.ru/docs/subdmn/billing/ajax1.php on line 19
Попробуйте пример из архива с исходным кодом в конце статьи.
Не сомневаюсь, что с примером в конце статьи все хорошо, но я не могу решить свою проблему. Я должен обработать XML сообщение. При помощи Javascript я сообщение с экрана поместил в переменную и передал PHP скрипту для получения информации с помощью XMLReader. Я понял, что во время передачи метом POST символы » поменялись на ‘<‘ и ‘>’, что и вызывает сообщение об ошибки у XMLReader::get(). Как мне вернуть прежние » ?
PHP функция str_replace не помогает.
Или есть другой способ получения XML-строки?
Попробуйте полученную переменную прогнать через htmlspecialchars_decode.
Как можно получить XML строку для работы с ней в PHP из выведенного на экран сообщения в виде XML не используя Javascript?
С помощью библиотеки curllib.dll, как ее подкючить чтиайте в статье: http://lifeexample.ru/razrabotka-i-optimizacia-saita/fatal-error-call-to-undefined-function-curl_init.html
Честно говоря немного не понятно про чтение XML.
Если я пытаюсь прочитать к примеру какой то уже готовый XML файл …
Я должен указать
$rxml->open(‘test.xml’))
так ?
нет, нужно передать в метод ниже строку в формате XML
получить строку из XML файла можно так:
Здравствуйте! Может Вы подскажите. Работал с кодировкой cp1251. Начинал делать сайт в этой кодировке. Имеются скрипты Ajax с передачей данных на сервер и, соответственно, чтением результатов обработки сервера на стороне клиента через XML. Все прекрасно работало. Но потом решил перевести сайт в кодировку UTF-8. Перезаписал скрипты и базу данных в эту кодировку. Но столкнулся с проблемой. Клиент передает с помощью Ajax данные PHP-скрипту на сервер. Тот их обрабатывает, делает перезапись в БД, но не формирует XML файл для получения ответа клиенту. На выходе получается обычный HTML документ. Хотя при cp1251 прекрасно формировался XML.
Формирую так:
2
3
4
5
6
7
$xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<response>
<res_pas id_uz='$id_uzer'>$res</res_pas>
</response>";
echo $xml;
В чем может быть проблема?
На выходе получаю такое:
2
3
4
5
6
7
8
9
<html>
<head></head>
<body>
<response>
<res_pas id_uz="6">4</res_pas>
</response>
</body>
</html>
Т.е. заголовок стоит вроде XML, а в реалии обычный HTML-документ.
Хотя, когда работал с cp1251, этот код выводил именно XML-документ. Естественно при той кодировке файл и запись encoding была cp1251.
Да, пробовал и Вашим способом создавать XML. Результат тот же.
А как вы принимаете этот XML в клиенте, может там нужно явно тип указать?
Имеем выгрузку из 1с в формате commerceml (xml). По факту характеристики у товаров заполнялись «абы как» и пробил час, когда они стали необходимы, но возможности как следует их записать уже нет.
Есть только вариант прописать их построчно в элемент .
например
Диаметр=100мм
Длина=120мм
Таким образом получаем в выгрузке
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<Ид>001bfc8d17d7</Ид>
<Наименование>Название товара</Наименование>
<БазоваяЕдиница Код="796" НаименованиеПолное="Штука" МеждународноеСокращение="">шт</БазоваяЕдиница>
<ЗначенияРеквизитов>
<ЗначениеРеквизита>
<Наименование>ВидНоменклатуры</Наименование>
<Значение>Товар</Значение>
</ЗначениеРеквизита>
<ЗначениеРеквизита>
<Наименование>ТипНоменклатуры</Наименование>
<Значение>Товар</Значение>
</ЗначениеРеквизита>
<ЗначениеРеквизита>
<Наименование>Полное наименование</Наименование>
<Значение>Здесь полное название товара</Значение>
</ЗначениеРеквизита>
</ЗначенияРеквизитов>
<СтавкиНалогов>
<СтавкаНалога>
<Наименование>НДС</Наименование>
<Ставка>18</Ставка>
</СтавкаНалога>
</СтавкиНалогов>
<Группы>
<Ид>001bfc8d17d7</Ид>
</Группы>
<Описание>Диаметр=100мм
Длина=120мм
</Описание>
</Товар>
Требуется каждую характеристику (Диаметр,Длина) записать в этот же файл должным образом, а значение элемента удалить (или вообще удалить весь этот элемент), то есть чтобы получилось так
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<Ид>001bfc8d17d7</Ид>
<Наименование>Название товара</Наименование>
<БазоваяЕдиница Код="796" НаименованиеПолное="Штука" МеждународноеСокращение="">шт</БазоваяЕдиница>
<ЗначенияРеквизитов>
<ЗначениеРеквизита>
<Наименование>ВидНоменклатуры</Наименование>
<Значение>Товар</Значение>
</ЗначениеРеквизита>
<ЗначениеРеквизита>
<Наименование>ТипНоменклатуры</Наименование>
<Значение>Товар</Значение>
</ЗначениеРеквизита>
<ЗначениеРеквизита>
<Наименование>Полное наименование</Наименование>
<Значение>Здесь полное название товара</Значение>
</ЗначениеРеквизита>
</ЗначенияРеквизитов>
<СтавкиНалогов>
<СтавкаНалога>
<Наименование>НДС</Наименование>
<Ставка>18</Ставка>
</СтавкаНалога>
</СтавкиНалогов>
<Группы>
<Ид>001bfc8d17d7</Ид>
</Группы>
<ХарактеристикиТовара>
<ХарактеристикаТовара>
<Наименование>Диаметр</Наименование>
<Значение>100мм</Значение>
</ХарактеристикаТовара>
<ХарактеристикаТовара>
<Наименование>Длина</Наименование>
<Значение>120мм</Значение>
</ХарактеристикаТовара>
</ХарактеристикиТовара>
</Товар>
Я смог только выдернуть характеристики из элемента и придать им нужный вид вот этим кодом
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
$reader->open($file);
while ($reader->read()) {
switch ($reader->nodeType) {
case (XMLREADER::ELEMENT):
if ($reader->localName == "Описание") {
$reader->read();
$rparams = explode("\n", $reader->value);
$newitem = "<ХарактеристикиТовара>\n";
foreach ($rparams as $rparam) {
$pieces = explode("=", $rparam);
$newitem .= "<ХарактеристикаТовара>\n";
$newitem .= "<Наименование>".$pieces[0]."</Наименование>\n";
$newitem .= "<Значение>".$pieces[1]."</Значение>\n";
$newitem .= "</ХарактеристикаТовара>\n";
}
$newitem .= "</ХарактеристикиТовара>\n";
echo $newitem;
}
}
}
Но как теперь записать это в файл, точнее заменить Описание на ХарактеристикиТовара — никак не пойму … может кто подскажет?
Добрый день,
$xml->openURI(‘test.xml’);
А как сделать чтобы test.xml записался в другую папку на другом сайте через фтп.
Спасибо.
Учитель ты хренов…
«Работа с XML в PHP – Добавление узлов дерева в существующий XML»… И что??? Где новый элемент, как было? Как стало после???
Может тебе это все и так понятно, а не опытному человеку ни хрена не понятно. Так что если вздумал учить — то разжовывай как первоклассникам…