I'm trying to remove all elements from an XML file that contain a certain other element. Here's a very simplified version of what I'm trying to do. Suppose I have the XML file
<RootEl>
<A>
<B/>
</A>
<A>
<C/>
</A>
</RootEl>
If I wanted to keep all and only the A's that DO contain B's, I could use this command line:
xml_grep -root A -cond B < TheFile.xml
But if I want to do the reverse--keep only the A's that do NOT contain B's, I'm at a loss. A command similar to the above, namely
xml_grep -root A -exclude B < TheFile.xml
gives me
<RootEl>
<A>
</A>
<A>
<C/>
</A>
</RootEl>
whereas what I want is
<RootEl>
<A>
<C/>
</A>
</RootEl>
I get the same undesired answer if I use
xml_grep -root A -exclude A/B < TheFile.xml
or
xml_grep -exclude A/B < TheFile.xml
I could figure out how to do this in Python, and I suppose it's possible in xslt. But I was hoping for a way to do this in xml_grep.
BTW, I'm sure someone will ask why I don't just tell it I want the As that contain Cs. The problem is that there are 20 or so things an A can contain besides B or C, so I'd have to specify an A that contains a C or a D or...or a Z. Which is a whole lot more work than specifying the one kind of A I don't want.
The question Delete XML node containing certain element is asking basically the same question, but there are no answers there using xml_grep. I'm hoping someone can suggest such an answer, since xml_grep seems reasonably popular and built for purposes like this...almost.
xmlstarlet
. Do you need to usexml_grep
?xmlstarlet sel -t -m "RootEl" -c "A[not(./B)]"
I am now sold on xmlstarlet!