devbull
devbull

Reputation: 227

XML: Select nodes by it's value instead of attribute

I have this code for removing unwanted items from xml list, based on their child's attributes.

var xmlDoc=loadXMLDoc(filePath);

var unwanted = xmlDoc.querySelectorAll("item > KlasId[id='1']");
Array.prototype.map.call(unwanted, function(element){
    element.parentNode.parentNode.removeChild(element.parentNode);
});

This works just fine and removes all the item nodes with KlasId children of id=1.

What i want now is to remove items based on KlasId value instead of attribute (for example value 101010), but it somehow doesnt work:

var unwanted = xmlDoc.querySelectorAll("item > KlasId[value='101010']");
etc...

My XML:

<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<dataroot>
<item>
<KlasId id='1'>101010</KlasId>
</item>

<item>
<KlasId id='2'>101010</KlasId>
</item>

<item>
<KlasId id='3'>202020</KlasId>
</item>
</dataroot>

EDIT:

function loadXMLDoc(filename)
{
if (window.XMLHttpRequest)
  {
  xhttp=new XMLHttpRequest();
  }
else // code for IE5 and IE6
  {
  xhttp=new ActiveXObject("Microsoft.XMLHTTP");
  }
xhttp.open("GET",filename,false);
xhttp.send();
return xhttp.responseXML;
}

Upvotes: 0

Views: 1673

Answers (2)

JLRishe
JLRishe

Reputation: 101730

If you are only using Chrome (or Firefox, Opera, or Safari), then you can use XPath to perform this selection:

var found = xmlDoc.evaluate("/*/item[KlasId = '101010']", xmlDoc);

This will return a node iterator that you can use to iterate through the nodes as described here.

function getNodes(iterator) {
    var nodes = [],
        next = iterator.iterateNext();

    while (next) {
        nodes.push(next);
        next = iterator.iterateNext();
    }
    return nodes;
}

getNodes(found).forEach(function (node) {
    node.parentNode.removeChild(node);
});

var xmlDoc = $.parseXML("<dataroot><item><KlasId id='1'>101010</KlasId></item><item><KlasId id='2'>101010</KlasId></item><item><KlasId id='3'>202020</KlasId></item></dataroot>");

var found = xmlDoc.evaluate("//item[KlasId = '101010']", xmlDoc);

function getNodes(iterator) {
    var nodes = [],
        next = iterator.iterateNext();

    while (next) {
        nodes.push(next);
        next = iterator.iterateNext();
    }
    return nodes;
}

getNodes(found).forEach(function (node) {
    console.log('Removing node.');
    node.parentNode.removeChild(node);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.0/jquery.min.js"></script>

Internet Explorer does not support .evaluate() (or any XPath functionality as far as I can tell), so if you need cross-browser support, I think you'll need to use a third party library. I recommend xpath.js, on which I am a contributor.

One more option is to use jQuery's extended CSS selectors to perform the selection:

var $nodes = $(xmlDoc).find('item > KlasId:contains("101010")');

$nodes.remove();

var xmlDoc = $.parseXML("<dataroot><item><KlasId id='1'>101010</KlasId></item><item><KlasId id='2'>101010</KlasId></item><item><KlasId id='3'>202020</KlasId></item></dataroot>");

var $nodes = $(xmlDoc).find('item > KlasId:contains("101010")');

console.log($nodes.length);

$nodes.remove();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script>

This is also a cross-browser solution, but it will select the elements based on a contains comparison rather than an equality comparison.

Unrelated side note: .map() is intended for projecting one array onto another. To just carry out a series of side effects, use .forEach().

Upvotes: 2

NDY
NDY

Reputation: 3557

You can't do it with CSS only, because there is no CSS selector to select by the value of the element. See this blogpost about it: Blog

Upvotes: 1

Related Questions