3

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> 
2
  • 2
    Thank you for not wanting to use sed or something for this. Commented Dec 9, 2023 at 0:35
  • 1
    regex came to mind - but brainfuck exists already. Commented Dec 11, 2023 at 10:52

2 Answers 2

4

The answer depends on whether by "contains any three element" you mean (1) or (2)

  1. As an immediate child:

    //one/two[not(three)] 

    will select all two elements that do not have a three child.

  2. As any descendent

    //one/two[not(.//three)] 

    will select all two elements that do not have a three descendent.

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you very much. The solution looks painfully simple :-) I wonder why i wasn't able to extract that from the documentation - but all these XSLT comparisons baffle me ...
3

i want to delete all "two" Elements that do not contain any "three" Element

If I understand correctly, that would be xmlstarlet ed -d '//two[not(three)]'

<?xml version="1.0"?> <one> <two> <three> <four>some text</four> </three> </two> <two> <three> <four>some other text</four> </three> </two> </one> 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.