PHP XML DOM Document在子节点内移动子节点

时间:2018-07-19 08:56:38

标签: domdocument php-7 clonenode

我有一个像这样的xml:

td:not(:empty) {
   background-color: #9ac99d;
}

尽管可以肯定有更好的方法, 解析所有订单,我建立了一个像这样的例程:

<?xml version="1.0" encoding="UTF-8"?>
<OrderListResponse>
  <OrderListResponseContainer>
    <DateFrom>2018-07-01T00:00:00+00:00</DateFrom>
    <DateTo>2018-07-19T00:00:00+00:00</DateTo>
    <Page>1</Page>
    <TotalNumberOfPages>4</TotalNumberOfPages>
    <Orders>
      <Order>
        <OrderID>158772</OrderID>
        <Customer>
          <Name><![CDATA[John Smith]]></Name>
          <StreetAddress><![CDATA[33, Sunset Boulevrd]]></StreetAddress>
        </Customer>
        <Delivery>
          <Name><![CDATA[John Smith]]></Name>
          <StreetAddress><![CDATA[47, Rodeo Drive]]></StreetAddress>
        </Delivery>
        <Billing>
          <Name><![CDATA[John Smith]]></Name>
          <StreetAddress><![CDATA[33, Sunset Boulevrd]]></StreetAddress>
        </Billing>
        <Payment>
          <Module>paypal</Module>
          <TransactionID/>
        </Payment>
        <DatePurchased>2018-07-01 16:30:42</DatePurchased>
        <DateLastModified>2018-07-02 21:08:28</DateLastModified>
        <CheckoutMessage><![CDATA[]]></CheckoutMessage>
        <Status>cancelled</Status>
        <Currency>EUR</Currency>
        <Products>
          <Product>
            <MxpID>44237</MxpID>
            <SKU>IRF 8707TR</SKU>
            <Quantity>3</Quantity>
            <Price>2.46</Price>
          </Product>
        </Products>
        <Total>
          <SubTotal>7.38</SubTotal>
          <Shipping>2.7</Shipping>
          <Cod>0</Cod>
          <Insurance>0</Insurance>
          <Tax>1.62</Tax>
          <Total>11.7</Total>
        </Total>
      </Order>
      <Order>...</Order>
     </Orders>
  </OrderListResponseContainer>
</OrderListResponse>
  

****添加****
  我使用嵌套循环为每个产品创建一个xml(每个xml包含有关买方,商品和商品的详细信息   销售),然后将此xml传递到存储过程以生成   用户/物品/销售记录:出于多种原因,我无法批量导入   用户,然后是商品,然后是销售,但在构建销售XML时   我需要从“总节点”中获取一些细节,获取它们的一种方法是   将“总节点”移到XML的顶部,但显然要移到“订购”节点内
  ****添加****

在处理产品之前,我需要访问一些Total子节点 我发现的唯一解决方案是在开始时移动Total节点,但是尽管进行了多次尝试,但我仍未能成功: 这个想法是克隆$xmlDoc = new DOMDocument(); $xmlDoc->preserveWhiteSpace = false; $xmlDoc->loadXML($response); $xpath = new DOMXPath($xmlDoc); $rootNode = $xpath->query('//OrderListResponseContainer/Orders')->item(0); foreach($rootNode->childNodes as $node) { foreach($node->childNodes as $subnode) { Process User foreach($subnode->childNodes as $subsubnode) { foreach($subsubnode->childNodes as $subsubsubnode) { Process Products and Sales } } } } totalNode appendbefore节点

问题是我需要处理子文档并选择要从节点本身克隆的节点,而我发现的所有示例都克隆了完整的OrderID

也许可以使用DocumentElement来实现更简单的解决方案?

可以提出解决方案吗?

1 个答案:

答案 0 :(得分:1)

我不完全了解您要说的克隆部分。也许您可以编辑问题并弄清楚您的意思。

但是,关于访问Total节点...您也可以简单地使用XPath。

$xmlDoc = new DOMDocument();
$xmlDoc->preserveWhiteSpace = false;
$xmlDoc->loadXML($response);
$xpath = new DOMXPath($xmlDoc);

// first, let's fetch all <Order> elements
$orders = $xpath->query('//OrderListResponseContainer/Orders/Order');

// loop through all <Order> elements
foreach( $orders as $order ) {
  /*
    There's all sorts of ways you could convert <Total> to something useful
  */

  // Example 1.
  // fetch <Total> that is a direct child (./) of our context node (second argument) $order
  $total = $xpath->query( './Total', $order )->item( 0 );

  // then do something like
  $subTotal = $total->getElementsByTagName( 'SubTotal' )->item( 0 );
  $shipping = $total->getElementsByTagName( 'Shipping' )->item( 0 );
  // ... etc. for each child node of <Total>

  // or perhaps simply convert it to a SimpleXMLElement
  $total = simplexml_import_dom( $total );
  var_dump( $total );
  // and then access the values like this:
  $total->SubTotal;
  $total->Shipping;
  // ... etc.


  // Example 2.1
  // fetch all children of <Total> into an array
  $total = [];
  foreach( $xpath->query( './Total/*', $order ) as $totalNode ) {
    $total[ $totalNode->nodeName ] = $totalNode->textContent;
  }
  var_dump( $total );

  // Example 2.2
  // fetch all children of <Total> into a stdClass object
  $total = new \stdClass;
  foreach( $xpath->query( './Total/*', $order ) as $totalNode ) {
    $total->{ $totalNode->nodeName } = $totalNode->textContent;
  }
  var_dump( $total );

  /*
    Now, after this you can create and process the Customer and Products data
    in a similar fashion as I've shown how to process the Total data above
  */
}