1
votes

I have modified my code with regular expression but I have problems with fn:tokenize. This is a bit part of my xml file:

<radix>
...
<EV>
  <accoppiamenti>
     <accoppiamento specie="e01" />
  </accoppiamenti>
</EV>
  <accoppiamenti>
     <accoppiamento specie="e00" />
     <accoppiamento specie="e01" />
     <accoppiamento specie="e02" />
  </accoppiamenti>
</EV>
...
</radix>

This is the part of my file xquery with tokenize:

for $ev in $snapshot/EV
let $stringa := $ev/accoppiamenti//accoppiamento/@specie
return(
    fn:tokenize($stringa,"e")        
)

The expected output is 01 00 01 02 but the effective output is 0100 (without space). What's the trouble? Thanks at all for the helps.

2
which xquery processor? I think this shouldn't even work because fn:tokenize(..) expects a single entry as the first parameter and you're giving it a sequence (in the second 'accoppiamenti'). - Ewout Graswinckel
I use ExistDB. But if I print $stringa (with data($stringa) ), it print the correct value: 01000102 - Local Hero
@EwoutGraswinckel Can I do a casting of $stringa to make it work for fn:tokenize? - Local Hero
Have you tried fn:tokenize(string-join($stringa),"e") ? I'm not really sure what you want to achieve though. If there is always an e in front then it's even overkill to use tokenize, you can just loop over specie attributes and remove the e. - Ewout Graswinckel
@EwoutGraswinckel I solved! I mustn't use tokenize, simply I use $stringa[1] for e01, $stringa[2] for e00 etc. Now I must cycle from the element $string[4] to the element $string[last()-3]. How can I do? Is there a cycle for in C style? - Local Hero

2 Answers

3
votes

Tokenize can be useful, but needs to be applied to single values at a time. Not sure why eXistDB is appears to be casting things to number before output. In your case, you don't really need tokenize. The older character-by-character replacement function fn:translate() will do too. And if you want make sure results are space-separated, try wrapping the for in a fn:string-join():

fn:string-join(
  for $a in $snapshot/EV/accoppiamenti//accoppiamento/@specie
  return
    fn:translate($a,"e", ""),
" ")

If you want to reverse order of things, just wrap the for in fn:reverse(), before you string-join everything. You can nest for loops if you want to iterate over specie attributes within each EV separately..

HTH!

1
votes

If you want to stick to fn:tokenize(...) (although @grtjn's answer will probably be more efficient), you need to apply the function to every single element, for example in a node step:

for $ev in $snapshot/EV
return $ev/accoppiamenti//accoppiamento/fn:tokenize(@specie,"e")