I’ve looked through the other XML discussions here and, though they’ve gotten me far, I just can’t seem to grok how to get from where they’ve gotten me to where I need to be. Here’s a sanitized approximation of my XML:
Ideally, I’m trying to pull out the FQDN of the Server in the ServerPriorityBlock named “Priority1”. Alternatively, I’ll take a sorted, comma-separeted list of all of the “Address” values in that ServerPriorityBlock. Here’s what I’ve managed so far:
Q: node values of attributes whose (node name of it = "Address") of child nodes of selects "ServerSettings/CommConf/ServerList/ServerPriorityBlock" of xml document of file "C:\data.xml"
A: 1.2.3.4
A: server1.servers.com
A: 2.3.4.5
A: server2.servers.com
I’m trying to get this to just be “server1.servers.com” or, barring that, “1.2.3.4, server1.servers.com”. Any ideas? (Also, any good documentation for traversing and extracting data from XML documents with BigFix Relevance that I’m just not finding with my Google-fu?)
One method would be to group by ServerPriorityBlock, iterating over each block of ‘child nodes of it’; then concatenating together the attributes -
Q: (concatenation ", " of node values of attributes whose (node name of it = "Address") of child nodes of it) of selects "ServerSettings/CommConf/ServerList/ServerPriorityBlock" of xml document of file "C:\temp\test.xml"
A: 1.2.3.4, server1.servers.com
A: 2.3.4.5, server2.servers.com
T: 0.411 ms
I: plural string
Another method would be to take all of the Address nodes together, and remove any that match an IP address format using a regular expression:
Q: node values whose (not exists matches (regex("^[0-9]{1,3}[.][0-9]{1,3}[.][0-9]{1,3}[.][0-9]{1,3}$")) of it) of attributes whose (node name of it = "Address") of child nodes of selects "ServerSettings/CommConf/ServerList/ServerPriorityBlock" of xml document of file "C:\temp\test.xml"
A: server1.servers.com
A: server2.servers.com
T: 0.617 ms
I: plural string
I love XML, and in particular XPATH. I would recommend INI files for very simple data, but I like XML for pretty much anything otherwise.
Don’t google for how to do this with BigFix… that will lead you down the wrong path. You need to figure out how to do this with XPATH, and then use the XPATH statement you come up with in the xpaths or selects inspectors.
I haven’t test this at all, but this should be very close:
node values whose(it as string as trimmed string as lowercase ends with ".com") of selects "ServerSettings/CommConf/ServerList/ServerPriorityBlock[@Name='Priority1']/Server/@Address" of xml document of file "C:\data.xml"
Thanks, Jason! I was primarily stuck on how to just get the “Priority1” information, but there’s lots of great sample code in your answer that I’m going to have to remember (or, at least, remember that it’s here and look for it again later).
Thanks, James! It works great with a little tweaking to match my actual data (and getting rid of the “, it” at the beginning due to a type mismatch). I had assumed that, as with much of how BigFix does things in relevance language, there would be no external sources of information that applied. Thanks for the XPATH info … that URL looks awesome (and so much better to test against than Q&A)!!
If you want to easily return to a post here later, you can Like or Bookmark it. Then when you select your avatar in the upper-right, you can see your own “Bookmarks” and “Likes Given”.
Another great resource for sample code is http://bigfix.me, if you haven’t come across that site yet.
Thanks, Jason. I do indeed know about http://bigfix.me and have been using BigFix for the better part of a decade. Unfortunately, the things I usually end up looking for use terms so generic that half of the web comes up in the results.
In the case of the WMI inspectors in BigFix, figure out how to do it with WMI online or with a WMI Explorer GUI, then apply that to the inspector.
In the case of the SQLite inspectors, figure out how to do it with SQLite, then use that in the inspector.
In the case of the XPATH inspectors, figure out how to do it with XPATH in general, then go from there with the inspector.
There are many cases where you should figure out how to do something in the general case, and then apply that to the inspectors. I’m sure there are other examples. All of the inspectors listed above are using an existing API or library to actually do the query, so it isn’t the inspector that is the hard part, it is figuring out the query that would be required even if BigFix wasn’t being used at all.
Argh … so NOW the problem is that I also need to do this same action on both Windows & Mac OS X and the XML inspectors are Windows-only. :-/ Off to mess with “following text of first blah blah blah” again…
concatenation " " of ((substrings between "%22" of following text of first "Priority1" of preceding text of first "</ServerPriorityBlock>" of lines of file "C:\data.xml") whose (it as string as trimmed string as lowercase ends with ".com"))
I’m really coming to love Regexen, seem to solve so many complex cases. Try this on:
//Match the strings between the quotes inside a "Server Address" node
q: parenthesized parts 2 of matches(regex("(Server Address=[%22])([^%22]*)")) of lines of file "c:\temp\test.xml"
A: 1.2.3.4
A: server1.servers.com
A: 2.3.4.5
A: server2.servers.com
T: 0.442 ms
I: plural substring
// Remove the strings that are an IP address
q: it whose ((not exists matches (regex("^[0-9]{1,3}[.][0-9]{1,3}[.][0-9]{1,3}[.][0-9]{1,3}$")) of it)) of parenthesized parts 2 of matches(regex("(Server Address=[%22])([^%22]*)")) of lines of file "c:\temp\test.xml"
A: server1.servers.com
A: server2.servers.com
T: 0.695 ms
I: plural substring
RegEx is very powerful, but I would recommend using it sparingly and only where required. Other text parsing options are more human readable and deterministic.
RegEx is a bit like WMI or SHA1… it is possible to create a query that given the right input will take so long to execute that it will cause problems.