Xquery MarkLogic 8 mem:节点替换

Xquery MarkLogic 8 mem:节点替换,xquery,marklogic,Xquery,Marklogic,我的数据包含一些我需要保密的ID。我想使用带有私钥的哈希函数,这很好。但是,当我尝试替换内存中的节点时,我无法使其工作 问题是: 我将$value放在mem:node replace中,但它不是一个节点,我尝试了xdmp:unquote和其他函数,但没有帮助 在本例中,我显示了$value,这是一个很好的“路径”,现在如何将其连接到节点 $doc/*:source/*:content/cdm:BerichtInhoud/cdm:bericht[1]/cdm:id/text() 完整示例: xq

我的数据包含一些我需要保密的ID。我想使用带有私钥的哈希函数,这很好。但是,当我尝试替换内存中的节点时,我无法使其工作

问题是: 我将$value放在
mem:node replace
中,但它不是一个节点,我尝试了xdmp:unquote和其他函数,但没有帮助

在本例中,我显示了$value,这是一个很好的“路径”,现在如何将其连接到节点

$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
xquery版本“1.0-ml”;
声明命名空间html=”http://www.w3.org/1999/xhtml";
导入模块名称空间mem=”http://xqdev.com/in-mem-update“在mem update.xqy中的'/MarkLogic/appservices/utils/at';
声明命名空间cdm=”http://schemas.dikw.nl/cdm/1.2";
let$key:=“secretkey”
让$doc:=
5ac03a41-004a-459b-84b1-4efa8f193847
dikw源数据
提斯
12345
皮特
65756
基斯
87232
对于$doc//cdm:id中的$singleid
让$idstring:=$singleid/text()
让$sterk:=子字符串(
xdmp:hmac-sha512($key,$idstring,'base64'),
1,字符串长度($idstring))
让$fullpath:=xdmp:path($idstring)
let$values:=fn:concat(fn:string(“$doc”),$fullpath)
让$nodev:=$values
让$newdoc:=mem:node替换($idstring,{$sterk})
返回$value

编辑 在Dave的博客上阅读和测试之后,我想到了这个。不幸的是,它没有像我预期的那样工作。代码不会在需要的地方更改元素

问题在于将数据提供给local:change()函数的格式。这是一份文件,这就是它失败的原因。 我认为在我的项目的原始代码中,类型也是一个文档,但我不能确定,因为xdmp:descripe和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})
xquery版本“1.0-ml”;
导入模块名称空间mem=”http://xqdev.com/in-mem-update“在mem update.xqy中的'/MarkLogic/appservices/utils/at';
导入模块命名空间functx=”http://www.functx.com“at”/MarkLogic/functx/functx-1.0-nodoc-2007-01.xqy”;
声明命名空间cdm=”http://schemas.dikw.nl/cdm/1.2";
声明函数本地:hashid($id){
let$\ux:=xdmp:log($id)
let$key:=“secretkey”
让$idstring:=$id/text()
让$sterk:=子字符串(
xdmp:hmac-sha512($key,$idstring,'base64'),
1,字符串长度($idstring))
返回$sterk
};
声明函数本地:更改($node)
{
类型开关($node)
(:id上的大小写:)
案例元素(cdm:id)返回
元素cdm:id{
本地:hashid($node)
}
(:默认情况,返回未更改:)
case元素()返回
元素{fn:node name($node)}{
$node/@*,
$node/node()!本地:更改(.)
}
默认返回$node
};
声明变量$doc:=
5ac03a41-004a-459b-84b1-4efa8f193847
dikw源数据
提斯
12345
皮特
65756
基斯
87232
;
返回本地:更改(文档{$doc})

我将您的FLWOR语句更改为返回$newdoc,并发现您的ID没有按您希望的方式被替换

<cdm:bericht>
  <cdm:name>Thijs</cdm:name>
  <cdm:id>
    <cdm:id>+CMs5</cdm:id>
  </cdm:id>
</cdm:bericht>

现在$idstring是整个cdm:id元素(可能应该重命名)。当您将其传递到xdmp:hmac-sha512()和fn:string-length()中时,它将被转换为字符串,您将得到预期的结果。如果您返回$newdoc,您的ID将按照您想要的方式显示:

<cdm:bericht>
  <cdm:name>Thijs</cdm:name>
  <cdm:id>+CMs5</cdm:id>
</cdm:bericht>

提斯
+CMs5

另一个注意事项:由于您有多个要替换的东西,因此您可能应该使用以下方法来解决此问题。那样的话,你只需要复制一份文件

这是我在Geert的帮助下最终提出的函数。棘手的部分是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
};

谢谢如您所述,我更改了$idstring。我的问题实际上更多的是关于递归下降:)我来看看你的链接!我使用了你博客中的一些智慧,在上面的编辑中。结果仍然不是我想要的,但至少现在它只是另一个“类型”问题。
<cdm:bericht>
  <cdm:name>Thijs</cdm:name>
  <cdm:id>+CMs5</cdm:id>
</cdm:bericht>
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
};