[xquery-talk] Selecting everything before and after path, but without duplicated leafs

Michael Kay mike at saxonica.com
Mon Feb 11 11:08:31 PST 2008


Sorry, I started writing the function to return elements only and then
changed my mind. The type signature of the function should be "as node()*"
rather than "as element()".

Michael Kay
http://www.saxonica.com/ 

> -----Original Message-----
> From: J. Zhang [mailto:zhangjunte at gmail.com] 
> Sent: 11 February 2008 10:53
> To: Michael Kay
> Cc: talk at x-query.com
> Subject: Re: [xquery-talk] Selecting everything before and 
> after path,but without duplicated leafs
> 
> On Feb 11, 2008 10:07 AM, Michael Kay <mike at saxonica.com> wrote:
> > > > what output would you like to see?
> > >
> > > I would like to preserve the original XML file, but only add an 
> > > extra tag, so I would like to have this output:
> > >
> > > <ead>
> > >  <banana/>
> > >  <archdesc>
> > >    <dsc>
> > >      <c00/>
> > >      <SELECT>
> > >      <c01/>
> > >      </SELECT>
> > >      <c02/>
> > >    </dsc>
> > >  </archdesc>
> > >  <custard/>
> > > </ead>
> >
> > In XSLT this is simply an identity template that copies all elements
> > unchanged:
> >
> > <xsl:template match="*">
> >   <xsl:copy><xsl:apply-templates/></xsl:copy>
> > </xsl:template>
> >
> > (or a variation of that if you need to handle attributes)
> >
> > supplemented by a template for the element you want to change:
> >
> > <xsl:template match="c01">
> >   <SELECT><xsl:next-match/></SELECT>
> > </xsl:template>
> >
> > (You can write a more elaborate match pattern if you need to be more
> > selective.)
> >
> > In XQuery you need to program the recursive descent by hand:
> >
> > declare function local:processNode($e as node()) as element() {
> >   typeswitch ($e) {
> >     case element(c01) return <SELECT>{$e}</SELECT>
> >     case element() return
> >       element {node-name($e)} {for $c in $e/child::node() return 
> > local:processNode($c)}
> >     default return $e
> >   }
> > }
> >
> > local:processNode(doc('abc.xml')/*)
> >
> > plus a bit of extra logic if you need to handle attributes 
> or namespaces.
> >
> 
> Ok, this is what I am using:
> 
> declare function local:processNode($e as node()) as element() 
> {  typeswitch ($e)
>    case element(c01)
>       return <SELECT>{$e}</SELECT>
>    case element()
>       return
>          element {node-name($e)} {
>             for $c in $e/child::node() return
>                local:processNode($c)
>          }
>    default return $e
> };
> 
> local:processNode(doc('ead_10748500.xml')/*)
> 
> ...but I am getting an error when using that function:
> 
>   XPTY0004: Required item type of result of function
> local:processNode() is element();
>   supplied value has item type text()
> Query processing failed: Run-time errors were reported
> 
> The error message is obvious, but probably typecasting won't 
> work here.
> 
> Do you have any ideas?
> 
> jz
> 
> 
> > Michael Kay
> > http://www.saxonica.com/
> >
> >
> >



More information about the talk mailing list