Damon Cortesi's blog

Musings of an entrepreneur.

Extracting Unique Values in a For-each With XSL

| Comments

XML can be a wonderful thing, and XSL (eXtensible Stylesheet Language) can be even more wonderful in formatting XML output to do darn near anything you want it to.

Basic usage of XSL isn’t too difficult to get a grasp on, but the more advanced features such as keys, generate-id, preceding-sibling and others are not as easy to understand as I’ve found the available documentation and samples lacking.

My problem, specifically, was dealing with duplicate id’s within for-each loops, for example:

1
2
3
4
5
6
7
8
9
<?xml version="1.0" ?>
<store id=2>
  <donuts type=glazed>
  <donuts type=jelly-filled>
  <donuts type=jelly-filled>
</store>
<store id=10>
  <donuts type=glazed>
</store>

So what I wanted to happen was display one glazed and jelly-filled for store 2 and one glazed for store 10. However, what was happening was all or nothing - it would display all the donuts if I did not filtering, or just one glazed overall if I tried to use preceding. Then I came across preceding-sibling, which seemed to be what I wanted…but just wasn’t working, and I was getting very frustrated. I spent quite a bit of time trying to figure out how to extract this information, but came across no help until tonight when I stumbled upon this thread about preceding-sibling.

Apparently, XPath expressions normally return node-sets. Second, node-sets are processed in document order. So your select expression is returning the first member of the set “preceding-sibling::attribute/@name”, which is always the first in document order.

sigh

So what this means is that even though I was using preceding-sibling, I wasn’t using it correctly. It returns a set and it’s always ordered in the same way, which expains some of the results I received during testing…I just didn’t realize that’s what it was doing. Apparently the solution is as simple as using a “positional predicate”. So instead of “attribute/@name”, you would do “attribute[1]/@name” which would, in reality, reference the preceding-sibling as desired. An item on immediacy of preceding-siblings was also quite useful. Maybe the documentation needs to be better because other people have obviously had this problem as well!

Perhaps if Nessus didn’t spit out duplicate findings, this wouldn’t have been such a problem, but alas…it does.

Comments