2
votes

I need to select nodes with distinct name attribute values considering the first character only.

The XML is

<A>
    <B name="X_01"/>
    <B name="X_02"/>
    <B name="Y_01"/>
    <B name="X_03"/>
    <B name="Z_01"/>
    <B name="Y_02"/>
</A>

Desired output

<B name="X_01"/>
<B name="Y_01"/>
<B name="Z_01"/>

It doesn't have to be the first occurrence of B with the distinct first character value in the name attribute.

I am new to XQuery and wasn't able to build a working statement.

Thanks for your help

2

2 Answers

2
votes
xquery version "1.0";

let $xml := <A>
<B name="X_01"/>
<B name="X_02"/>
<B name="Y_01"/>
<B name="X_03"/>
<B name="Z_01"/>
<B name="Y_02"/>
</A>

let $distinct-values := fn:distinct-values(
    for $attr in $xml/B/@name
    return fn:substring($attr,1,1)
  )

return for $prefix in $distinct-values
  return $xml/B[fn:starts-with(@name, $prefix)][1]
1
votes

Slightly simpler implementation using the group by clause thusly:

let $stuff := <A>
    <B name="X_01"/>
    <B name="X_02"/>
    <B name="Y_01"/>
    <B name="X_03"/>
    <B name="Z_01"/>
    <B name="Y_02"/>
</A>
return 
  for $b in $stuff/B
  group by $val := substring($b/@name, 1, 1)
  return $b[1]