使用XPath和PHP删除XML中的节点
我有一个使用XPath和PHP删除XML中的节点,php,xml,xpath,Php,Xml,Xpath,我有一个XML: <root> <level name="main"> <level name="sub_1"> <content id="abc123" /> </level> </level> </root> 我在PHP中尝试了这个,但没有结果,我做错了什么 $doc = new DOMDocument; $doc->loadxml($xml_
XML
:
<root>
<level name="main">
<level name="sub_1">
<content id="abc123" />
</level>
</level>
</root>
我在PHP中尝试了这个,但没有结果,我做错了什么
$doc = new DOMDocument;
$doc->loadxml($xml_from_file);
$xpath = new DOMXPath($doc);
$node_list = $xpath->query("content[@id='abc123']/parent::*");
$node = $node_list->item(0);
$doc->removeChild($node);
这是一种黑客行为,但我用你的例子来说明。
xpath
查询可能存在一个问题——请注意开头的/
$xml_string = '<root>
<level name="main">
<level name="sub_1">
<content id="abc123" />
</level>
</level>
</root>';
// using SimpleXMLElement instead of DOMDocument
$xml = new SimpleXMLElement($xml_string);
// standardize the string version of the xml so str_replace works
$xml_string = $xml->asXML();
// search for the target; note the // at the beginning of the query
$target = $xml->xpath("//content[@id='abc123']/parent::*");
// use simple string replacement to remove the node
echo str_replace($target[0]->asXML(), '', $xml_string);
$xml\u string=>
';
//使用SimpleXMLElement代替DOMDocument
$xml=新的simplexmlement($xml\u字符串);
//标准化xml的字符串版本,以便str_replace工作
$xml_string=$xml->asXML();
//搜索目标;请注意查询开头的//
$target=$xml->xpath(//content[@id='abc123']/parent::*”;
//使用简单的字符串替换删除节点
echo str_replace($target[0]->asXML(),“”,$xml_字符串);
不是很优雅,但它似乎解决了您的问题。loadxml($xml\u from\u file);
<?php
$xml_from_file = '<root>
<level name="main">
<level name="sub_1">
<content id="abc123" />
</level>
</level>
</root>';
$doc = new DOMDocument;
$doc->loadxml($xml_from_file);
$xpath_selector = new DOMXPath($doc);
//Here you forget at the begin the //
$node_list = $xpath_selector->query("//content[@id='abc123']/parent::*");
//here you get the reference to the parent of content
$node = $node_list->item(0);
//but for remove the child you need to go to the parent node
$node->parentNode->removeChild($node);
echo $doc->saveXML();
?>
$xpath\u选择器=新的DOMXPath($doc);
//在这里,你一开始就忘了//
$node\u list=$xpath\u选择器->查询(//content[@id='abc123']/parent::*”;
//在这里,您可以获得对内容父级的引用
$node=$node_list->item(0);
//但是要删除子节点,需要转到父节点
$node->parentNode->removeChild($node);
echo$doc->saveXML();
?>
输出:
<root>
<level name="main">
</level>
</root>
您的源代码有两个问题 表达式仅匹配子节点。您需要以
//
开头以匹配任何节点://content[@id='abc123']/parent::*
找到的节点不是文档的子节点,因此,您需要将其从自己的父节点中删除:$node->parentNode->removeChild($node)代码>
我建议使用foreach
,以避免节点不存在时出现问题
$document = new DOMDocument;
$document->loadxml($xmlString);
$xpath = new DOMXPath($document);
foreach ($xpath->evaluate("//content[@id='abc123']/parent::*") as $node) {
$node->parentNode->removeChild($node);
}
echo $document->saveXml();
DOMDocument::loadXML
接受XML。使用文件名DOMDocument::load
。谢谢。实际上,我是从loadXML
中的字符串加载它的。在处理XML时,尝试使用字符串函数来处理它通常是一个坏主意,因为它的结构错综复杂(想想实体、cdata节、注释、dtd)。几乎总是最好使用XML类,比如DOM、XPath、XQuery或XSLT。
$document = new DOMDocument;
$document->loadxml($xmlString);
$xpath = new DOMXPath($document);
foreach ($xpath->evaluate("//content[@id='abc123']/parent::*") as $node) {
$node->parentNode->removeChild($node);
}
echo $document->saveXml();