1
votes

I have a document in Marklogic database and would like to retain product node where rating code is either "Agree" or "Strongly Agree" using XQuery, other nodes need to be removed.

I have tried few options to find node with appropriate attribute and delete others but no luck something like

let $rating5Exists := fn:exists($doc//rating[@code eq "Strongly Agree"])

let $rating4Exists := fn:exists($doc//rating[@code eq "Agree"])

<products>
    <product>
        <product-id>9039034</product-id>
        <status>
            <rating code="Strongly Agree">
                <count>5</count>
            </rating>
        </status>
    </product>
    <product>
        <product-id>9039034</product-id>
        <status>
            <rating code="Agree">
                <count>4</count>
            </rating>
        </status>
    </product>
    <product>
        <product-id>9039034</product-id>
        <status>
            <rating code="Neither Agree nor Disagree">
                <count>3</count>
            </rating>
        </status>
    </product>
    <product>
        <product-id>9039034</product-id>
        <status>
            <rating code="Disagree">
                <count>2</count>
            </rating>
        </status>
    </product>
    <product>
        <product-id>9039034</product-id>
        <status>
            <rating code="Strongly Disagree">
                <count>1</count>
            </rating>
        </status>
    </product>
</products>

Expected output:

<products>
    <product>
        <product-id>9039034</product-id>
        <status>
            <rating code="Strongly Agree">
                <count>5</count>
            </rating>
        </status>
    </product>
    <product>
        <product-id>9039034</product-id>
        <status>
            <rating code="Agree">
                <count>4</count>
            </rating>
        </status>
    </product>
</products>
2

2 Answers

0
votes

Answer in this post help me, I knew that there is always someone out there had same question :)

How to delete an XML element according to value of one of its children?

0
votes

There are several ways of doing this inside MarkLogic. In generic terms it comes down to either manipulating the document in-site, using node update statements, or rewriting the document in its entirety. Performance can be good with either method.

A node-update approach (in XQuery) could look like:

for $product in
    $doc/products/product
let $rating :=
    $product/status/rating
where
    not($rating/@code = ('Agree', 'Strongly Agree'))
return
    xdmp:node-delete($product)

A document rewrite approach (in XQuery) could look like:

let $newDoc := element { node-name($doc/*) } {
    $doc/*/namespace::*,
    $doc/*/@*,
    $doc/*/product[status/rating/@code = ('Agree', 'Strongly Agree')]
}
return
    (: using node-replace here to preserve doc permissions, collections, etc :)
    xdmp:node-replace($doc, $newDoc)

HTH!