Skip to content

Instantly share code, notes, and snippets.

@KrzysztofPrzygoda
Last active April 23, 2018 14:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save KrzysztofPrzygoda/e53223e4450ed35effb75f54826cc434 to your computer and use it in GitHub Desktop.
Save KrzysztofPrzygoda/e53223e4450ed35effb75f54826cc434 to your computer and use it in GitHub Desktop.
PHP Filtering XML nodes based on attributes
<?php
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;
}
}
?>
<?php
// To remove/keep nodes with certain attribute value or falling into array of attribute values
// you can extend SimpleXMLElement class like this:
require('class.simplexmlelement.php');
// Then having your $doc XML you can remove your <seg id="A12"/> node calling:
$data='<data>
<seg id="A1"/>
<seg id="A5"/>
<seg id="A12"/>
<seg id="A29"/>
<seg id="A30"/>
</data>';
$doc=new SimpleXMLElementExtended($data);
$doc->seg->filterAttribute('id', ['A12'], FALSE);
//or remove multiple <seg /> nodes:
$doc->seg->filterAttribute('id', ['A1', 'A12', 'A29'], FALSE);
//For keeping only <seg id="A5"/> and <seg id="A30"/> nodes and removing the rest:
$doc->seg->filterAttribute('id', ['A5', 'A30'], TRUE);
?>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment