Tim*_*wdi 48 php xml dom simplexml
我有几个具有不同属性的相同元素,我正在使用SimpleXML访问:
<data>
<seg id="A1"/>
<seg id="A5"/>
<seg id="A12"/>
<seg id="A29"/>
<seg id="A30"/>
</data>
Run Code Online (Sandbox Code Playgroud)
我需要删除id为"A12" 的特定seg元素,我该怎么做?我已经尝试循环遍历seg元素并取消设置特定元素,但这不起作用,元素仍然存在.
foreach($doc->seg as $seg)
{
if($seg['id'] == 'A12')
{
unset($seg);
}
}
Run Code Online (Sandbox Code Playgroud)
hak*_*kre 56
与现有答案中的流行信念相反,每个Simplexml元素节点都可以单独从文档中删除unset().问题的关键在于您需要了解SimpleXML的实际工作原理.
首先找到要删除的元素:
list($element) = $doc->xpath('/*/seg[@id="A12"]');
Run Code Online (Sandbox Code Playgroud)
然后删除$element你在其中表示的元素取消设置其自引用:
unset($element[0]);
Run Code Online (Sandbox Code Playgroud)
这是有效的,因为任何元素的第一个元素都是Simplexml中的元素本身(自引用).这与它的神奇本质有关,数字索引表示任何列表中的元素(例如,父 - >子),甚至单个子列表也是如此.
非数字字符串索引表示属性(在数组访问中)或子元素(在属性访问中).
因此,属性访问中的数字缺省如下:
unset($element->{0});
Run Code Online (Sandbox Code Playgroud)
也工作.
当然,使用该xpath示例,它非常简单(在PHP 5.4中):
unset($doc->xpath('/*/seg[@id="A12"]')[0][0]);
Run Code Online (Sandbox Code Playgroud)
完整的示例代码(Demo):
<?php
/**
* Remove a child with a specific attribute, in SimpleXML for PHP
* @link http://stackoverflow.com/a/16062633/367456
*/
$data=<<<DATA
<data>
<seg id="A1"/>
<seg id="A5"/>
<seg id="A12"/>
<seg id="A29"/>
<seg id="A30"/>
</data>
DATA;
$doc = new SimpleXMLElement($data);
unset($doc->xpath('seg[@id="A12"]')[0]->{0});
$doc->asXml('php://output');
Run Code Online (Sandbox Code Playgroud)
输出:
<?xml version="1.0"?>
<data>
<seg id="A1"/>
<seg id="A5"/>
<seg id="A29"/>
<seg id="A30"/>
</data>
Run Code Online (Sandbox Code Playgroud)
Ste*_*rig 52
虽然SimpleXML提供了一种删除 XML节点的方法,但其修改功能有限.另一种解决方案是使用DOM扩展.dom_import_simplexml()将帮助您将您SimpleXMLElement转换为DOMElement.
只是一些示例代码(使用PHP 5.2.5测试):
$data='<data>
<seg id="A1"/>
<seg id="A5"/>
<seg id="A12"/>
<seg id="A29"/>
<seg id="A30"/>
</data>';
$doc=new SimpleXMLElement($data);
foreach($doc->seg as $seg)
{
if($seg['id'] == 'A12') {
$dom=dom_import_simplexml($seg);
$dom->parentNode->removeChild($dom);
}
}
echo $doc->asXml();
Run Code Online (Sandbox Code Playgroud)
输出
<?xml version="1.0"?>
<data><seg id="A1"/><seg id="A5"/><seg id="A29"/><seg id="A30"/></data>
Run Code Online (Sandbox Code Playgroud)
顺便说一下:当您使用XPath(SimpleXMLElement-> xpath)时,选择特定节点要简单得多:
$segs=$doc->xpath('//seq[@id="A12"]');
if (count($segs)>=1) {
$seg=$segs[0];
}
// same deletion procedure as above
Run Code Online (Sandbox Code Playgroud)
dat*_*.io 23
只是取消设置节点:
$str = <<<STR
<a>
<b>
<c>
</c>
</b>
</a>
STR;
$xml = simplexml_load_string($str);
unset($xml –> a –> b –> c); // this would remove node c
echo $xml –> asXML(); // xml document string without node c
Run Code Online (Sandbox Code Playgroud)
此代码取自如何删除/删除SimpleXML中的节点.
Wit*_*man 10
我相信Stefan的答案是正确的.如果您只想删除一个节点(而不是所有匹配的节点),这是另一个例子:
//Load XML from file (or it could come from a POST, etc.)
$xml = simplexml_load_file('fileName.xml');
//Use XPath to find target node for removal
$target = $xml->xpath("//seg[@id=$uniqueIdToDelete]");
//If target does not exist (already deleted by someone/thing else), halt
if(!$target)
return; //Returns null
//Import simpleXml reference into Dom & do removal (removal occurs in simpleXML object)
$domRef = dom_import_simplexml($target[0]); //Select position 0 in XPath array
$domRef->parentNode->removeChild($domRef);
//Format XML to save indented tree rather than one line and save
$dom = new DOMDocument('1.0');
$dom->preserveWhiteSpace = false;
$dom->formatOutput = true;
$dom->loadXML($xml->asXML());
$dom->save('fileName.xml');
Run Code Online (Sandbox Code Playgroud)
请注意,根据XML数据的来源以及您想要对输出执行的操作,可以使用不同的代码替换"加载XML ...(第一个)"和"格式XML ...(最后一个)"部分; 中间的部分找到一个节点并将其删除.
此外,if语句仅用于确保目标节点在尝试移动之前存在.您可以选择不同的方式来处理或忽略这种情况.
小智 5
这项工作对我来说:
$data = '<data>
<seg id="A1"/>
<seg id="A5"/>
<seg id="A12"/>
<seg id="A29"/>
<seg id="A30"/></data>';
$doc = new SimpleXMLElement($data);
$segarr = $doc->seg;
$count = count($segarr);
$j = 0;
for ($i = 0; $i < $count; $i++) {
if ($segarr[$j]['id'] == 'A12') {
unset($segarr[$j]);
$j = $j - 1;
}
$j = $j + 1;
}
echo $doc->asXml();
Run Code Online (Sandbox Code Playgroud)