Down and Dirty
Fear Keeps You Sha
Our coming-of-age
You get so fat tha
A Lost Puppy Dog
Love Many, Trust F
Salvation and Dese
Each time you will
Tastes Like Chicke
Tiny Little Shanks

Now’s the Time to
I know that you me
Stranded
Jury duty auto enr
So Smart They're D
This could force t
I'm the Kingpin
Gifts for the busy
Personal Escort se
Fun, Liesure, Phot
Vitamin, Protein, Vegan, Beyond Meat" type="product" product_name="Beyond Meat - Beyond Burger" product_title="Beyond Meat - Beyond Burger: Vegan & Kosher " brand="" web_title="Beyond Meat - Beyond Burger: Vegan & Kosher "/> This is what I need to be returned: menu brand 3 American Harvest 3 American Harvest A: I suggest using the following XPath expression: /catalog/menu/item[not(span)][not(img)]/span That selects the title that doesn't have both an img and a span child. You can use normalize-space() to replace all whitespace in the string with a single space and thus remove empty strings, and use text() to get the text without any element nodes. This expression selects the name, regardless of brand, price or qty. If you want a specific brand, product, price, or quantity to be returned, then you can add additional predicates after the /catalog/menu/item[not(span)][not(img)]. Update: If you just want to select a single item, you can use the following expression: /catalog/menu/item[not(span)][not(img)]/span It selects the first span. Note that the preceding / catalog/ menu/ item[not(span)][not(img)] expression does not give you the same result, because it selects all spans regardless of whether the price, qty, or brand name is the same for all the spans. A: This is one option for your problem: The result should be exactly the text you want. The above does, of course, assume your input contains only one such brand per menu, i.e. that menu items with the same brand are siblings in the same way as menu items with different brands. Edit: As for the problem with your desired result set you posted, the only fix to make the above work (assuming there are no other problems like missing span nodes) is to make your desired output use "text()[.='']" instead of "[contains(text(), '')]", which would work because your desired output doesn't have any spans at all. Second edit: If you want a solution that deals with all the special cases mentioned in your comment below then try this: Note that the second for-each in the first for-each of the above will only be executed once. Third edit: The solution above, when corrected, returns the following output: menu brand American Harvest 3 American Harvest 3