Search code examples
xquerymarklogic

How to get node variables out of an error


I have a short function, where if anything goes wrong at any part of the process, I can get the data from previous parts of the process and write them out for future investigation. For example:

try {
  let $var1 := element outer {
    element inner {"test"}
  }
  let $var2 := element outer2 {
    element inner2 {"test2"}
  }
  let $var3 as xs:string := 2
  return ()
}
catch($e) {
  xdmp:document-insert(
    "testdoc.xml",
    element toplevel {
      element test1 {$e/error:stack/error:frame/error:variables/error:variable[error:name eq "var1"]/error:value},
      element test2 {$e/error:stack/error:frame/error:variables/error:variable[error:name eq "var2"]/error:value}
    }
  )
}

This produces the record:

<toplevel>
  <test1>
    <error:value xmlns:error="http://marklogic.com/xdmp/error"><outer><inner>test</inner></outer></error:value>
  </test1>
  <test2>
    <error:value xmlns:error="http://marklogic.com/xdmp/error"><outer2><inner2>test2</inner2></outer2></error:value>
  </test2>
</toplevel>

When I'd like to produce this:

<toplevel>
  <test1>
    <outer>
      <inner>test</inner>
    </outer>
  </test1>
  <test2>
    <outer2>
      <inner2>test2</inner2>
    </outer2>
  </test2>
</toplevel>

Any thoughts? It's possible that an "error" record only keeps a shortened version of what was in the variable, not the whole value. If that's so, can anyone think of another way to get data after an unexpected break?

Addendum: Though the solution given will work for passing small variables through error, longer variables are truncated.


Solution

  • Similar to what Martin Honnen suggested in the comments, but instead of * you might consider using node() so that if any variables happen not to be elements, they are still selected:

    element toplevel {
      element test1 {$e/error:stack/error:frame/error:variables/error:variable[error:name eq "var1"]/error:value/node()},
      element test2 {$e/error:stack/error:frame/error:variables/error:variable[error:name eq "var2"]/error:value/node()}
    }