Hello,
I have a table with several fields that I display in a dashboard.
One column is from violation_details field, which contains XML data.
Note that I don't want to parse anything from this field, because depending on the violations the tags won't be the same.
Here is an example of a value for this field
<?xml version='1.0' encoding='UTF-8'?><BAD_MSG><violation_masks><block>58f7c3e96a0c279b-7e3f5f28b0000040</block><alarm>5cf7c3e97b0c6fdb-7e3f5f28b0000040</alarm><learn>5cf2c1e9730c2f5b-3d3c000830000000</learn><staging>0-0</staging></violation_masks><response_violations><violation><viol_index>56</viol_index><viol_name>VIOL_HTTP_RESPONSE_STATUS</viol_name><response_code>500</response_code></violation></response_violations></BAD_MSG>
How could I make this more readable like this :
<?xml version='1.0' encoding='UTF-8'?>
<BAD_MSG>
<violation_masks>
<block>58f7c3e96a0c279b-7e3f5f28b0000040</block>
<alarm>5cf7c3e97b0c6fdb-7e3f5f28b0000040</alarm>
<learn>5cf2c1e9730c2f5b-3d3c000830000000</learn>
<staging>0-0</staging>
</violation_masks>
<response_violations>
<violation>
<viol_index>56</viol_index>
<viol_name>VIOL_HTTP_RESPONSE_STATUS</viol_name>
<response_code>500</response_code>
</violation>
</response_violations>
</BAD_MSG>
I've seen this POST XML-to-display-in-a-proper-format-with-tag but it seems to use a deprecated method.
Is there a better way ?
Try something along these lines
| makeresults
| eval origData="<?xml version='1.0' encoding='UTF-8'?><BAD_MSG><violation_masks><block>58f7c3e96a0c279b-7e3f5f28b0000040</block><alarm>5cf7c3e97b0c6fdb-7e3f5f28b0000040</alarm><learn>5cf2c1e9730c2f5b-3d3c000830000000</learn><staging>0-0</staging></violation_masks><response_violations><violation><viol_index>56</viol_index><viol_name>VIOL_HTTP_RESPONSE_STATUS</viol_name><response_code>500</response_code></violation></response_violations></BAD_MSG>"
| rex mode=sed field=origData "s/<(?<!)/
</g s/>(?=<)/>
/g"
| rex max_match=0 field=origData "(?m)(?<line>^.+$)"
| fields - origData
| streamstats count as row
| mvexpand line
| eval open=if(match(line,"^\<(?!.*\/)"),1,null())
| eval undent=if(match(line,"^<\/"),-1,null())
| streamstats window=1 current=f values(open) as indent by row global=f
| streamstats sum(indent) as space by row global=f
| streamstats sum(undent) as unspace by row global=f
| fillnull value=0 unspace space
| eval spaces=space+unspace+len(line)
| eval line=printf("%".spaces."s",line)
| stats list(line) as line by row
| eval line=mvjoin(line,"
")
| fields - row
You could add some additional tweaking to deal with the initial xml line if you are certain it is always there
You can do the more or less same thing with rex alone
https://regex101.com/r/KFMlCd/1
EDIT: Ready Splunk version:
| makeresults
| eval origData="<?xml version='1.0' encoding='UTF-8'?><BAD_MSG><violation_masks><block>58f7c3e96a0c279b-7e3f5f28b0000040</block><alarm>5cf7c3e97b0c6fdb-7e3f5f28b0000040</alarm><learn>5cf2c1e9730c2f5b-3d3c000830000000</learn><staging>0-0</staging></violation_masks><response_violations><violation><viol_index>56</viol_index><viol_name>VIOL_HTTP_RESPONSE_STATUS</viol_name><response_code>500</response_code></violation></response_violations></BAD_MSG>"
| rex field=origData mode=sed "s/<([^\\/][^>]+)>(?=.*<\\/\\1>)/\n<\1>/g"
| rex field=origData mode=sed "s/><\//>\n<\//g"
It doesn't indent though.
Hi @ITWhisperer,
the request is great ! it's working fine in the search indeed.
Unfortunately it doesn't work within a dashboard source code : first line is highlighted with the message "unencoded <"
| rex mode=sed field=origData "s/<(?<!)/
</g s/>(?=<)/>
/g"
it there a way to make the request understandable in dashboard UI ?
Either edit the search from the panel in dashboard edit mode or use & in the XML source