2

I am running the following command

xmlstarlet ed -d "/Package/types[name='ApexEmailNotifications']" test.xml

against the below XML

<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
  <types>
    <members>1</members>
    <name>ApexEmailNotifications</name>
  </types>
  <types>
    <members>2</members>
    <name>ApexTrigger</name>
  </types>
  <types>
    <members>3</members>
    <members>4</members>
    <name>AppMenu</name>
  </types>
  <version>50.0</version>
</Package>

expecting it to change to the following

<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
  <types>
    <members>2</members>
    <name>ApexTrigger</name>
  </types>
  <types>
    <members>3</members>
    <members>4</members>
    <name>AppMenu</name>
  </types>
  <version>50.0</version>
</Package>

however nothing happens I just feel like I am missing one stupid character here or there or have misunderstood the man pages.

any help would be much appreciated by what's left of my hair

RobC
  • 22,977
  • 20
  • 73
  • 80

2 Answers2

2

XML namespaces make things generally difficult. This is what you have to do in xmlstarlet: declare the namespace (there's nothing magic about _ below, it's just a name) and then use the prefix for each tag

xmlstarlet ed \
    -N _=http://soap.sforce.com/2006/04/metadata \
    -d "/_:Package/_:types[_:name = 'ApexEmailNotifications']" \
    test.xml

result

<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
  <types>
    <members>2</members>
    <name>ApexTrigger</name>
  </types>
  <types>
    <members>3</members>
    <members>4</members>
    <name>AppMenu</name>
  </types>
  <version>50.0</version>
</Package>

As Daniel Haley comments, since the namespace applies to the root element, we can use the _ prefix without -N, for xmlstarlet version >= 1.2.1

xmlstarlet ed -d "/_:Package/_:types[_:name = 'ApexEmailNotifications']"  test.xml

And version 1.5.0 provided DEFAULT for the same purpose

xmlstarlet ed -d "/DEFAULT:Package/DEFAULT:types[DEFAULT:name = 'ApexEmailNotifications']"  test.xml
glenn jackman
  • 238,783
  • 38
  • 220
  • 352
  • 1
    Actually `_` _is_ magic in version 1.2.1 and later: https://stackoverflow.com/a/44186555/317052 So in your example it should still work if you remove `-N`. This is a much cleaner option than `local-name()` in my opinion (+1). – Daniel Haley Nov 24 '20 at 21:09
1

Another way, use local-name():

xml ed -d  '//*[local-name()="Package"]//*[local-name()="types"][.//*[local-name()="name"][./text()="ApexEmailNotifications"]]' test.xml
Jack Fleeting
  • 24,385
  • 6
  • 23
  • 45