使用 SimpleXML/DOM 通过 php 将节点从一个 XML 复制到另一个

Posted

技术标签:

【中文标题】使用 SimpleXML/DOM 通过 php 将节点从一个 XML 复制到另一个【英文标题】:Using SimpleXML/DOM to copy node from one XML to another via php 【发布时间】:2021-03-25 16:00:12 【问题描述】:

我目前正在尝试将节点从一个 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>

我想从 2.xml 中获取每个 &lt;OrderItems&gt; 节点及其所有子节点,并附加到 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();

这正确地在我需要的地方附加了一个“项目”,但是从 foreach 函数的最后一行发送的信息似乎不起作用,因为运行脚本后“项目”标签为空。

我可能需要恢复到 DOM XML 操作来实现我正在尝试的内容,但我更熟悉 SimpleXML 表示法,所以我想我会尝试这种方式。困难在于需要将 OrderId 123456789 的项目附加到正确的顺序下。非常感谢任何指针。到达后,我将使用正确的解决方案更新帖子。我了解使用 php DOM,我可以使用 xpath 导航到正确的正确节点,但是我不确定如何继续执行此操作,因为 OrderId 未存储为属性。我已经使用 DOM 手册编写了此摘录,但是我不确定如何继续将节点附加到正确的位置。目前它只是在文档末尾添加了一个孩子。

我对 DOM XML 处理的问题是如何导航到 SuccessResponse->Body->Orders->OrderId 并分配给该节点的特定文本,例如 123456789,然后在 OrderId 之前附加到节点,所以附加为一个订单的孩子

$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();

【讨论】:

以上是关于使用 SimpleXML/DOM 通过 php 将节点从一个 XML 复制到另一个的主要内容,如果未能解决你的问题,请参考以下文章

通过 XMLHttpRequest 将 gettext 与 PHP 中的 Javascript 一起使用

通过 PHP 使用 *** 的服务

如何通过 cURL/PHP 使用 PUT 方法将 JSON 数据发送到 API

如何:正确使用PHP将数据编码成JSON格式,并通过jquery/ajax请求数据

jcrop 在上传之前是不是通过将 xy 发送到 php 进行裁剪来工作?

使用PHP和cURL通过它们的API将文件上传到RapidShare