Search code examples
xquerymarklogic

How to return a existing document except an element using xquery in marklogic


I have a document I have written to ignore the element id from the document and return the document as below but throws error

let $ex := fn:doc("/name/docs")/* except $ex//sar:id return $ex

returns

Error: undefined variable $ex


Solution

  • You are attempting to reference the let variable within the let statement. You can't do that.

    You could let a variable for the document, and then use it in a similar statement:

    let $doc := fn:doc("/name/docs")
    let $ex := $doc/* except $doc//sar:id 
    return $ex
    

    Or you could use a simple mapping operator:

    let $ex := fn:doc("/name/docs") ! (./* except .//sar:id) 
    return $ex
    

    That will return a sequence of child elements from the document (but there is only one immediate child element for a doc, so unless it happens to be sar:id, that likely won't achieve what you are trying to do.

    If you want to return a new document that has all of the content except for the sar:id element, then you could run it through an XSLT that is a modified identity transform with an empty template matching that element to exclude:

    declare variable $XSLT := 
      <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0" xmlns:sar="sar-namespace-needs-to-be-updated-here">
        <!--this generic template matches on, and copies all attributes and nodes by default-->
        <xsl:template match="@*|node()">
            <xsl:copy>
                <xsl:apply-templates select="@*|node()"/>
            </xsl:copy>
        </xsl:template>
        <!--this empty template will ensure that the sar:id is dropped from the output-->
        <xsl:template match="sar:id"/>
    </xsl:stylesheet>;
    
    xdmp:xslt-eval($XSLT, fn:doc("/name/docs"))
    

    Otherwise you could run it through a recursive descent function with a typeswitch. I find XSLT shorter and easier to write, but that's a personal preference.