#php #xml #dom #simplexml
#php #xml #dom #simplexml
Вопрос:
В настоящее время я пытаюсь скопировать узлы из одного XML в другой. Скажем, у нас есть 1.xml следующим образом:
///THIS IS 1.XML
<SuccessResponse>
<Body>
<Orders>
<Order>
<OrderId>123456789</OrderId>
...
</Order>
<Order>
<OrderId>987654321</OrderId>
...
</Order>
</Orders/>
</Body>
</SuccessResponse>
И 2.xml следующим образом:
<SuccessResponse>
<Body>
<Orders>
<Order>
<OrderId>123456789</OrderId>
<OrderItems>
<OrderItem>
...
</OrderItem>
<OrderItem>
...
</OrderItem>
</OrderItems>
</Order>
<Order>
<OrderId>987654321</OrderId>
<OrderItems>
<OrderItem>
...
</OrderItem>
<OrderItem>
...
</OrderItem>
</OrderItems>
</Order>
</Orders/>
</Body>
</SuccessResponse>
Я хотел бы взять КАЖДЫЙ <OrderItems>
узел и все его дочерние элементы из 2.xml и добавить к правильному узлу в 1.xml . Оба XML-файла будут находиться в определенном порядке, так что первый тег будет иметь одинаковый, и я создал массив, который будет содержать все это. До сих пор я писал это:
$idsarray = range(0, count($ids)-1); //idsarray is array of order Ids. this transforms into a list: 0, 1... etc. counting how many orders i have requested
$itemsxml = new SimpleXMLElement($orderitemresponse); //$orderitemresponse is XML string with 2.xml
$ordersxml = new SimpleXMLElement($getordersRESPONSE); //$getordersRESPONSE is XML string with 1.xml
foreach ($idsarray as $orderno) {
$item = $itemsxml->Body->Orders->Order[$orderno]->OrderItems;
$ordersxml->Body->Orders->Order[$orderno]->addChild('Items');
$ordersxml->Body->Orders->Order[$orderno]->Items = $item;
}
echo $ordersxml->asXML();
Это правильно добавляет ‘Items’ там, где мне это нужно, но информация, отправленная из последней строки функции foreach, не кажется функциональной, поскольку тег ‘Items’ пуст после запуска скрипта.
Возможно, мне придется вернуться к работе с DOM XML, чтобы добиться того, что я пытаюсь, но я больше знаком с нотацией SimpleXML, поэтому я подумал, что попробую этот способ. Трудность возникает из-за того, что элементы для OrderID 123456789 должны быть добавлены в правильном порядке. Любые указатели очень приветствуются. Я обновлю сообщение с правильным решением, когда оно будет достигнуто. Я понимаю, что с php DOM я мог бы использовать xpath для перехода к правильному правильному узлу, однако я не уверен, как поступить с этим, поскольку OrderID не сохраняется как атрибут. Я написал этот отрывок, используя руководство по DOM, однако я не уверен, как продолжить добавление узла в правильное местоположение. На данный момент он просто добавляет дочерний элемент в конец документа.
Мой вопрос для обработки DOM XML заключается в том, как перейти к SuccessResponse-> Body-> Orders-> OrderID с определенным текстом, назначенным этому узлу, например, 123456789, а затем добавить к узлу ПЕРЕД OrderID, поэтому добавляйте в качестве ДОЧЕРНЕГО элемента к Orders
$itemxml = new DOMDocument;
$itemxml->formatOutput = true;
$itemxml = DOMDocument::loadXML($orderitemresponse);
$orderxml = new DOMDocument;
$orderxml->formatOutput = true;
$orderxml = DOMDocument::loadXML($getordersRESPONSE);
$idsarray = range(0, count($ids)-1); //creates counting total orders
foreach ($idsarray as $orderno) {
$i = $itemxml->getElementsByTagName("OrderItems")[$orderno];
$node = $orderxml->importNode($i, true);
$orderxml->documentElement->appendChild($node);
}
echo $orderxml->saveXML();
ОБНОВЛЕНИЕ: я считаю, что я решил эту проблему. Для тех, кто заинтересован:
$itemxml = new DOMDocument;
$itemxml->formatOutput = true;
$itemxml = DOMDocument::loadXML($orderitemresponse);
$orderxml = new DOMDocument;
$orderxml->formatOutput = true;
$orderxml = DOMDocument::loadXML($getordersRESPONSE);
$idsarray = range(0, count($ids)-1); //creates counting total orders
foreach ($idsarray as $orderno) {
$i = $itemxml->getElementsByTagName("OrderItems")[$orderno];
$node = $orderxml->importNode($i, true);
$parent = $orderxml->getElementsByTagName("Order")[$orderno];
$parent->appendChild($node);
}
echo $orderxml->saveXML();
Ответ №1:
Вы можете сделать это немного более стабильным, используя выражения Xpath для сопоставления OrderId
значений.
// bootstrap the DOMs
$sourceDocument = new DOMDocument();
$sourceDocument->loadXML($itemsXML);
$sourceXpath = new DOMXpath($sourceDocument);
$targetDocument = new DOMDocument();
$targetDocument->loadXML($targetXML);
$targetXpath = new DOMXpath($targetDocument);
// iterate the target orders
foreach ($targetXpath->evaluate('//Order') as $order) {
// get the order id
$orderId = $targetXpath->evaluate('string(OrderId)', $order);
// iterate the OrderItems elements for a specific order id
foreach($sourceXpath->evaluate('//Order[OrderId="'.$orderId.'"]/OrderItems') as $items) {
// import and append
$order->appendChild($targetDocument->importNode($items, TRUE));
}
}
echo $targetDocument->saveXML();