ritzdiamond
ritzdiamond

Reputation: 269

XQuery tokenize strings with single and multiple values

I have the following XML file:

<layout>
 <layout-structure>
  <layout-root id="layout-root">
    <layout-chunk id="header-text">
         <layout-leaf xref="lay-1.01"/>
         <layout-leaf xref="lay-1.02"/>
    </layout-chunk>
    <layout-leaf xref="lay-1.03"/>
  </layout-root>
  <layout-root id="layout-root-two">
    <layout-chunk id="header-text-two">
     <layout-leaf xref="lay-1.04"/>
     <layout-leaf xref="lay-1.05"/>
     <layout-leaf xref="lay-1.06"/>
    </layout-chunk>
  <layout-leaf xref="lay-1.07"/>
 </layout-root>
</layout-structure>

<realization>
  <text xref="lay-1.01 lay-1.04"/>
  <text xref="lay-1.02 lay-1.05"/>
  <graphics xref="lay-1.03 lay-1.06" type="1"/>
  <graphics xref="lay-1.07" type="2"/>
</realization>
</layout>

I want to extract the values for the xref attribute of the graphics element, in order to limit the output in the for clause of the function shown below.

declare function local:gfx($root, $graphics) {
let $graphic-xrefs := tokenize($graphics/@xref, " ")
for $layout-leafs in $root//layout-leaf[@xref = $graphic-xrefs]
return concat('"', $layout-leafs/@xref, '" ', $dotgraphics, ';', $newline) 
};

This, however, causes an error because some of the xref attributes under the graphics element contain a single value, as in the case of <graphics xref="lay-1.07"/>.

Is it possible to use tokenize to fetch the graphics/xref values, or should I use a different approach?

Upvotes: 1

Views: 1614

Answers (2)

Daniel Haley
Daniel Haley

Reputation: 52878

You could try changing the way you create $graphic-xrefs...

declare function local:gfx($root, $graphics) {
    let $graphic-xrefs := 
        for $xref in $graphics/@xref
        return
            tokenize($xref,' ')
    for $layout-leafs in $root//layout-leaf[@xref = $graphic-xrefs]
    return concat('"', $layout-leafs/@xref, '" ', $dotgraphics, ';', $newline) 
};

Upvotes: 1

dirkk
dirkk

Reputation: 6218

This should not cause a problem, as the tokenize will simply return the whole string if the split string is not within the search string.

For dealing with such in general a normal if (...) then ... else ... statement might be useful. Additionally you might want to use the try { ... } catch {...} construct to handle unexpected conditions.

Your code actually works as expected when I run this:

declare variable $t :=
<layout>
 <layout-structure>
  <layout-root id="layout-root">
    <layout-chunk id="header-text">
         <layout-leaf xref="lay-1.01"/>
         <layout-leaf xref="lay-1.02"/>
    </layout-chunk>
    <layout-leaf xref="lay-1.03"/>
  </layout-root>
  <layout-root id="layout-root-two">
    <layout-chunk id="header-text-two">
     <layout-leaf xref="lay-1.04"/>
     <layout-leaf xref="lay-1.05"/>
     <layout-leaf xref="lay-1.06"/>
    </layout-chunk>
  <layout-leaf xref="lay-1.07"/>
 </layout-root>
</layout-structure>

<realization>
  <text xref="lay-1.01 lay-1.04"/>
  <text xref="lay-1.02 lay-1.05"/>
  <graphics xref="lay-1.03 lay-1.06" type="1"/>
  <graphics xref="lay-1.07" type="2"/>
</realization>
</layout>;

declare function local:gfx($root, $graphics) {
let $graphic-xrefs := tokenize($graphics/@xref, " ")
for $layout-leafs in $root//layout-leaf[@xref = $graphic-xrefs]
return $layout-leafs/@xref
};

local:gfx($t, $t/realization/graphics[2])

Please note, that the last <layout> in your code snippet should actually be a closing statement.

Upvotes: 0

Related Questions