views:

71

answers:

4

Given this:

<element_1> 
    <element_2>Text</element_2> 
    <element_3> 
        <element_4> 
            <element_5>Text with @ in Value</element_5> 
        </element_4> 
        <element_4> 
            <element_5>Test Text</element_5> 
        </element_4> 
    </element_3> 
    <element_6> 
        <element_7> 
            <element_8>0</element_8> 
...

How do I select all instances of element_1 that do not contain an '@' in element_5?

A: 
element1[not(contains(.//element_5, '@'))]
John Kugelman
What is up with the downvote?
John Kugelman
+3  A: 
element_1[not(contains(element_3/element_4/element_5,'@'))]

This is interpreted as

element_1[                          #select elements named "element_1"
  not(contains(                     #that do not contain
    element_3/element_4/element_5,  #children in this hierarchy
    '@'                             #the character @
  ))
]
Welbog
Does this need leading // before element_1?
Snekse
Depends if you want to match element_1 at any level, or if it's always the root of the DOM.
dty
Also note that this solution assumes that element_5 is always directly beneath element_4, which in turn is always directly beneath element_3, which in turn is always directly beneath element_1. The other two solutions assume that element_5 can appear at any level beneath element_1.
dty
Thanks. I haven't been able to test this yet, but I think I can figure it out from here if this doesn't work.
Snekse
+1 for not use of `//` operator.
Alejandro
A: 

My XPath is a bit rusty, but something like this:

//element_1[.//element_5[not(contains(., "@"))]]
dty
@dty: We are a litle bit picky and don't recommend `//` operator when the schema is wellknown...
Alejandro
That's fine. The OP wasn't specific about that.
dty
Why the down-rank? At least have the decency to leave a message saying why you've down-ranked, whoever you are.
dty
A: 

How do I select all instances of element_1 that do not contain an '@' in element_5?

Use:

//element_1[not(.//element_5[contains(.,'@')])]

In English, this means: Select all "element_1" elements in the document that do not have an "element_5" descendant whose string value contains the string '@'.

I am using the // abbreviation only because the structure of the XML file isn't clear.

I always recommend to avoid using the // abbreviation always when this is possible, because otherwise this may result in very inefficient XPath evaluation.

Dimitre Novatchev
@Mads-Hansen: Thank you for the edits, but "descendent" is a valid English word.
Dimitre Novatchev