2016-04-11 13 views
0

XQY Datei:XQuery: Debug-rekursive Funktion

import module namespace functx="http://www.functx.com"; 

declare variable $defaultXMLNS:="http://www.test.com#"; 
declare variable $defaultXMLBase:=$defaultXMLNS; 

declare function local:descriptionConstructorTail(
    $seq as item()*, 
    $i as xs:integer?, 
    $res as item()* 
) 
{ 
    if($i <= 0) 
    then $res 
    else local:descriptionConstructorTail($seq, 
      $i - 1, 
      functx:value-union($res, 
        (<test1 about="{$seq[$i]/@value}"/>))) 
}; 

declare function local:descriptionConstructor($pnode as node()*) 
{ 
    local:descriptionConstructorTail($pnode//xs:enumeration, 
     count($pnode//xs:enumeration), 
     ()) 
}; 

element test 
{ 
    local:descriptionConstructor(doc("./test2.xsd")) 
} 

XSD-Datei:

<?xml version="1.0"?> 
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    attributeFormDefault="unqualified" 
    elementFormDefault="qualified"> 

    <xs:simpleType name="size"> 
    <xs:restriction base="xs:string"> 
     <xs:enumeration value="small" /> 
     <xs:enumeration value="medium" /> 
     <xs:enumeration value="large" /> 
    </xs:restriction> 
    </xs:simpleType> 

</xs:schema> 

Ich habe 2 Stunden um mit diesem kleinen Programm durcheinander. Die Ausgabe wird immer nicht erwartet.

$ basex test2.xqy 
<test/> 

Für das Beispiel XSD-Datei oben, möchte ich eine Ausgabe wie diese haben: kann nicht logisch

<test> 
<test1 about="small"/> 
<test1 about="medium"/> 
<test1 about="large"/> 
</test> 

Dieses Beispiel gesehen, weil Sie verwenden müssen, um das nicht-rekursive Funktion zu tun. Aber ich möchte das als Übung für die rekursive Funktion tun.

+0

Die Namespaces, die Sie deklariert haben und die im Dokument definiert sind, unterscheiden sich ('#' am Ende des Dokuments). –

+0

@JensErat Eigentlich hat dies keinen Einfluss auf die Ausgabe –

Antwort

0

Während die functx Bibliothek eine sehr bequeme Sammlung von Dienstprogrammfunktionen ist, ist es wichtig zu wissen, was genau diese tun, damit Sie Überraschungen wie diese vermeiden können. functx:value-union(...) wird wie folgt umgesetzt:

declare function functx:value-union(
    $arg1 as xs:anyAtomicType*, 
    $arg2 as xs:anyAtomicType* 
) as xs:anyAtomicType* { 
    distinct-values(($arg1, $arg2)) 
}; 

es also gilt nur distinct-values(...) auf die Verkettung ihrer Eingänge. Da diese Funktion mit Werten vom Typ xs:anyAtomicType arbeitet, sind Ihre XML-Knoten atomisiert. Dies hinterlässt nur ihre Textinhalte, die deine Elemente nicht haben. Also baut man einfach die Vereinigung leerer Sequenzen immer wieder auf.

Dies sollte funktionieren:

declare function local:descriptionConstructorTail($seq as item()*, $i as xs:integer?, $res as item()*) { 
    if($i <= 0) then $res 
    else local:descriptionConstructorTail($seq, $i - 1, distinct-values(($res, $seq[$i]/@value))) 
}; 

declare function local:descriptionConstructor($pnode as node()*) { 
    let $enums := $pnode//xs:enumeration 
    for $res in local:descriptionConstructorTail($enums, count($enums),()) 
    return <test1 about="{$res}"/> 
}; 

element test { 
    local:descriptionConstructor(doc("./test2.xsd")) 
} 

Durch die Art und Weise Ihrer rekursive Funktion der Rekursion Regelung durch die höhere Ordnung Funktion fold-right(...) codiert folgt, so dass man auch schreiben kann:

declare function local:descriptionConstructor($pnode as node()*) { 
    for $res in 
    fold-right(
     $pnode//xs:enumeration, 
    (), 
     function($enum, $res) { 
     distinct-values(($enum/@value, $res)) 
     } 
    ) 
    return <test1 about="{$res}"/> 
}; 

element test { 
    local:descriptionConstructor(doc("./test2.xsd")) 
}