Search code examples
jsonxmlshellxpathxidel

Xidel: Parse attributes into new object


Given is a verbose GC log from any Java virtual machine (could be any xml, so not tagging with java):

<?xml version="1.0" ?>

<verbosegc version="versioninformation">

<af type="nursery" id="49383" timestamp="Jan 01 01:34:54 2015" intervalms="33.821">
  <tenured freebytes="769243504" totalbytes="1610416128" percent="47" >
    <soa freebytes="198858272" totalbytes="805208064" percent="24" />
    <loa freebytes="570385232" totalbytes="805208064" percent="70" />
  </tenured>
  <gc></gc>
  <tenured freebytes="768800232" totalbytes="1610416128" percent="47" >
    <soa freebytes="198415" totalbytes="805208064" percent="24" />
    <loa freebytes="570385232" totalbytes="805208064" percent="70" />
  </tenured>
</af>

<af type="nursery" id="49384" timestamp="Jan 01 01:35:54 2015" intervalms="40.877">
  <tenured freebytes="768800232" totalbytes="1610416128" percent="47" >
    <soa freebytes="198415" totalbytes="805208064" percent="24" />
    <loa freebytes="570385232" totalbytes="805208064" percent="70" />
  </tenured>
  <gc></gc>
  <tenured freebytes="768320928" totalbytes="1610416128" percent="47" >
    <soa freebytes="197935696" totalbytes="805208064" percent="24" />
    <loa freebytes="570385232" totalbytes="805208064" percent="70" />
  </tenured>
</af>

So, I'd like to create a new object, which gets repeated for each garbage collection cycle with the timestamp and the used bytes (total minus free). The calculation works just fine, but the output does not. This is what I excpect to get:

[
  {
    "timestamp": "Jan 01 01:34:54 2015",
    "used": 8.41172624E8
  },
  {
    "timestamp": "Jan 01 01:35:54 2015",
    "used": 8.41615896E8
  },
]

I tried this command line, which sadly creates a null timestamp and a long list of heap information:

xidel --input-format=xml   -e "//af/tenured[1]/(heap:={used:=(@totalbytes - @freebytes):timestamp:=@timestamp})" gc.log --output-format=json-wrapped

The output looks like this:

[
  {
    "timestamp": [null],
    "used": [8.41172624E8, 8.41615896E8]
  }
]

Obviously not what I excpected.


Solution

  • You can actually write the entire JSON structure in the extract expression and do not need output-format:

    xidel --input-format=xml   -e "[ //af/tenured[1]/{'used':(@totalbytes - @freebytes),'timestamp':../@timestamp} ]" gc.log