Reputation: 5039
I looked at some other articles here and elsewhere but nothing was exactly what I'm trying to implement.
Please take a look at this xpath query (using mozxpath.js file to clone IE functionality)
var XMLObj.selectSingleNode("/Catalog/Albums/Album/Tracks/Track[../../AlbumNo='" + AlbumNo + "' and ./TrackNo = '" + TrackNo + "']");
How can I convert this expression to jquery?
I tried the following to get me started and it only selects the AlbumNo node:
$(XMLObj).find("AlbumNo:contains(" + AlbumNo + ")", "TrackNo:contains(" + TrackNo + ")");
The xpath expression is looking for the Track node where both conditions are met. How can I rewrite the xpath expression to something jQuery friendly?
Thank you.
Edit
Here is the dumbed-down version of the XML structure:
<Catalog>
<Albums>
<Album>
<AlbumNo>1</AlbumNo>
<Tracks>
<Track>
<TrackNo>1</TrackNo>
<Track>
<TrackNo>2</TrackNo>
<Track>
<TrackNo>3</TrackNo>
<Track>
<TrackNo>4</TrackNo>
<Track>
<TrackNo>5</TrackNo>
<Track>
<TrackNo>6</TrackNo>
<Track>
<TrackNo>7</TrackNo>
<Track>
<TrackNo>8</TrackNo>
<Track>
<TrackNo>9</TrackNo>
<Track>
<TrackNo>10</TrackNo>
<Track>
<TrackNo>11</TrackNo>
<Track>
<TrackNo>12</TrackNo>
</Tracks>
</Album>
</Album>
</Catalog>
Upvotes: 1
Views: 540
Reputation: 816790
An example of the XML structure would be helpful.
I don't think you can achieve the same with a single selector, you have to use a more complex structure:
$(XMLObj).find('Album').filter(function() { // filter albums by album number
return !!$(this).find('AlbumNo').filter(function() {
return $(this).text() == AlbumNo;
}).length;
}).find('Track').filter(function() { // filter tracks by track number
return !!$(this).find('TrackNo').filter(function() {
return $(this).text() == TrackNo;
}).length;
});
It would definitely be easier if the numbers were attributes of the elements and not descendants.
The reason why I use another filter
function instead of :contains
is that it is the only way you can search for an exact match. :contains
will also match if the text you search is only a substring. That is, if you search for track number 1
, :contains
would also match track number 10
, 11
, 12
, etc.
If you have to do similar things quite often, it might be useful to extend jQuery with a function which filters elements with certain subelements with certain content.
For example:
(function($) {
$.fn.whichContains = function(element, content) {
return this.filter(function() {
return !!$(this).find(element).filter(function() {
return $(this).text() == content;
}).length;
});
};
}(jQuery));
which can be used as
$(XMLObj)
.find('Album').whichContains('AlbumNo', AlbumNo)
.find('Track').whichContains('TrackNo', TrackNo)
Upvotes: 1
Reputation: 76003
I've setup a jsfiddle that selects the requested TrackNo
element within the requested AlbumNo
element: http://jsfiddle.net/jasper/tDhLF/.
Here is the selector I used:
$(xml_string).find('AlbumNo:contains(' + AlbumNo + ')').next('tracks').find('TrackNo:contains(' + TrackNo + ')');
Upvotes: 1
Reputation: 78550
comma deliminators as a means of including other elements requires the comma to be in the quotes:
$(XMLObj).find("AlbumNo:contains(" + AlbumNo + "),TrackNo:contains(" + TrackNo + ")");
Upvotes: 1