首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >XQuery:如何使用计算的命名空间构造函数设置默认名称空间?

XQuery:如何使用计算的命名空间构造函数设置默认名称空间?
EN

Stack Overflow用户
提问于 2015-08-21 05:31:35
回答 3查看 2K关注 0票数 1

使用直接元素构造函数设置默认命名空间非常简单。例如:

代码语言:javascript
复制
<map xmlns="http://www.w3.org/2013/XSL/json"/>

上面的直接构造函数输出与预期完全相同的元素。但是,如果我试图对计算元素和命名空间构造函数做同样的操作,那么我就倒霉了:

代码语言:javascript
复制
element {"map"} {
  namespace {""} { "http://www.w3.org/2013/XSL/json" }
}

Duplicate namespace declaration: '' 8.2中抛出一个BaseX错误,在Saxon 9.6中抛出一个XTDE0440: Cannot output a namespace node for the default namespace when the element is in no namespace

如果我传递前缀就没问题了。以下内容运作良好:

代码语言:javascript
复制
element {"map"} {
  namespace { "e" } {"http://www.w3.org/2013/XSL/json"}
}

在上述情况下,BaseX和撒克逊人都没有抱怨。但是,我希望将名称空间设置为默认名称空间。

关于计算的命名空间构造函数,XQuery 3.0规范他说

如果构造函数指定了PrefixExpr,则前缀表达式的计算方式如下: 如果结果是空序列或零长度xs:string或xs:untyped原子值,则新的命名空间节点没有名称(这样的命名空间节点表示默认名称空间的绑定)。

规范还提供了“带有空前缀的计算名称空间构造函数”的类似示例:

代码语言:javascript
复制
namespace { "" } {"http://a.example.com" }

那么,为什么错误信息呢?显然,计算的命名空间构造函数试图重新声明已由计算元素构造函数声明的命名空间。另一方面,直接构造函数将直接初始化元素的命名空间以供我选择。但这只是我的猜测。我唯一确定的就是我的困惑。

在任何情况下,是否有一种方法可以通过计算构造函数获得与直接构造函数相同的结果?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2015-08-21 12:51:01

我还没有在saxon或basex中测试过这一点,但是在Marklogic中使用XQuery3,这是可行的:

代码语言:javascript
复制
element {fn:QName("http://www.w3.org/2013/XSL/json", "map")} { }

然而,光靠这一点可能并不能真正做到你想做的事。

在XQuery中,计算构造函数不会继承父元素的默认命名空间;第一部分总是元素的(完全限定的) QName。您可以在那里使用一个字符串,但是它会被强制放入一个QName --如果该字符串没有前缀,那么您将显式地请求一个没有命名空间的元素(除非您已经声明了一个默认的元素命名空间,在这种情况下,您就是在请求它)。这意味着,即使在元素上设置默认名称空间,构造函数中没有为其指定默认名称空间的任何子元素也将显式地将其设置为"“。

到目前为止,使用计算构造函数的最简单方法是在文件顶部声明名称空间,然后对每个元素名称使用前缀。这确实导致XML在每个元素上都有前缀。就我个人而言,我喜欢这显然是明确的,但很多人觉得它过于冗长,特别是在只使用一个名称空间的XML中。

您还可以对每个元素使用我上面使用的构造,这将或多或少地完成相同的任务,但不需要使用前缀。如果要这样做,而必须在代码中构造的每个元素上指定名称空间,则生成的XML应该只在顶层元素上指定名称空间,其子元素继承它就像您所期望的那样(尽管这可能取决于您的XQuery处理器)。

或者,您可以声明默认的元素命名空间,然后只为与此不同的元素指定名称空间。但就我个人而言,我觉得这是令人困惑的,而且很难发现错误。

票数 2
EN

Stack Overflow用户

发布于 2015-08-21 21:12:41

基本原因是元素的名称(即名称的前缀、本地部分和uri部分)是由元素构造函数本身决定的,而不是由添加到元素中的动态内容决定的。

当你这样做时:

代码语言:javascript
复制
element {"map"} {
  namespace {""} { "http://www.w3.org/2013/XSL/json" }
}

您正在创建一个没有前缀和名称空间的元素,然后为它提供一个名称空间节点,该节点将默认名称空间绑定到“无命名空间”以外的其他内容;您不能同时使用它。动态地向元素的内容添加命名空间将永远不会更改元素名称。

票数 5
EN

Stack Overflow用户

发布于 2016-04-22 17:06:25

我试图添加一个评论,但它不允许我添加新行。

正如威尔·戈林在他的回答中提到的那样,子元素不会继承父元素的默认命名空间。使这更容易的一种方法是声明名称空间并在子元素中使用它。

代码语言:javascript
复制
declare namespace json = "http://www.w3.org/2013/XSL/json";

element {fn:QName("http://www.w3.org/2013/XSL/json", "map")} {
    element json:child { }
}

变成了

代码语言:javascript
复制
<map xmlns="http://www.w3.org/2013/XSL/json"><child/></map>

其子空间具有相同的默认命名空间。

相当于:

代码语言:javascript
复制
element {fn:QName("http://www.w3.org/2013/XSL/json", "map")} {
    element {fn:QName("http://www.w3.org/2013/XSL/json", "child")} { }
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/32132978

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档