如何在XQuery上声明多个默认命名空间

时间:2015-11-20 01:12:55

标签: xml namespaces xquery xmlbeans

美好的一天!

我一直在寻找可以在XQuery中声明多个默认命名空间吗?

我使用的示例XML有2个默认命名空间:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
....
  <wsMessageHeader xmlns="http://integration.sampleabc.com/common/header/WSMessageHeader/v2">
........
</wsMessageHeader> 

<queryContactGlobalPreferences xmlns="http://integration.sampleabc.com/interfaces/queryContactGlobalPreferences/v1/queryContactGlobalPreferences.xsd">
</queryContactGlobalPreferences >
...
</soapenv:Envelope>

所以我在查询中声明了两个默认命名空间:

declare namespace soapenv='.......'; 
declare default element namespace '......'; 
declare default element namespace '........'; 

结论:当我执行查询时,我总是收到此错误。 如果我删除一个默认命名空间,它在该节点上工作,但我还需要查询另一个节点。它似乎只允许1个默认命名空间。 这个是否有解决方法?

这是错误:

Error on line 1 column 264 
  XPST0003: XQuery syntax error in #...lare default element namespace#:
    Namespace declarations cannot follow variables, functions, or options

2 个答案:

答案 0 :(得分:1)

对于特定的解决方法,您需要提供一个您遇到问题的查询示例,但这是正确的。只能有一个默认元素名称空间。

通常,您会将默认命名空间声明为查询中最常用的命名空间。为其他人分配一个前缀(正如您对soapenv所做的那样),并为该命名空间中的任何元素使用前缀。但是,您可能会为自己节省一些困惑,只需将所有内容都指定为前缀,因此在阅读查询时不会产生歧义。

for $e in $doc//soapenv:Envelope
let $header := $e/headerns:wsMessageHeader
let $prefs := $e/prefsns:queryContactGlobalPreferences
return element stuff {
  $header, $prefs
}

这里的关键概念是命名空间在选择元素时非常重要。您可以为它们分配或不分配前缀,并且您不必使用文档中使用的相同前缀,只要与您声明的前缀相关联的名称空间与您要从中选择的元素相关联的名称空间相同一份文件。

答案 1 :(得分:1)

您只能拥有一个默认元素名称空间。默认命名空间也用于生成的元素,多个默认元素命名空间会导致未定义的行为。选择哪个命名空间?一个元素只能有一个名称空间!

声明命名空间

相反,使用前缀声明名称空间(您可以使用任意名称,只有名称空间URI必须与文档匹配):

declare namespace soapenv = "http://schemas.xmlsoap.org/soap/envelope/";
declare namespace messageHeader = "://integration.sampleabc.com/common/header/WSMessageHeader/v2";
declare namespace preferences = "http://integration.sampleabc.com/interfaces/queryContactGlobalPreferences/v1/queryContactGlobalPreferences.xsd";

并使用前缀对元素进行寻址,例如

//soapenv:Envelope/messageHeader:wsMessageHeader

命名空间通配符

作为即席查询的替代方法,定义命名空间可能看起来像不必要的开销和麻烦,您还可以使用匹配所有命名空间的命名空间通配符运算符*来模拟多个默认元素命名空间。上面的查询将是

//*:Envelope/*:wsMessageHeader

我强烈反对将此用于更持久的生产代码,因为声明命名空间可能会发现问题,否则只是通过未经通知传递,最终使查询更容易阅读和理解,因为您知道元素的来源或种类'目前正在处理。