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

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

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


    
    

        
17条回答
  •  天涯浪人
    2020-11-22 03:08

    To remove/keep nodes with certain attribute value or falling into array of attribute values you can extend SimpleXMLElement class like this (most recent version in my GitHub Gist):

    class SimpleXMLElementExtended extends SimpleXMLElement
    {    
        /**
        * Removes or keeps nodes with given attributes
        *
        * @param string $attributeName
        * @param array $attributeValues
        * @param bool $keep TRUE keeps nodes and removes the rest, FALSE removes nodes and keeps the rest 
        * @return integer Number o affected nodes
        *
        * @example: $xml->o->filterAttribute('id', $products_ids); // Keeps only nodes with id attr in $products_ids
        * @see: http://stackoverflow.com/questions/17185959/simplexml-remove-nodes
        */
        public function filterAttribute($attributeName = '', $attributeValues = array(), $keepNodes = TRUE)
        {       
            $nodesToRemove = array();
    
            foreach($this as $node)
            {
                $attributeValue = (string)$node[$attributeName];
    
                if ($keepNodes)
                {
                    if (!in_array($attributeValue, $attributeValues)) $nodesToRemove[] = $node;
                }
                else
                { 
                    if (in_array($attributeValue, $attributeValues)) $nodesToRemove[] = $node;
                }
            }
    
            $result = count($nodesToRemove);
    
            foreach ($nodesToRemove as $node) {
                unset($node[0]);
            }
    
            return $result;
        }
    }
    

    Then having your $doc XML you can remove your node calling:

    $data='
        
        
        
        
        
    ';
    
    $doc=new SimpleXMLElementExtended($data);
    $doc->seg->filterAttribute('id', ['A12'], FALSE);
    

    or remove multiple nodes:

    $doc->seg->filterAttribute('id', ['A1', 'A12', 'A29'], FALSE);
    

    For keeping only and nodes and removing the rest:

    $doc->seg->filterAttribute('id', ['A5', 'A30'], TRUE);
    

提交回复
热议问题