I have some XML like this: some.xml
:
<one>
<two>
<three>
<four>some text</four>
</three>
</two>
<two>
<three>
<four>some other text</four>
</three>
</two>
<two>
</two>
</one>
I can delete any of the two
elements by searching for a text:
xmlstarlet ed -d "//one/two[contains(.,'some text')]" some.xml
This removes the first two
node. But I want to delete all two
elements that do not contain any three
element, like this:
<one>
<two>
<three>
<four>some text</four>
</three>
</two>
<two>
<three>
<four>some other text</four>
</three>
</two>
</one>
The answer depends on whether by "contains any three
element" you mean (1) or (2)
As an immediate child:
//one/two[not(three)]
will select all two
elements that do not have a three
child.
As any descendent
//one/two[not(.//three)]
will select all two
elements that do not have a three
descendent.