Remove a child with a specific attribute, in SimpleXML for PHP

后端 未结 17 2310
星月不相逢
星月不相逢 2020-11-22 02:50

I have several identical elements with different attributes that I\'m accessing with SimpleXML:


    
    

        
相关标签:
17条回答
  • 2020-11-22 02:50

    If you want to cut list of similar (not unique) child elements, for example items of RSS feed, you could use this code:

    for ( $i = 9999; $i > 10; $i--) {
        unset($xml->xpath('/rss/channel/item['. $i .']')[0]->{0});
    }
    

    It will cut tail of RSS to 10 elements. I tried to remove with

    for ( $i = 10; $i < 9999; $i ++ ) {
        unset($xml->xpath('/rss/channel/item[' . $i . ']')[0]->{0});
    }
    

    But it works somehow randomly and cuts only some of the elements.

    0 讨论(0)
  • 2020-11-22 02:51

    For future reference, deleting nodes with SimpleXML can be a pain sometimes, especially if you don't know the exact structure of the document. That's why I have written SimpleDOM, a class that extends SimpleXMLElement to add a few convenience methods.

    For instance, deleteNodes() will delete all nodes matching a XPath expression. And if you want to delete all nodes with the attribute "id" equal to "A5", all you have to do is:

    // don't forget to include SimpleDOM.php
    include 'SimpleDOM.php';
    
    // use simpledom_load_string() instead of simplexml_load_string()
    $data = simpledom_load_string(
        '<data>
            <seg id="A1"/>
            <seg id="A5"/>
            <seg id="A12"/>
            <seg id="A29"/>
            <seg id="A30"/>
        </data>'
    );
    
    // and there the magic happens
    $data->deleteNodes('//seg[@id="A5"]');
    
    0 讨论(0)
  • 2020-11-22 02:52

    This work for me:

    $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();
    
    0 讨论(0)
  • 2020-11-22 02:52

    There is a way to remove a child element via SimpleXml. The code looks for a element, and does nothing. Otherwise it adds the element to a string. It then writes out the string to a file. Also note that the code saves a backup before overwriting the original file.

    $username = $_GET['delete_account'];
    echo "DELETING: ".$username;
    $xml = simplexml_load_file("users.xml");
    
    $str = "<?xml version=\"1.0\"?>
    <users>";
    foreach($xml->children() as $child){
      if($child->getName() == "user") {
          if($username == $child['name']) {
            continue;
        } else {
            $str = $str.$child->asXML();
        }
      }
    }
    $str = $str."
    </users>";
    echo $str;
    
    $xml->asXML("users_backup.xml");
    $myFile = "users.xml";
    $fh = fopen($myFile, 'w') or die("can't open file");
    fwrite($fh, $str);
    fclose($fh);
    
    0 讨论(0)
  • 2020-11-22 02:54

    Just unset the node:

    $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
    

    This code was taken from How to delete / remove nodes in SimpleXML.

    0 讨论(0)
  • 2020-11-22 02:55

    With FluidXML you can use XPath to select the elements to remove.

    $doc = fluidify($doc);
    
    $doc->remove('//*[@id="A12"]');
    

    https://github.com/servo-php/fluidxml


    The XPath //*[@id="A12"] means:

    • in any point of the document (//)
    • every node (*)
    • with the attribute id equal to A12 ([@id="A12"]).
    0 讨论(0)
提交回复
热议问题