php dom XML элементы цикла сохраняют детские

Итак, у меня есть XML-файл, как

<cars>
<id>1</id>
<photos>
<img>http://sit.com/img.jpg</img>
<img>http://sit.com/img.jpg</img>
<img>http://sit.com/img.jpg</img>
<img>http://sit.com/img.jpg</img>
</photos>
</cars>

Поэтому мне нужно изменить все имя тега на альтернативное, и мне нужно получить что-то вроде

<cars>
<ex_id>1</ex_id>
<images>
<photo>http://sit.com/img.jpg</photo>
<photo>http://sit.com/img.jpg</photo>
<photo>http://sit.com/img.jpg</photo>
<photo>http://sit.com/img.jpg</photo>
</images>
</cars>

Мой код

foreach ($dom->getElementsByTagName('cars') as $item) {
for ($i = 0; $i < $item->childNodes->length; ++$i) {
$car = $item->childNodes->item($i);
$NewElement = $dom->createElement($newName,$value);
$car->parentNode->replaceChild($NewElement->cloneNode(TRUE), $car);
}
}

Сделать что-то подобное

<cars>
<ex_id>1</ex_id>
<images/>
</cars>

Так что порезали всех детей <photos>, поэтому мой вопрос, как сохранить детей, а также изменить теги детей от <img> в <photo>

0

Решение

Вот несколько вопросов:

  1. getElementByTagName () и $ childNodes возвращают «живые» списки, они меняются, если вы меняете DOM. Вы можете использовать iterator_to_array (), чтобы скопировать их в массив.

  2. Здесь находятся не только узлы элементов. Комментарии, разделы cdata и текст (даже содержащий только пробелы) также являются узлами. Если вы перебираете $ childNodes, вам нужно будет проверить DOMNode :: $ nodeType.

  3. Не используйте второй аргумент DOMDocument :: createElement (). У него сломан побег. Создайте текстовый узел и добавьте его.

1 и 2 уходят, если вы используете Xpath для извлечения узлов.

$dom = new DOMDocument();
$dom->loadXml($xml);
$xpath = new DOMXPath($dom);

foreach ($xpath->evaluate('/cars/images/img') as $photo) {
$newNode = $dom->createElement('photo');
$newNode->appendChild($dom->createTextNode($photo->textContent));
$photo->parentNode->replaceChild($newNode, $photo);
}

echo $dom->saveXml();

Выход:

<?xml version="1.0"?>
<cars>
<ex_id>1</ex_id>
<images>
<photo>http://sit.com/img.jpg</photo>
<photo>http://sit.com/img.jpg</photo>
<photo>http://sit.com/img.jpg</photo>
<photo>http://sit.com/img.jpg</photo>
</images>
</cars>

Изменение документа DOM часто является плохой идеей. Проще извлечь данные из исходного документа и создать новый целевой документ:

$source = new DOMDocument();
$source->loadXml($xml);
$xpath = new DOMXPath($source);

$target = new DOMDocument();
$target->formatOutput = TRUE;

$cars = $target->appendChild($target->createElement('cars'));
$cars
->appendChild($target->createElement('ex_id'))
->appendChild(
$target->createTextNode(
$xpath->evaluate('string(/cars/id)')
)
);

$images = $cars->appendChild($target->createElement('images'));

foreach ($xpath->evaluate('/cars/photos/img') as $photo) {
$images
->appendChild($target->createElement('photo'))
->appendChild($target->createTextNode($photo->textContent));
}

echo $target->saveXml();

Выход:

<?xml version="1.0"?>
<cars>
<ex_id>1</ex_id>
<images>
<photo>http://sit.com/img.jpg</photo>
<photo>http://sit.com/img.jpg</photo>
<photo>http://sit.com/img.jpg</photo>
<photo>http://sit.com/img.jpg</photo>
</images>
</cars>

Вот язык, посвященный преобразованию XML — XSLT. XSLT поддерживается PHP ext/xsl,

1

Другие решения

Других решений пока нет …