Search code examples
xmlrecursionxpathxmlstarlet

xmlstarlet delete parent elements from multiple documents recursively


Have a set of xml docs in separate directories, each document like this:

    <xmldoc>
      <data>data text</data>
      <parent>
        <descendent1>
          <descendent2>motorcyclebaby.com?query</descendent2>
        </descendent1>
      </parent>
    </xmldoc>

I want to remove the parent element that contains "motorcycle" in descendent2 in all of the documents. So far, I have this, which works for a single doc:

   xmlstarlet ed -d "//parent[descendent1/descendent2[contains(text(),'motorcycle')]]" xmldoc.xml

I've tried this to delete the parent element recursively with find:

    find . -name 'xmldoc.xml' -print0 | xmlstarlet ed -d "//parent[descendent1/descendent2[contains(text(),'motorcycle')]]" xmldoc.xml

but got 'failed to load external entity "xmldoc.xml"'

also tried:

    find . -name "xmldoc.xml" -exec xmlstarlet ed -d "//parent[descendent1/descendent2[contains(text(),'motorcycle')]]" xmldoc.xml {} +

Solution

  • Figured it out!

        find . -iname "xmldoc.xml" -exec xmlstarlet ed --inplace -d "//parent[descendent1/descendent2[contains(text(),'motorcycle')]]" {} +
    

    -iname to ignore case since my docs were capitalized

    //parent[descendent1/descendent2[contains... needed to select the entire parent element where the child contained the searched string.

    --inplace needed to make changes to the actual documents, rather than printed in Terminal.

    {} + needed with -exec to make the change to each document listed by find.

    \o/