Слияние двух файлов xml на основе общего атрибута

У меня есть два xml-файла с аналогичной структурой, и мне нужно объединить их на основе общего атрибута. Чтобы быть более явным, вот два примера:

file1.xml

<Products> <record ProductId="366" ProductName="Test" ProductCategory="Categ1"></record> </Products> 

file2.xml

  <Productprices> <record ProductId="366" ProductPrice="10" ProductVAT="24"></record> </Productprices> 

Общим атрибутом в обоих файлах является ProductId. Мне нужно объединить все атрибуты, чтобы объединенный файл выглядел так:

  <Products> <record ProductId="366" ProductName="Test" ProductCategory="Categ1" ProductPrice="10" ProductVAT="24"></record> </Products> 

К сожалению, все, что мне удалось сделать, это просто объединить два файла, объединенный файл выглядит так:

  <Products> <record ProductId="366" ProductName="Test" ProductCategory="Categ1"></record> <record ProductId="366" ProductPrice="10" ProductVAT="24"></record> </Products> 

Это код PHP, который я использовал:

  $doc1 = new DOMDocument(); $doc1->load('file1.xml'); $doc2 = new DOMDocument(); $doc2->load('file2.xml'); $res1 = $doc1->getElementsByTagName('Products')->item(0); $items2 = $doc2->getElementsByTagName('record'); for ($i = 0; $i < $items2->length; $i ++) { $item2 = $items2->item($i); $item1 = $doc1->importNode($item2, true); $res1->appendChild($item1); } $doc1->save('file1.xml'); 

Есть ли способ объединить все атрибуты в одну запись на основе общего ProductId с помощью DomDocument? Я бы предпочел не пойти в XSLT.

Любая помощь будет оценена.

Заранее спасибо.

Я использую Xpath для извлечения узлов и значений из DOM. В вашем случае я вижу две задачи.

Одна задача перебора всех элементов записи в документе, выбор атрибутов совпадающего элемента из второго документа и копирование атрибутов.

Другая задача – перебрать все элементы записи во втором документе и добавить их в первый, если здесь нет элемента с этим 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(); 

Вы можете использовать функцию attribute () для SimpleXML

 $xml = simplexml_load_file($filename); foreach($xml->Products->record->attributes() as $attribute => $value) { //do something }