Hi all,
this is gonna be somewhat longish - thx for your consideration.
I have written an XQuery that works fine in XMLSpy 2007 rel. 3 Enterprise (native Windows), but doesn't with xmlpatterns version 0.1 using Qt 4.7.1 (SLES-10) unless considerably tweaked. The question I have is: Are these issues of Qt xmlpatterns', or is it just my fault/lack of understanding? Also, should my solution be clumsy, please feel free to propose enhancements. 
I should mention that I managed to work around these issues to reach my goal for the time being, yet the nature of this post is not purely academic.
I will first post the original query, then name the issues and tweaks. In the zip attached you will find the .xq file (containing both the original and the tweaked version) and the data it is meant to work on (actually an .xsd file edit: that I do not have control over).
The query should be executed like this (the last param is obsolete edit: until one wants to access a single attribute rather than the element sequence; see below):
xmlpatterns test.xq -param fileToOpen=CSBF_V_1_3.xsd -param dottedPath=Angebot.Bieter.ARGE_Mitglied.NUTS -param attrName=type
xmlpatterns test.xq -param fileToOpen=CSBF_V_1_3.xsd -param dottedPath=Angebot.Bieter.ARGE_Mitglied.NUTS -param attrName=type
To copy to clipboard, switch view to plain text mode
and it should return, in order, this sequence (abbreviated for clarity):
<xsd:element name="Angebot" .../>
<xsd:element name="Bieter" .../>
<xsd:element name="ARGE_Mitglied" .../>
<xsd:element name="NUTS" .../>
<xsd:element name="Angebot" .../>
<xsd:element name="Bieter" .../>
<xsd:element name="ARGE_Mitglied" .../>
<xsd:element name="NUTS" .../>
To copy to clipboard, switch view to plain text mode
that is, the schema elements according to the "dottedPath" parameter.
This is the query that works in XMLSpy:
xquery version "1.0";
declare namespace csbf= "http://www.foo.de/csbf";
declare namespace xsd = "http://www.w3.org/2001/XMLSchema";
declare variable $fileToOpen as xs:anyURI external;
declare variable $inDoc as document-node() := doc($fileToOpen);
declare variable $dottedPath as xs:string external;
declare variable $attrName as xs:string external;
(:
This is ok for XMLSpy, but Qt xmlpatterns complains about the leading dot in
'let $e := ." (Error XPDY0002 [...] The focus is undefined.).
We therefore provide a variant to overcome this issue (see below).
:)
declare function csbf:schema-path($names as xs:string*) as element()*
{
if ( empty($names) )
then ()
else
let $e := .[last()]/child::xsd:sequence/child::xsd:element[@name=$names[1]]
let $complexTypeDef := $inDoc//xsd:complexType[@name=$e/@type/string()]
let $anchor := if ( exists($complexTypeDef ) )
then $complexTypeDef
else $e/xsd:complexType
return ( $e , $anchor/csbf:schema-path(subsequence($names, 2)) )
};
$inDoc//xsd:schema/xsd:element/xsd:complexType/csbf:schema-path(tokenize($dottedPath, '\.'))
xquery version "1.0";
declare namespace csbf= "http://www.foo.de/csbf";
declare namespace xsd = "http://www.w3.org/2001/XMLSchema";
declare variable $fileToOpen as xs:anyURI external;
declare variable $inDoc as document-node() := doc($fileToOpen);
declare variable $dottedPath as xs:string external;
declare variable $attrName as xs:string external;
(:
This is ok for XMLSpy, but Qt xmlpatterns complains about the leading dot in
'let $e := ." (Error XPDY0002 [...] The focus is undefined.).
We therefore provide a variant to overcome this issue (see below).
:)
declare function csbf:schema-path($names as xs:string*) as element()*
{
if ( empty($names) )
then ()
else
let $e := .[last()]/child::xsd:sequence/child::xsd:element[@name=$names[1]]
let $complexTypeDef := $inDoc//xsd:complexType[@name=$e/@type/string()]
let $anchor := if ( exists($complexTypeDef ) )
then $complexTypeDef
else $e/xsd:complexType
return ( $e , $anchor/csbf:schema-path(subsequence($names, 2)) )
};
$inDoc//xsd:schema/xsd:element/xsd:complexType/csbf:schema-path(tokenize($dottedPath, '\.'))
To copy to clipboard, switch view to plain text mode
The issues are:
(1) See function comment: Qt xmlpatterns doesn't set the context/focus dynamically and complains about the dot. I can work around this by adding another function parameter (see below).
(2) The resulting sequence is not in-order, but like this:
<xsd:element name="Angebot" .../>
<xsd:element name="ARGE_Mitglied" .../>
<xsd:element name="NUTS" .../>
<xsd:element name="Bieter" .../>
<xsd:element name="Angebot" .../>
<xsd:element name="ARGE_Mitglied" .../>
<xsd:element name="NUTS" .../>
<xsd:element name="Bieter" .../>
To copy to clipboard, switch view to plain text mode
The element "Bieter" supposed to be second comes last. (Oops, can't [COLOR] inside [CODE] here?)
(3) (minor) xmlpattern warns that $attrName was not used. This can be worked around by adding
declare variable $attr as xs:string := $attrName;
declare variable $attr as xs:string := $attrName;
To copy to clipboard, switch view to plain text mode
and use that instead.
This is the tweaked query that works with both XMLSpy and xmlpatterns:
(edit: order is still incorrect, but workaround shown - see text below)
xquery version "1.0";
declare namespace csbf= "http://www.foo.de/csbf";
declare namespace xsd = "http://www.w3.org/2001/XMLSchema";
declare variable $fileToOpen as xs:anyURI external;
declare variable $inDoc as document-node() := doc($fileToOpen);
declare variable $dottedPath as xs:string external;
declare variable $attrName as xs:string external;
(:
Variant for Qt xmlpatterns compliance (see above).
:)
declare function csbf:schema-path($e as element(), $names as xs:string*) as element()*
{
if ( empty($names) )
then ()
else
let $e := $e/child::xsd:sequence/child::xsd:element[@name=$names[1]]
let $complexTypeDef := $inDoc//xsd:complexType[@name=$e/@type/string()]
let $anchor := if ( exists($complexTypeDef ) )
then $complexTypeDef
else $e/xsd:complexType
return ( $e , $anchor/csbf:schema-path($anchor, subsequence($names, 2)) )
(: return insert-before( $anchor/csbf:schema-path($anchor, subsequence($names, 2)), 1, $e ) :)
};
let $names := tokenize($dottedPath, '\.')
let $parent := $inDoc//xsd:schema/xsd:element/xsd:complexType
(:this returns the element sequence. comment out for attribute access.:)
return csbf:schema-path($parent, $names)
(:this returns the attribute value. uncomment as needed.:)
(:let $schema-element := $parent/csbf:schema-path($parent, tokenize($dottedPath, '\.'))[@name=$names[last()]]
return $schema-element/@*[name()=$attrName]/string():)
xquery version "1.0";
declare namespace csbf= "http://www.foo.de/csbf";
declare namespace xsd = "http://www.w3.org/2001/XMLSchema";
declare variable $fileToOpen as xs:anyURI external;
declare variable $inDoc as document-node() := doc($fileToOpen);
declare variable $dottedPath as xs:string external;
declare variable $attrName as xs:string external;
(:
Variant for Qt xmlpatterns compliance (see above).
:)
declare function csbf:schema-path($e as element(), $names as xs:string*) as element()*
{
if ( empty($names) )
then ()
else
let $e := $e/child::xsd:sequence/child::xsd:element[@name=$names[1]]
let $complexTypeDef := $inDoc//xsd:complexType[@name=$e/@type/string()]
let $anchor := if ( exists($complexTypeDef ) )
then $complexTypeDef
else $e/xsd:complexType
return ( $e , $anchor/csbf:schema-path($anchor, subsequence($names, 2)) )
(: return insert-before( $anchor/csbf:schema-path($anchor, subsequence($names, 2)), 1, $e ) :)
};
let $names := tokenize($dottedPath, '\.')
let $parent := $inDoc//xsd:schema/xsd:element/xsd:complexType
(:this returns the element sequence. comment out for attribute access.:)
return csbf:schema-path($parent, $names)
(:this returns the attribute value. uncomment as needed.:)
(:let $schema-element := $parent/csbf:schema-path($parent, tokenize($dottedPath, '\.'))[@name=$names[last()]]
return $schema-element/@*[name()=$attrName]/string():)
To copy to clipboard, switch view to plain text mode
Since for now I need only access the cardinality, and the "dottedPath" tokens are presumably distinct, I can work around the second issue as shown in the above code (currently commented) accessing the element by name. However, this is not robust, and the assumption may fail in the future.
Any enlightenment is very much appreciated!
Bookmarks