3

Given the following XML

<Address>
 <CountryName>France</CountryName>
</Address>
...
<Address>
 <CountryName>Germany</CountryName>
</Address>
...
<Address>
 <CountryName>Spain</CountryName>
</Address>

How can I count the number of distinct countries using XPath 1.0?

The list of addresses is very long and contains many distinct countries so I want to avoid having to express each one specifically.

Splic
  • 298
  • 3
  • 8

1 Answers1

4

Select the count of all the CountryName elements who's value is not the same value as the CountryName elements that are children of the current CountryName element's parent's following-siblings that are Address elements:

count(//Address/CountryName[not(.=../following-sibling::Address/CountryName)])
Mads Hansen
  • 63,927
  • 12
  • 112
  • 147
  • You are assuming records are sorted by CountryName, I think. – michael.hor257k Jun 04 '14 at 00:12
  • No, sort order does not matter. – Mads Hansen Jun 04 '14 at 00:26
  • 2
    Nice one! We can avoid assuming that all Address elements are siblings by evaluating (on the root element) `count(./descendant::CountryName[not( . = preceding::CountryName)])` (@michael.hor257k - no, sorted input would be required only if we added [1] to the following-sibling expression.) – C. M. Sperberg-McQueen Jun 04 '14 at 00:34
  • @C.M.Sperberg-McQueen Yes, I got that when told the first time, thank you. I just thought that it was well established that this method is "very inefficient" (quoting from the above article), so I didn't think anyone would suggest it - esp. as OP states that "the list of addresses is very long". – michael.hor257k Jun 04 '14 at 00:54
  • Apologies; no offense intended. As for the efficiency -- sometimes it matters. – C. M. Sperberg-McQueen Jun 04 '14 at 04:33
  • @C.M.Sperberg-McQueen None taken. – michael.hor257k Jun 04 '14 at 06:15
  • @C.M.Sperberg-McQueen your answer ended up being perfect - I neglected to imply in my OP that the Addresses were indeed not siblings. Thank you for the suggestion! – Splic Jun 10 '14 at 16:33