grahl/ch

Minutiae: Return the content of an element with xmlstarlet

It’s not uncommon to find desktop applications storing some information in XML files. While it’s nice that it isn’t binary and it might be technically human readable, it’s hardly as easy to read or edit as a CSV or plaintext file.

So, when you want to export data from XML, xmlstarlet is a parser that can be a quick solution to the problem. It’s documentation, though, is a bit arcane. Every six months or so, I start googling the same problem for xmlstarlet: How to get the content of an element, not just the value of an attribute. I might be using the wrong terms to find what I’m looking for, since even old posts of mine show up in Google for it.

Either way, the solution is simply a . and here is an example that uses the XML of KDE’s Wallet Manager:

xmlstarlet sel -t -m //map -v @name -n -m mapentry -o " " -v @name -o " : " -v . -n wallet.xml

The code above will iterate through all map elements, write the name attribute and a newline, iterate through all mapentries of the map and write the value of the subsequent name value indented by two spaces and then finally the actual content of the mapentry element after a colon separated by whitespaces. So there you go, an entire post because I don’t think the dot-for-content is documented well. The above example then converts takes XML structured as in the following example:

<map name="http-www.example.com">
  <mapentry name="login">a@example.com</mapentry>
  <mapentry name="login-2">b@example.com</mapentry>
  <mapentry name="password">12345</mapentry>
  <mapentry name="password-2">54321</mapentry>
</map> 

This is then turned into:

 http-www.example.com
  login : a@example.com
  login-2 : b@example.com
  password : 12345
  password-2 : 54321