Merge two xml files based on common attribute

前端 未结 2 482
忘了有多久
忘了有多久 2021-01-25 00:27

I have two xml files with a similar structure, and I need to merge them based on a common attribute. To be more explicit, here are two samples:

file1.xml



        
相关标签:
2条回答
  • 2021-01-25 00:47

    I use Xpath to fetch nodes and values from DOM. In your case I see two tasks.

    One task to iterate all record elements in on document, fetch the attributes of the matching element from the second document and copy the attributes.

    The other task to iterate all record elements in the second document and add them to the first if here is no element with that ProductId.

    $xmlOne = <<<'XML'
    <Products>
     <record ProductId="366" ProductName="Test" ProductCategory="Categ1"></record>
    </Products>
    XML;
    
    $xmlTwo = <<<'XML'
    <Productprices>
     <record ProductId="366" ProductPrice="10" ProductVAT="24"></record>
     <record ProductId="444" ProductPrice="23" ProductVAT="32"></record>
    </Productprices>
    XML;
    
    $targetDom = new DOMDocument();
    $targetDom->loadXml($xmlOne);
    $targetXpath = new DOMXpath($targetDom);
    
    $addDom = new DOMDocument();
    $addDom->loadXml($xmlTwo);
    $addXpath = new DOMXpath($addDom);
    
    // merge attributes of record elements depending on ProductId
    foreach ($targetXpath->evaluate('//record[@ProductId]') as $record) {
      $productId = $record->getAttribute('ProductId');
      foreach ($addXpath->evaluate('//record[@ProductId='.$productId.']/@*') as $attribute) {
        if (!$record->hasAttribute($attribute->name)) {
          $record->setAttribute($attribute->name, $attribute->value);
        }
      }
    }
    
    // copy records elements that are not in target dom
    foreach ($addXpath->evaluate('//record[@ProductId]') as $record) {
      $productId = $record->getAttribute('ProductId');
      if ($targetXpath->evaluate('count(//record[@ProductId='.$productId.'])') == 0) {
        $targetDom->documentElement->appendChild(
          $targetDom->importNode($record)
        );
      }
    }
    
    echo $targetDom->saveXml();
    
    0 讨论(0)
  • 2021-01-25 00:50

    You can use the attribute() function of SimpleXML

    $xml = simplexml_load_file($filename);
    foreach($xml->Products->record->attributes() as $attribute => $value) {
        //do something
    }
    
    0 讨论(0)
提交回复
热议问题