3

Given an xml document like

<root>
  <row>
    <a>2</a>
    <b>1</b>
    <c>8</c>
  </row>
  <row>
    <b>5</b>
    <a>2</a>
    <c>8</c>
  </row>
  <row>
    <a>2</a>
    <c>8</c>
    <b>6</b>
  </row>
</root>

Is there an easy way to assert that the XML document is sorted on element B in XMLUnit

Edit: I have an odd problem with a piece of software that I can not change where the value of the XML tags in any given node needs to be in a specific order. I'd like it for my test harness to enforce this set of rules before any other validation.

sal
  • 23,373
  • 15
  • 66
  • 85
  • I can't think of any (but then again, I don't know XmlUnit et al). Why do you want to do this? Is this the output of some method to be tested? Can you refactor the code to produce output in a more testable format? – Péter Török Apr 26 '10 at 20:23
  • @Peter, I'm dealing with some legacy software where the XML needs to be in a quirky format. I'd like to make sure my xml output always obeys those quirky rules. – sal Apr 26 '10 at 21:29
  • Good Question (+1). See my answer for a very simple solution. :) – Dimitre Novatchev Apr 27 '10 at 12:57

3 Answers3

2

Use the value of the following simple XPath 1.0 expression:

not(//b[. > following::b])

Dimitre Novatchev
  • 240,661
  • 26
  • 293
  • 431
1

You can build an assertion around an XPath selection.

Probably the simplest way would be to use the XPath expression /root/row/b, request the NODESET result type, then copy the text from each result node into a List structure. You can assert that the text in that list is equal to an "expected" list created with the Arrays.asList() method (I'm assuming you're using Java).

Anon
  • 126
  • 1
  • This was what I was doing and I wasn't happy with it. For starters, there was too much code that was specific to a particular test and more code that might have to change as my code changed. – sal Apr 27 '10 at 18:24
1

If you can execute XQuery, then the XQuery assertion:

every $i in (1 to count ($x/row) - 1)
satisfies 
   let $j :=  $i + 1   
   return number($x/row[$i]/b) <= number($x/row[$j]/b)

where $x is the document, is true if the rows are in ascending order of b, false otherwise

Chris Wallace
  • 495
  • 3
  • 11
  • I'm too junior to comment on Dimitre's neat answer but shouldn't it be not($x//b[number(.) > following::b/number(.)]) for this numeric data and isnt this O N^2 since every b is compared with all the following b's? – Chris Wallace Apr 27 '10 at 14:15