简体   繁体   English

使用XPath和PHP删除XML中的节点

[英]Removing nodes in XML with XPath and PHP

I have an XML : 我有一个XML

<root>
   <level name="main">
      <level name="sub_1">
         <content id="abc123" />
      </level>
   </level>
</root>

I would like to search for the node with id that is abc123 and delete the <content> and its parent <level> 我想搜索idabc123的节点并删除<content>及其父<level>

So the end result would be: 所以最终的结果是:

<root>
  <level name="main">
  </level> 
</root>

I have tried this in PHP without result, what am I doing wrong? 我在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);

Here are two issues with your source. 以下是您的来源的两个问题。

The expression does only match child nodes. 表达式仅匹配子节点。 You need to start it with // to match any node: //content[@id='abc123']/parent::* . 你需要用//来匹配任何node: //content[@id='abc123']/parent::*

The found node is not a child of the document so, you need to remove it from its own parent: $node->parentNode->removeChild($node); 找到的节点不是文档的子节点,因此需要将其从自己的父$node->parentNode->removeChild($node);删除: $node->parentNode->removeChild($node); .

I suggest using a foreach to avoid problems if the node doesn't exists. 如果节点不存在,我建议使用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();
<?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();

?> 

Output: 输出:

<root>
  <level name="main">
  </level> 
</root>

This is kind of a hack but I got it to work with your example. 这是一种黑客攻击,但我让它与你的例子一起工作。 One problem is likely with your xpath query--note the // at the beginning. 您的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);

Not very elegant, but it seemed to take care of your problem. 不是很优雅,但它似乎照顾你的问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM