From: Alfredo C. <alf...@gm...> - 2021-07-07 11:42:01
|
Hi All, thanks for your suggestions. I moved from Finian approach to manage a somewhat more complex scenario. With this function: declare function local:elems($tkns as xs:string*, $pos as xs:integer) { if ($tkns[$pos]) then ( if(starts-with($tkns[$pos + 1], '@')) then ( let $attr:=replace($tkns[$pos + 1],"@",'') return element {$tkns[$pos]} {attribute {$attr} {''}, local:elems($tkns, $pos + 2)} ) else( element {$tkns[$pos]} {local:elems($tkns, $pos + 1)} ) ) else () }; I can manage this path for elements: teiHeader/fileDesc/sourceDesc/msDesc/msIdentifier/idno And this path for attributes: teiHeader/fileDesc/sourceDesc/msDesc/physDesc/objectDesc/@form They become: <teiHeader> <fileDesc> <sourceDesc> <msDesc> <msIdentifier> <idno/> </msIdentifier> </msDesc> </sourceDesc> </fileDesc> </teiHeader> and: <teiHeader> <fileDesc> <sourceDesc> <msDesc> <physDesc> <objectDesc form=""/> </physDesc> </msDesc> </sourceDesc> </fileDesc> </teiHeader> I have all the paths in a sequence so i can parse them: for $path in $tei-paths let $token:=tokenize($path, '/') let $result:=local:elems($token, 1) return $result *The problem is that I have to merge all the pieces before storing them in a file*, the two xml fragments must become something like: <teiHeader> <fileDesc> <sourceDesc> <msDesc> <msIdentifier> <idno/> </msIdentifier> <physDesc> <objectDesc form=""/> </physDesc> </msDesc> </sourceDesc> </fileDesc> </teiHeader> Thanks, Alfredo Il giorno mar 6 lug 2021 alle ore 17:29 Joe Wicentowski <jo...@gm...> ha scritto: > Hi Alfredo, > > It's always fun to see different approaches to the same problem. To add > one more approach to the mix, this uses XQuery 3.0's fold-right() function > (which has been available in eXist since v2.2+) and arrow operator > (available since v3.1.0+): > > "teiHeader/fileDesc/titleStmt/title" > => tokenize("/") > => fold-right((), function($segment, $results) { element { $segment } { > $results } }) > > If you're not familiar with the arrow operator ( > https://www.w3.org/TR/xquery-3/#id-arrow-operator), you can use it to > pipe the results of an expression into a follow-on function as its first > parameter. > > On the final line, we use the fold-right function ( > https://www.w3.org/TR/xpath-functions-31/#func-fold-right) to take the > path segments, from right-to-left, and cumulatively build up the element > structure from innermost to outermost: > > title --> <title/> > titleStmt --> <titleStmt><title/></titleStmt> > fileDesc --> <fileDesc><titleStmt><title/></titleStmt></fileDesc> > teiHeader --> > <teiHeader><fileDesc><titleStmt><title/></titleStmt></fileDesc></teiHeader> > > The result: > > <teiHeader> > <fileDesc> > <titleStmt> > <title/> > </titleStmt> > </fileDesc> > </teiHeader> > > Another use of fold-right and discussion of this function is in my article > on parsing Roman numerals: > https://joewiz.org/2021/05/30/converting-roman-numerals-with-xquery-xslt/. > > Joe > > On Tue, Jul 6, 2021 at 5:26 AM Alfredo Cosco <alf...@gm...> > wrote: > >> Hi all, >> I'm working on eXist 4.7. >> I have a string like this: >> teiHeader/fileDesc/titleStmt/title >> >> Is there a way to transform it and store in a node like: >> <teiHeader> >> <fileDesc> >> <titleStmt> >> <title/> >> <titleStmt> >> </fileDesc> >> </teiHeader> >> >> Thanks, >> Alfredo >> _______________________________________________ >> Exist-open mailing list >> Exi...@li... >> https://lists.sourceforge.net/lists/listinfo/exist-open >> > |