Marklogic DB中的节点更新

时间:2012-08-01 19:28:26

标签: xml marklogic

我在ML DB中使用doc uri(/employee/*.xml)保存了多个员工xml文档,我想从新XML获取更新,其中唯一引用键是roleID(在ML XML中,其roleID和新XML)它是newroleID)。每当找到匹配时,它应该使用新的XMl的newFirstName更新ML xml的firstName值,使用newlastName更新lastname值,使用new dep更新dep,并且xml结构的其余部分保持相同。

Marklogic XML结构如下:

    doc uri /employee/1.xml
    <employee>
        <firstName>Jim</firstName>
        <lastName>Day</lastName>
        <dep>IT</dep>
        <city>Boston</city>
        <roleID>1111<roleID>
        <internalID>2222</internalID>
    </employee>

    doc uri /employee/2.xml
    <employee>
        <firstName>Jan</firstName>
        <lastName>Silly</lastName>
        <dep>Finance</dep>
        <city>DC</city>
        <roleID>3333<roleID>
        <internalID>4444</internalID>
    </employee>

    doc uri /employee/3.xml
    <employee>
        <firstName>Jack</firstName>
        <lastName>John</lastName>
        <dep>HR</dep>
        <city>Virginia</city>
        <roleID>5555<roleID>
        <internalID>6666</internalID>
    </employee>

我正在尝试这个但不确定如何更新文档,它也似乎是优化的xquery,请帮助。

    let $newXML := <employees>
                        <newemployee>
                            <NewfirstName>New Fname1</newfirstName>
                            <newlastName>New Lname1</newlastName>
                            <newdep>New Dep1</newdep>
                            <newcity>Boston</newcity>
                            <newroleID>1111<newroleID>
                            <internalID>2222</internalID>
                        </newemployee>
                        <newemployee>
                            <newfirstName>New Fname2</newfirstName>
                            <newlastName>New Lname</newlastName>
                            <newdep>New Dep</newdep>
                            <newcity>Boston</newcity>
                            <newroleID>5555<newroleID>
                            <newinternalID>6666</newinternalID>
                        </employee>
                    </employees>
    for $oldXML in doc("/employee/*.xml")/employee
        where $newXML/newemployee/newroleID eq $oldXML/roleID
        return
          for $Matched in $oldXML
            return
            let $finalXML := 
                (: Not sure how to update some nodes in given URI, where rest of structure remain same :)

                <employee>
                    <firstName>{$newXML/newemployee/newfirstName/text()}</firstName>
                    <lastName>{$newXML/newemployee/newlastName/text()}</lastName>
                    <dep>{$newXML/newemployee/newdep/text()}</dep>              
                </employee>

2 个答案:

答案 0 :(得分:3)

请参阅xdmp:node-replace

来自文档示例:

(: insert the doc :)
xdmp:document-insert("/example.xml", <a><b>bbb</b></a>);
(: replace the b node in the doc with this c node :)
xdmp:node-replace(doc("/example.xml")/a/b, <c>ccc</c>);
doc("/example.xml") => <a><c>ccc</c></a>

答案 1 :(得分:1)

表达式doc("/employee/*.xml")不起作用。如果创建目录(自动或手动),则使用xdmp:directory。或者,您可以使用cts:uri-match为员工查找uris,如果启用了URI词典,则可以将这些内容传递给doc()

但是......你方法中最大的瓶颈就是遍历所有文件。这不是必要的。如果roleID是唯一的,那么将其用于uri,这样您就不需要遍历所有文档,只需立即打开正确的文档即可。或者,使用可由XQuery处理器优化的表达式,或者仅依赖于索引。如下所示:

doc()[//roleID = $newRoleID]

或者:

cts:search(doc(), cts:element-value-query(xs:QName("roleID"), $newRoleID))

对于更新本身,您可以使用xdmp:node-replace和@sgarrett建议的相关,但您也可以简单地重新创建整个XML,并使用xdmp:document-insert完全替换它。无论如何,文件完全替换在场景后面,所以你几乎不会注意到这些小文件的任何差异。

HTH!