2012-06-07 46 views
2

使用MarkLogic从网络服务中提取xdmp:http-get()xdmp:http-post()的数据,我希望能够检查返回的标题,然后再尝试处理数据。在DQ我可以这样做:访问来自xdmp的HTTP响应:http-get()

let $result := xdmp:http-get($query,$options) (: $query and $options are fine, I promise. :) 
return $result 

而结果我回来是这样的:

<v:results v:warning="more than one node"> 
     <response> 
      <code>200</code> 
      <message>OK</message> 
      <headers> 
       <server>(actual server data was here)</server> 
       <date>Thu, 07 Jun 2012 16:53:24 GMT</date> 
       <content-type>application/xml;charset=UTF-8</content-type> 
       <content-length>2296</content-length> 
       <connection>close</connection> 
      </headers> 
     </response> 

之后的实际响应。问题是我似乎无法将XPath引入此响应节点。如果我将我的退货声明更改为return $result/response/code,我会得到空序列。如果我可以检查该代码以确保在尝试处理返回的实际数据之前返回200,那么它将比使用try-catch块来查看数据是否存在并且是否理智更好。

因此,如果有人知道如何访问这些响应代码,我很乐意看到您的解决方案。

为了记录,我试过xdmp:get-response-code(),但它不需要任何参数,所以我不知道它在查看什么响应代码。

回答

7

你得到两个陷阱一次烧:

  • 命名空间的意识
  • 文档节点的意识

首先,命名空间。在HTTP-GET功能的XML输出是一个命名空间由顶级元素所见:

<response xmlns="xdmp:http-get"> 

成功访问的元素在命名空间中,你需要声明绑定到正确的查询前缀名称空间,然后在XPath表达式中使用该前缀。例如:

declare namespace h="xdmp:http-get"; 
//h:code 

现在我们来谈谈文档节点。 :-)

您试图访问$result就好像它是一个包含元素的文档节点,但实际上它是由两个根节点组成的序列(因此它们不是兄弟)。第一个(你在这里感兴趣的)是一个无父母的<response>元素 - 而不是一个包含<response>元素的文档。

这是一个常见的问题:知道文档节点是否存在。文档节点在序列化时始终是不可见的(因此存在),并且它们始终存在于存储在数据库中的文档中。但是,当您仅在XQuery中使用裸元素构造函数(如http-get实现那样)时,不会构建文档节点,而会构造没有文档节点父元素的元素节点。

例如,下面的查询将返回空序列,因为它试图让<foo>孩子的<foo>

declare variable $foo := <foo>bar</foo>; 
$foo/foo 

在另一方面,下面的确实返回<foo>,因为它是越来越所述<foo>子文档节点(其必须被显式构造,在XQuery中):

$declare variable $doc := document{ <foo>bar</foo> }; 
$doc/foo 

所以你必须知道给定函数的API是如何设计的(不管它是返回一个包含一个元素还是一个元素的文档)。

要解决您的问题,请不要尝试访问$result/h:response/h:code(它试图获得<response>的子<response>)。相反,访问$result/h:code(或更准确地说$result[1]/h:code,因为<response>是由http-get函数返回的两个节点序列中的第一个)。

有关文件节点的详细信息,请查看本博客系列文章:http://community.marklogic.com/blog/document-formats-part1

+3

在命名空间,我有时会欺骗(尤其是当有没有真正的性能问题与短暂的XML一样未存储在''数据库),而不是声明一个名称空间,只需使用一个名称空间通配符:'$ result/*:code' –