jerney
jerney

Reputation: 2243

XMLStarlet, XPath - How to remove attributes depending on node

I'm trying to use XMLStarlet to transform this (test.xml):

<?xml version="1.0"?>
<root xmlns:doc="http://www.test.com" doc:id="hello">
  <a doc:id="x"/>
  <a doc:id="x"/>
  <c doc:id="x">
    <a doc:id="x"/>
    <a doc:id="x"/>
    <c doc:id="x"/>
  </c>
</root>

into this (removing the doc:id attribute on all nodes except c):

<?xml version="1.0"?>
<root xmlns:doc="http://www.test.com" doc:id="hello">
  <a/>
  <b/>
  <c doc:id="hello">
    <a/>
    <b/>
    <c doc:id="hello"/>
  </c>
</root>

I've tried this, but it removes all of the doc:id attributes:

xml ed -N doc="http://www.test.com" -d "//@doc:id[not(self::c)]" test.xml

Upvotes: 2

Views: 435

Answers (1)

zx485
zx485

Reputation: 29052

You can use this concatenation of two xmlstarlet commands:

  1. The first one deletes(-d) all doc:id attributes which are not part of a <c> element (as you already did)
  2. The second part of the command updates(-u) the values(-v) of all doc:id attributes of the <c> elements.

This is the command:

xml ed -N doc="http://www.test.com" -d "//*[not(self::c)]/@doc:id" -u "//c/@doc:id" -v "hello" test.xml

The output is as desired.

Upvotes: 2

Related Questions