我有一项令人难以置信的任务。我有一个直接的提要。确切地说,出租的房产看起来像这样:
<ad>
<name>Property 1</name>
<latitude>29.723085</latitude>
<longitude>-95.66024</longitude>
<area>2000</area>
</ad>
<ad>
<name>Property 1</name>
<latitude>29.723085</latitude>
<longitude>-95.66024</longitude>
<area>2500</area>
</ad>
在上面的示例中,有一个具有两个不同单元的属性。两者唯一的共同点是名称和纬度、经度字段。
现在,我需要使用PHP将这个XML重新创建到新的XML中,并将所有不同的单元放置到一个属性中。因此,新的提要将如下所示:
<ad>
<property_name>Property 1</property_name>
<latitude>29.723085</latitude>
<longitude>-95.66024</longitude>
<units>
<unit>
<area>2000</area>
</unit>
<unit>
<area>2500</area>
</unit>
</units>
</ad>
有人能帮我吗?非常感谢
有更多选项可以获得您想要的结果。使用DOMDocument
可以使用importNode
,也可以直接修改原始XML。
我将向您展示一种创建全新XML的方法。
首先,您必须在DOMDocument
对象中加载现有的XML:
$src = new DOMDocument();
libxml_use_internal_errors(1);
$src->loadXML( $xml );
然后创建目标DOMDocument
对象。为此,我使用了一个通用的<root>
标签;您可以将其替换为完整的XML包装<ad>
标签:
$dom = new DOMDocument();
libxml_use_internal_errors(1);
$dom->loadXML( '<root></root>' );
$dom->formatOutput = True;
$root = $dom->getElementsByTagName( 'root' )->item(0);
现在,为目标XML初始化一个DOMXpath
对象。DOMXPath
允许执行复杂的XML查询:
$xpath = new DOMXPath( $dom );
此时,通过源XML的所有<ad>
节点执行foreach
,并为每个节点检索<name>
和<area>
值:
foreach( $src->getElementsByTagName( 'ad' ) as $node )
{
$name = $node->getElementsByTagName( 'name' )->item(0)->nodeValue;
$area = $node->getElementsByTagName( 'area' )->item(0)->nodeValue;
现在使用DOMXPath
查找目标XML中是否已经存在<ad>
节点,其<name>
值=检索名称:
$found = $xpath->query( '//ad[name[.="'.$name.'"]]' );
如果找到目的节点,则将其<units>
设置为$child
:
if($found->length)
{
$child = $found->item(0)->getElementsByTagName('units')->item(0);
}
否则,创建一个添加源基础数据的新节点,然后将其设置为$child
:
else
{
$lat = $node->getElementsByTagName( 'latitude' )->item(0)->nodeValue;
$long = $node->getElementsByTagName( 'longitude' )->item(0)->nodeValue;
$child = $dom->createElement( 'ad' );
$child->appendChild( $dom->createElement( 'name', $name ) );
$child->appendChild( $dom->createElement( 'latitude', $lat ) );
$child->appendChild( $dom->createElement( 'longitude', $long ) );
$child->appendChild( $dom->createElement( 'units' ) );
$root->appendChild( $child );
$child = $child->getElementsByTagName('units')->item(0);
}
此时,您有了正确的$child
节点来添加<unit>
:
$unit = $dom->createElement( 'unit' );
$unit->appendChild( $dom->createElement( 'area', $area ) );
$child->appendChild( $unit );
}
在foreach()
循环结束时,您可以打印获得的XML:
echo $dom->saveXML();
输出:
<?xml version="1.0"?>
<root>
<ad>
<name>Property 1</name>
<latitude>29.723085</latitude>
<longitude>-95.66024</longitude>
<units/>
<unit>
<area>2000</area>
</unit>
<unit>
<area>2500</area>
</unit>
</ad>
</root>
eval.in演示
附加说明:
在上面的脚本中,我假设每个属性名称都有唯一的long/lat。若可以存在名称相同但长度/纬度不同的属性,则必须不仅按名称,而且按纬度/经度查找节点。
我还假设您的结构示例在每个节点中都受到尊重。否则,像$node->getElementsByTagName( 'latitude' )->item(0)->nodeValue
这样的语法可能会失败,您必须将其替换为:
if( $node->getElementsByTagName( 'latitude' )->length )
{
$lat = $node->getElementsByTagName( 'latitude' )->item(0)->nodeValue;
}
对于具有CCD_ 23语法的每个代码行也是如此。