удаление узлов из XML с помощью PHP

Я пытаюсь удалить все NodePrices, которые не соответствуют определенному NodeName, для этого примера Place2. Вот пример XML

<DocHeader>
    <DocTitle>Node Price Report</DocTitle>
    <DocRevision>1</DocRevision>
    <DocConfidentiality>
        <DocConfClass>PUB</DocConfClass>
    </DocConfidentiality>
    <CreatedAt>2018-02-03T13:02:01</CreatedAt>
</DocHeader>
<DocBody>
  <NodePrices>
    <NodeName>Place1</NodeName>
    <Contact>Employee1</Contact>
  </NodePrices>
  <NodePrices>
    <NodeName>Place2</NodeName>
    <Contact>Employee2</Contact>
  </NodePrices>
  <NodePrices>
    <NodeName>Place3</NodeName>
    <Contact>Employee3</Contact>
  </NodePrices>
</DocBody>

Я нашел ранее заданный вопрос, который выглядит как ответ на мой вопрос, однако результаты не такие, как я ожидал. Когда я запускаю код и повторяю результаты, которых я ожидаю, я вижу Place2. Когда я сохраняю результаты в файл, Place2 отсутствует, все, что у меня есть, это DocHeader. Что я делаю неправильно?

Предыдущее сообщение: Как изменить XML-файл с помощью PHP

Вот мой PHP

$dom=new DOMDocument();
$dom->load("Nodes.xml");

$root=$dom->documentElement; 

$nodesToDelete=array();

$markers=$root->getElementsByTagName('NodePrices');

// Loop trough childNodes
foreach ($markers as $marker) {
    $NodeName=$marker->getElementsByTagName('NodeName')->item(0)->textContent;

    if($NodeName=='Place2') {
        continue;
    }

    $nodesToDelete[]=$marker;
}

// You delete the nodes
foreach ($nodesToDelete as $node) {
    $node->parentNode->removeChild($node);
}

echo $dom->saveXML();
$dom->save('FilteredNodes.xml');

person L Helmer    schedule 04.02.2018    source источник
comment
Пожалуйста, опубликуйте более полный XML с корнем и сократите повторяющиеся узлы с помощью ....   -  person Parfait    schedule 05.02.2018
comment
Как вы проверяете проблему? Как вы просматриваете файл? Вы вообще смотрите на тот файл? Я бы попробовал $dom->save(__DIR__ . '/FilteredNodes.xml'); убедиться, что файл сохраняется в том же каталоге, что и ваш скрипт.   -  person Phil    schedule 05.02.2018
comment
Только что понял, что код работает, однако он оставляет пустую строку для каждого удаленного узла. В моем случае это приводит к примерно 400 пустым строкам. Когда я проверял результаты, я не прокручивал вниз, чтобы найти нужные данные. Мой вопрос должен был быть... Как удалить все эти пустые строки? Я попробовал preg_replace(/(^[\r\n]*|[\r\n]+)[\s\t]*[\r\n]+/, \n, $string); однако это не удалило пустые строки. Все еще ищу решение.   -  person L Helmer    schedule 05.02.2018
comment
@LHelmer ... чтобы помочь, опубликуйте полный XML-файл. Прямо сейчас в вашем сообщении нет корневого элемента, который не является правильно сформированным XML.   -  person Parfait    schedule 05.02.2018


Ответы (1)


При удалении узла в XML и DOM обычно остается пробел. Это связано с форматированием документа и тем, что обычно узел DOMText предшествует фактическому узлу данных. Чтобы закрыть этот пробел, вам также необходимо удалить этот узел, а также данные...

foreach ($nodesToDelete as $node) {
    $prevNode = $node->previousSibling;
    if ( $prevNode != null && $prevNode instanceof DOMText )    {
        $node->parentNode->removeChild($prevNode);
    }
    $node->parentNode->removeChild($node);
}
person Nigel Ren    schedule 05.02.2018