Reputation: 269
I need to produce a DOT graph from the following XML.
<layout>
<layout-structure>
<layout-root id="layout-root" orientation="landscape">
<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-leaf xref="lay-1.03"/>
</layout-root>
</layout-structure>
<realization>
<text xref="lay-1.01"/>
<text xref="lay-1.02"/>
<graphics xref="lay-1.03 lay-1.04"/>
</realization>
</layout>
I use the following XQuery to generate the DOT markup:
declare variable $newline := ' ';
declare function local:ref($root) {
string-join((
for $chunk in $root/layout-chunk
return (
concat(' "', $root/@id, '" -- "', $chunk/@id, '";', $newline),
local:ref($chunk)
),
local:leaf($root)), "")
};
declare function local:leaf($root) {
for $leaf in $root/layout-leaf
return concat(' "', $root/@id, '" -- "', $leaf/@xref, '";', $newline)
};
let $doc := doc("layout-data.xml")/layout
let $root := $doc/layout-structure/*
return concat('graph "', $root/@id, '" { ', $newline, local:ref($root),'}')
The query above works fine and produces the following graph:
graph "layout-root" {
"layout-root" -- "header-text";
"header-text" -- "lay-1.01";
"header-text" -- "lay-1.02";
"layout-root" -- "lay-1.03";
"layout-root" -- "lay-1.04";
}
The result is shown below:
Now, what I would like to do is to assign a set of properties for each element in the DOT graph depending on their properties, defined under the realization element in the XML, as shown below:
This would, of course, require the following DOT markup:
graph "layout-root" {
"lay-1.03" [shape="box", style="filled", color="#b3c6ed"];
"lay-1.04" [shape="box", style="filled", color="#b3c6ed"];
"layout-root" -- "header-text";
"header-text" -- "lay-1.01";
"header-text" -- "lay-1.02";
"layout-root" -- "lay-1.03";
"layout-root" -- "lay-1.04";
}
I have written two additional variables and functions to select and write the required DOT markup:
declare variable $dotgraphics := '[shape="box", style="filled", color="#b3c6ed"]';
declare function local:gfx($doc) {
for $layout-leafs in $doc//layout-leaf
let $graphics := $doc/realization//graphics
where $graphics[contains(@xref, $layout-leafs/@xref)]
return concat($layout-leafs/@xref, ' ', $dotgraphics, ';', $newline)
};
My problem is: how do I include the function local:gfx to the working XQuery script above?
If I simply call the function *local:gfx($doc) before local:ref($root) as shown below,
return concat('graph "', $root/@id, '" { ', $newline, local:gfx($doc), $newline, local:ref($root),'}')
The query returns an error that a sequence of multiple items cannot be an argument for the concat function; how can this be fixed?
Upvotes: 1
Views: 1580
Reputation: 4241
You can use fn:string-join($strings[, $separator])
for this, which takes the strings as a sequence instead. If you use $newline
as the second parameter (the default is the empty string), it even inserts the line breaks for you:
string-join(('foo', 'bar', 'baz'), ' ')
yields
foo
bar
baz
Upvotes: 1