我有两个具有相似结构的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');
有没有办法可以使用DomDocument基于常见的ProductId将所有属性合并到一个记录中?我宁愿不进入XSLT。
非常感谢任何帮助。
提前致谢。
答案 0 :(得分:2)
我使用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();
答案 1 :(得分:0)
您可以使用SimpleXML的attribute()功能
$xml = simplexml_load_file($filename);
foreach($xml->Products->record->attributes() as $attribute => $value) {
//do something
}