У меня есть два 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 }