Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用XPath和PHP删除XML中的节点_Php_Xml_Xpath - Fatal编程技术网

使用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();