MarkLogic 8 mem:node-替换
MarkLogic 8 mem:node-replace
我的数据包含一些我需要保密的 ID。我想将散列函数与私钥一起使用,效果很好。但是当我尝试替换内存中的节点时,我无法让它工作。
问题是:
我将 $values 放在 mem:node-replace
中,但它不是节点,尝试了 xdmp:unquote 和其他函数,但它们没有帮助。
在这个示例中,我显示了 $values,这很好 'path',现在如何将其发送到节点?
$doc/*:source/*:content/cdm:BerichtInhoud/cdm:bericht[1]/cdm:id/text()
完整示例:
xquery version "1.0-ml";
declare namespace html = "http://www.w3.org/1999/xhtml";
import module namespace mem = "http://xqdev.com/in-mem-update" at '/MarkLogic/appservices/utils/in-mem-update.xqy';
declare namespace cdm = "http://schemas.dikw.nl/cdm/1.2";
let $key := 'secretkey'
let $doc :=
<source:source
xmlns:source="http://marklogic.com/solutions/obi/source">
<obi:metadata createdBy="admin" createdDateTime="2015-10-16T13:51:30.699172+02:00" lastUpdatedBy="admin" lastUpdatedDateTime="2015-10-16T13:51:30.699172+02:00"
xmlns:obi="http://marklogic.com/solutions/obi">
</obi:metadata>
<source:id>5ac03a41-004a-459b-84b1-4efa8f193847</source:id>
<dcterms:title
xmlns:dcterms="http://purl.org/dc/terms/">dikw source data
</dcterms:title>
<source:content>
<cdm:BerichtInhoud xsi:schemaLocation="http://schemas.dikw.nl/build22.xsd"
xmlns="http://schemas.dikw.nl/export/1.0"
xmlns:export="http://schemas.dikw.nl/exporter/1.0"
xmlns:cdm="http://schemas.dikw.nl/cdm/1.2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<cdm:bericht>
<cdm:name>Thijs</cdm:name>
<cdm:id>12345</cdm:id>
</cdm:bericht>
<cdm:bericht>
<cdm:name>Piet</cdm:name>
<cdm:id>65756</cdm:id>
</cdm:bericht>
<cdm:bericht>
<cdm:name>Kees</cdm:name>
<cdm:id>87232</cdm:id>
</cdm:bericht>
</cdm:BerichtInhoud>
</source:content>
</source:source>
for $singleid in $doc//cdm:id
let $idstring := $singleid/text()
let $sterk := substring(
xdmp:hmac-sha512($key, $idstring, 'base64'),
1, string-length($idstring))
let $fullpath := xdmp:path($idstring)
let $values := fn:concat(fn:string('$doc'), $fullpath)
let $nodev := $values
let $newdoc := mem:node-replace($idstring, <cdm:id>{$sterk}</cdm:id>)
return $values
编辑
在 Dave 的博客上进行了一些阅读和测试之后,这就是我的想法。不幸的是,它没有像我预期的那样工作。代码不会更改需要的元素。
问题在于将数据提供给 local:change() 函数的格式。这是一份文件,这就是它失败的原因。
我认为在我项目的原始代码中,类型也是一个文档,但我不能确定,因为 xdmp:describe 和 xdmp:type 不起作用。
xquery version "1.0-ml";
import module namespace mem = "http://xqdev.com/in-mem-update" at '/MarkLogic/appservices/utils/in-mem-update.xqy';
import module namespace functx = "http://www.functx.com" at "/MarkLogic/functx/functx-1.0-nodoc-2007-01.xqy";
declare namespace cdm = "http://schemas.dikw.nl/cdm/1.2";
declare function local:hashid($id) {
let $_ := xdmp:log($id)
let $key := 'secretkey'
let $idstring := $id/text()
let $sterk := substring(
xdmp:hmac-sha512($key, $idstring, 'base64'),
1, string-length($idstring))
return $sterk
};
declare function local:change($node)
{
typeswitch($node)
(: case on id :)
case element(cdm:id) return
element cdm:id {
local:hashid($node)
}
(: default case, returns unchanged :)
case element() return
element { fn:node-name($node) } {
$node/@*,
$node/node() ! local:change(.)
}
default return $node
};
declare variable $doc :=
<source:source
xmlns:source="http://marklogic.com/solutions/obi/source">
<obi:metadata createdBy="admin" createdDateTime="2015-10-16T13:51:30.699172+02:00" lastUpdatedBy="admin" lastUpdatedDateTime="2015-10-16T13:51:30.699172+02:00"
xmlns:obi="http://marklogic.com/solutions/obi">
</obi:metadata>
<source:id>5ac03a41-004a-459b-84b1-4efa8f193847</source:id>
<dcterms:title
xmlns:dcterms="http://purl.org/dc/terms/">dikw source data
</dcterms:title>
<source:content>
<cdm:BerichtInhoud xsi:schemaLocation="http://schemas.dikw.nl/build22.xsd"
xmlns="http://schemas.dikw.nl/export/1.0"
xmlns:export="http://schemas.dikw.nl/exporter/1.0"
xmlns:cdm="http://schemas.dikw.nl/cdm/1.2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<cdm:bericht>
<cdm:name>Thijs</cdm:name>
<cdm:id>12345</cdm:id>
</cdm:bericht>
<cdm:bericht>
<cdm:name>Piet</cdm:name>
<cdm:id>65756</cdm:id>
</cdm:bericht>
<cdm:bericht>
<cdm:name>Kees</cdm:name>
<cdm:id>87232</cdm:id>
</cdm:bericht>
</cdm:BerichtInhoud>
</source:content>
</source:source>;
return local:change(document {$doc})
我将您的 FLWOR 语句更改为 return $newdoc,发现您的 ID 没有按照您想要的方式进行替换。
<cdm:bericht>
<cdm:name>Thijs</cdm:name>
<cdm:id>
<cdm:id>+CMs5</cdm:id>
</cdm:id>
</cdm:bericht>
发生的事情是 cdm:id 下的文本节点被替换为完整节点。解决方案是传入要替换的完整节点。在这种情况下,您需要做的就是更改:
let $idstring := $singleid/text()
至
let $idstring := $singleid
现在 $idstring 是整个 cdm:id 元素(也许应该重命名)。当您将其传递给 xdmp:hmac-sha512() 和 fn:string-length() 时,它会转换为一个字符串,您会得到您期望的结果。如果您 return $newdoc,您的 ID 将按照您的要求显示:
<cdm:bericht>
<cdm:name>Thijs</cdm:name>
<cdm:id>+CMs5</cdm:id>
</cdm:bericht>
附加说明:由于您有多个要替换的东西,您可能应该使用 recursive descent 来解决这个问题。这样一来,您最终只会制作一份文档副本。
这是我在 theGeert 的帮助下最终想出的函数。棘手的部分是 case document-node() 来解决传入数据是文档的问题。
declare function changeid(
$document
){
for $node in $document
let $data :=
typeswitch($node)
(: case on the right cdm:id :)
case element(cdm:id) return
if ($node/parent::cdm:bericht) then
element cdm:id {
hashid($node)
}
else ()
(: root level node :)
case document-node() return
document { $node/node() ! changeid(.) }
(: default case, returns unchanged :)
case element() return
element { fn:node-name($node) } {
$node/@*,
$node/node() ! changeid(.)
}
default return ($node)
return $data
};
我的数据包含一些我需要保密的 ID。我想将散列函数与私钥一起使用,效果很好。但是当我尝试替换内存中的节点时,我无法让它工作。
问题是:
我将 $values 放在 mem:node-replace
中,但它不是节点,尝试了 xdmp:unquote 和其他函数,但它们没有帮助。
在这个示例中,我显示了 $values,这很好 'path',现在如何将其发送到节点?
$doc/*:source/*:content/cdm:BerichtInhoud/cdm:bericht[1]/cdm:id/text()
完整示例:
xquery version "1.0-ml";
declare namespace html = "http://www.w3.org/1999/xhtml";
import module namespace mem = "http://xqdev.com/in-mem-update" at '/MarkLogic/appservices/utils/in-mem-update.xqy';
declare namespace cdm = "http://schemas.dikw.nl/cdm/1.2";
let $key := 'secretkey'
let $doc :=
<source:source
xmlns:source="http://marklogic.com/solutions/obi/source">
<obi:metadata createdBy="admin" createdDateTime="2015-10-16T13:51:30.699172+02:00" lastUpdatedBy="admin" lastUpdatedDateTime="2015-10-16T13:51:30.699172+02:00"
xmlns:obi="http://marklogic.com/solutions/obi">
</obi:metadata>
<source:id>5ac03a41-004a-459b-84b1-4efa8f193847</source:id>
<dcterms:title
xmlns:dcterms="http://purl.org/dc/terms/">dikw source data
</dcterms:title>
<source:content>
<cdm:BerichtInhoud xsi:schemaLocation="http://schemas.dikw.nl/build22.xsd"
xmlns="http://schemas.dikw.nl/export/1.0"
xmlns:export="http://schemas.dikw.nl/exporter/1.0"
xmlns:cdm="http://schemas.dikw.nl/cdm/1.2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<cdm:bericht>
<cdm:name>Thijs</cdm:name>
<cdm:id>12345</cdm:id>
</cdm:bericht>
<cdm:bericht>
<cdm:name>Piet</cdm:name>
<cdm:id>65756</cdm:id>
</cdm:bericht>
<cdm:bericht>
<cdm:name>Kees</cdm:name>
<cdm:id>87232</cdm:id>
</cdm:bericht>
</cdm:BerichtInhoud>
</source:content>
</source:source>
for $singleid in $doc//cdm:id
let $idstring := $singleid/text()
let $sterk := substring(
xdmp:hmac-sha512($key, $idstring, 'base64'),
1, string-length($idstring))
let $fullpath := xdmp:path($idstring)
let $values := fn:concat(fn:string('$doc'), $fullpath)
let $nodev := $values
let $newdoc := mem:node-replace($idstring, <cdm:id>{$sterk}</cdm:id>)
return $values
编辑
在 Dave 的博客上进行了一些阅读和测试之后,这就是我的想法。不幸的是,它没有像我预期的那样工作。代码不会更改需要的元素。
问题在于将数据提供给 local:change() 函数的格式。这是一份文件,这就是它失败的原因。 我认为在我项目的原始代码中,类型也是一个文档,但我不能确定,因为 xdmp:describe 和 xdmp:type 不起作用。
xquery version "1.0-ml";
import module namespace mem = "http://xqdev.com/in-mem-update" at '/MarkLogic/appservices/utils/in-mem-update.xqy';
import module namespace functx = "http://www.functx.com" at "/MarkLogic/functx/functx-1.0-nodoc-2007-01.xqy";
declare namespace cdm = "http://schemas.dikw.nl/cdm/1.2";
declare function local:hashid($id) {
let $_ := xdmp:log($id)
let $key := 'secretkey'
let $idstring := $id/text()
let $sterk := substring(
xdmp:hmac-sha512($key, $idstring, 'base64'),
1, string-length($idstring))
return $sterk
};
declare function local:change($node)
{
typeswitch($node)
(: case on id :)
case element(cdm:id) return
element cdm:id {
local:hashid($node)
}
(: default case, returns unchanged :)
case element() return
element { fn:node-name($node) } {
$node/@*,
$node/node() ! local:change(.)
}
default return $node
};
declare variable $doc :=
<source:source
xmlns:source="http://marklogic.com/solutions/obi/source">
<obi:metadata createdBy="admin" createdDateTime="2015-10-16T13:51:30.699172+02:00" lastUpdatedBy="admin" lastUpdatedDateTime="2015-10-16T13:51:30.699172+02:00"
xmlns:obi="http://marklogic.com/solutions/obi">
</obi:metadata>
<source:id>5ac03a41-004a-459b-84b1-4efa8f193847</source:id>
<dcterms:title
xmlns:dcterms="http://purl.org/dc/terms/">dikw source data
</dcterms:title>
<source:content>
<cdm:BerichtInhoud xsi:schemaLocation="http://schemas.dikw.nl/build22.xsd"
xmlns="http://schemas.dikw.nl/export/1.0"
xmlns:export="http://schemas.dikw.nl/exporter/1.0"
xmlns:cdm="http://schemas.dikw.nl/cdm/1.2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<cdm:bericht>
<cdm:name>Thijs</cdm:name>
<cdm:id>12345</cdm:id>
</cdm:bericht>
<cdm:bericht>
<cdm:name>Piet</cdm:name>
<cdm:id>65756</cdm:id>
</cdm:bericht>
<cdm:bericht>
<cdm:name>Kees</cdm:name>
<cdm:id>87232</cdm:id>
</cdm:bericht>
</cdm:BerichtInhoud>
</source:content>
</source:source>;
return local:change(document {$doc})
我将您的 FLWOR 语句更改为 return $newdoc,发现您的 ID 没有按照您想要的方式进行替换。
<cdm:bericht>
<cdm:name>Thijs</cdm:name>
<cdm:id>
<cdm:id>+CMs5</cdm:id>
</cdm:id>
</cdm:bericht>
发生的事情是 cdm:id 下的文本节点被替换为完整节点。解决方案是传入要替换的完整节点。在这种情况下,您需要做的就是更改:
let $idstring := $singleid/text()
至
let $idstring := $singleid
现在 $idstring 是整个 cdm:id 元素(也许应该重命名)。当您将其传递给 xdmp:hmac-sha512() 和 fn:string-length() 时,它会转换为一个字符串,您会得到您期望的结果。如果您 return $newdoc,您的 ID 将按照您的要求显示:
<cdm:bericht>
<cdm:name>Thijs</cdm:name>
<cdm:id>+CMs5</cdm:id>
</cdm:bericht>
附加说明:由于您有多个要替换的东西,您可能应该使用 recursive descent 来解决这个问题。这样一来,您最终只会制作一份文档副本。
这是我在 theGeert 的帮助下最终想出的函数。棘手的部分是 case document-node() 来解决传入数据是文档的问题。
declare function changeid(
$document
){
for $node in $document
let $data :=
typeswitch($node)
(: case on the right cdm:id :)
case element(cdm:id) return
if ($node/parent::cdm:bericht) then
element cdm:id {
hashid($node)
}
else ()
(: root level node :)
case document-node() return
document { $node/node() ! changeid(.) }
(: default case, returns unchanged :)
case element() return
element { fn:node-name($node) } {
$node/@*,
$node/node() ! changeid(.)
}
default return ($node)
return $data
};