XQuery 中的 element() 与 node()

2024-03-18

有人可以告诉我两者之间的确切区别吗node() and element()XQuery 中的类型?该文档指出element()是一个元素节点,而node()是任何节点,所以如果我理解正确的话element()是一个子集node().

问题是我有一个像这样的 XQuery 函数:

declare function local:myFunction($arg1 as element()) as element() {
    let $value := data($arg1/subelement)
   etc...
};

现在我想使用另一个函数获得的参数来调用该函数,例如functionX(我无法控制):

let $parameter := someNamespace:functionX()
return local:myFunction($parameter)

问题是,functionX返回一个node()所以它不会让我通过$parameter直接地。我尝试更改函数的类型以获取node()而不是element(),但我似乎无法从中读取任何数据。$value只是空的。

有没有某种方法可以将节点转换为元素,还是我应该遗漏一些东西?

EDIT:据我所知,问题出在我尝试使用获取子元素的部分$arg1/subelement。显然你可以这样做,如果$arg1 is an element()但如果它是node().

UPDATE:我已经测试了下面 Dimitre 提供的示例,它确实工作得很好,无论是使用 Saxon 还是使用 eXist DB(这是我用作 XQuery 引擎的)。问题实际上发生在request:get-data()来自 eXist DB 的函数。通过 REST 使用 eXist 时,此函数获取 POST 请求提供的数据,将其解析为 XML 并将其返回为node()。但由于某种原因,当我将数据传递给另一个函数时,XQuery 不承认它是有效的element(),尽管如此。如果我手动提取它(即复制输出并将其粘贴到我的源代码中),将其分配给一个变量并将其传递给我的函数,一切都会顺利。但是如果我直接传递它,它会给我一个运行时错误(并且确实失败了instance of test).

我需要能够使其忽略此类型检查或将数据“类型转换”为element().


data()仅仅因为参数类型是,就返回空元素node()对我来说听起来像是一个错误。您使用什么 XQuery 处理器?

听起来您需要安抚静态类型检查,您可以使用treat as表达。我不相信使用动态测试instance of就足够了。

尝试这个:

let $parameter := someNamespace:functionX() treat as element()
return local:myFunction($parameter)

引用迈克尔·凯的巨著第四版,“treat as运算符本质上是告诉系统您知道运行时类型是什么,并且您希望将任何检查推迟到运行时,因为您确信您的代码是正确的。”(第 679 页)

UPDATE:我认为上面的说法实际上是错误的,因为treat as只是一个断言。它不会更改类型注释node(),这意味着这也是一个错误的断言,对您没有帮助。嗯...我真正想要的是cast as,但这仅适用于原子类型。我想我被难住了。也许您应该更改 XQuery 引擎。 :-) 如果我想到其他事情,我会报告。另外,我很想知道 Dimitre 的解决方案是否适合您。

更新#2:我早些时候在这里退缩了。我还能再退一步吗? ;-) 现在我的理论是treat as will工作基于以下事实node()被解释为各种特定节点类型注释的联合,而不是作为运行时类型注释本身(请参阅XQuery 形式语义的“项目类型”部分 http://www.w3.org/TR/xquery-semantics/#sec_item_types.) 在运行时,类型注释将是element(). Use treat as向类型检查器保证这是真的。现在我屏息以待:这对你有用吗?

解释性附录:假设这有效,原因如下。node()是联合类型。运行时的实际项目永远不会被注释为node()。 “项目类型可以是原子类型、元素类型、属性类型、文档节点类型、文本节点类型、注释节点类型或处理指令类型。”1 http://www.w3.org/TR/xquery-semantics/#sec_item_types请注意node()不在该列表中。因此,您的 XQuery 引擎不会抱怨某项具有类型node();相反,它抱怨它没有know类型将会是什么(node()意味着它最终可能会成为attribute(), element(), text(), comment(), processing-instruction(), or document-node())。为什么它必须知道?因为你在其他地方告诉它它是一个元素(在你的函数的签名中)。仅将其范围缩小到上述六种可能性之一是不够的。静态类型检查意味着您必须在编译时保证类型匹配(在本例中是元素与元素)。treat as用于从通用类型中缩小静态类型的范围(node())到更具体的类型(element())。它不会改变动态类型。cast as另一方面,用于将项目从一种类型转换为另一种类型,同时更改静态和动态类型(例如,xs:string 到 xs:boolean)。这是有道理的cast as只能与原子值(而不是节点)一起使用,因为将属性转换为元素(等)意味着什么?并且不存在转换这样的事情node()项目到element()项目,因为没有这样的东西node() item. node()仅作为静态联合类型存在。故事的道德启示?避免使用静态类型检查的 XQuery 处理器。 (很抱歉得出了尖刻的结论;我觉得我已经赢得了权利。:-))

基于更新信息的新答案:听起来静态类型检查是一个转移注意力的话题(一条大鱼)。我相信你事实上not处理一个元素但是一个文档节点,它是不可见的根节点,包含格式良好的 XML 文档的 XPath 数据模型表示中的顶级元素(文档元素)。

因此,树的模型如下:

      [document-node]
             |
        <docElement>
             |
        <subelement>

and not像这样:

        <docElement>
             |
        <subelement>

我原以为你会通过<docElement>节点。但如果我是对的,您实际上正在传递文档节点(其父节点)。由于文档节点是不可见的,因此它的序列化(您复制和粘贴的内容)与元素节点无法区分,并且当您在 XQuery 中粘贴现在被解释为裸元素构造函数的内容时,区别就消失了。 (要在 XQuery 中构造文档节点,您必须将元素构造函数包装为document{ ... }.)

The instance of测试失败,因为节点not一个元素,但一个文档节点。 (这不是一个node()就其本身而言,因为不存在这样的事情;参见上面的解释。)

另外,这可以解释为什么data()当您尝试获取时返回空<subelement>文档节点的子节点(将函数参数类型放宽为node())。上面的第一个树表示表明<subelement> is not文档节点的子节点;因此它返回空序列。

现在来说说解决方案。在传递(文档节点)参数之前,通过附加来获取其子元素(文档元素)/* (or /element()这是等效的)像这样:

let $parameter := someNamespace:functionX()/*
return local:myFunction($parameter)

或者,让您的函数采用文档节点并更新传递给 data() 的参数:

declare function local:myFunction($arg1 as document-node()) as element() {
    let $value := data($arg1/*/subelement)
   etc...
};

最后,它看起来像eXist请求说明:get-data()函数 http://demo.exist-db.org/exist/functions/request/get-data与这个解释完全一致。它说:“如果它不是二进制文档,我们会尝试将其解析为 XML并返回一个文档节点().”(强调)

感谢您的冒险。事实证明,这是一个常见的 XPath 陷阱(文档节点意识),但我从静态类型检查的绕行中学到了一些东西。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

XQuery 中的 element() 与 node() 的相关文章

随机推荐

  • 我想做的是 FreezableCollection.AddRange(collectionToAdd)

    我想做的是FreezableCollection AddRange collectionToAdd 每次我添加到 FreezableCollection 时 都会引发一个事件并发生一些事情 现在我有一个新的收藏 我想添加 但这次我想要集合更
  • R - 改变列表结构

    我有一些文本数据 在读入 R 后以以下格式呈现 gt lst lt list A c aa bb cc B c aa bb cc dd 1 1 A 2 1 aa 3 1 bb 4 1 cc 5 1 B 6 1 aa 7 1 bb 8 1 c
  • 更新到 Spring Boot 2.2.1 后出现 NoSuchBeanDefinitionException

    将现有代码从 Spring Boot 2 2 0 升级到 2 2 1 后 我遇到了一个奇怪的问题 看来我的 spring data jdbc 存储库不再以某种方式被扫描 Caused by org springframework beans
  • 我可以使用协议相关的 标签吗?

    协议相关 URL http www paulirish com 2010 the protocol relative url 可以方便地包含使用与原始请求相同的架构 HTTP 或 HTTPS 的资源 图像 CSS JS 同时仅保留缓存页面的
  • 鼠标在图像上单击的位置

    我有一个 GWT 容器 里面有一些东西和一个添加了点击处理程序的图像 我尝试做的是获取相对于图像的确切鼠标事件 X 和 Y 坐标 我看到帖子了here https stackoverflow com questions 1726137 tr
  • 跨编译单元的 OCaml 递归模块

    我试图将以下递归模块拆分为单独的编译单元 具体来说 我希望 B 位于它自己的 b ml 中 以便能够与其他 A 一起重用它 module type AT sig type b type t Foo of b Bar val f t gt b
  • PL/SQL:从表中选择到关联数组中

    我正在尝试在一个查询中将数据选择到 pl sql 关联数组中 我知道我可以使用硬编码密钥来做到这一点 但我想看看是否有某种方法可以引用另一列 密钥列 DECLARE TYPE VarAssoc IS TABLE OF varchar2 2
  • 在拉斐尔·JS

    我需要做类似的事情 paper text Left Top this p Label paper text Left Top nbsp this p Label 但前置空格不会显示或显示为 nbsp 在文本中 我试过了 label attr
  • Laravel 模型工厂播种机将两个模型分配给一个模型

    我正在开发 Laravel 9 项目 需要创建大量测试数据 我有一些模型 我想通过我的模型工厂自动将它们链接起来 这是我的模型关系 User Company 用户可以拥有一家公司 但他们可能没有一家 Affiliate 附属机构拥有user
  • scikit 多标签分类:ValueError:错误的输入形状

    我相信SGDClassifier with loss log 支持多标签分类 我不必使用 OneVsRestClassifier 检查这个 https stackoverflow com questions 15036630 batch g
  • Gui 工具包,我应该使用哪个? [关闭]

    Closed 这个问题是无关 help closed questions 目前不接受答案 我正在编写一个相当大且复杂的数据分析程序 我认为是时候为该程序构建一个 GUI 了 所以我的问题是 我应该使用哪个 GUI 工具包 我对编码和构建 G
  • Phonegap 1.7中的Childbrowser插件只能第一次打开

    Phonegap 1 7 中的 Childbrowser 插件只能在第一次打开 我正在使用 Phonegap 1 7 和 Childbrowser 仅在子浏览器第一次工作时 当我关闭 Childbrowser 按下完成按钮 后 当我尝试打开
  • 如何仅删除父表中由子表中的外键引用的行

    我想从父表中删除行 元组 但它抛出错误消息 因为它的子表中有外键引用 但是 就我而言 我想仅删除父表中的记录并保留子表中的数据 有可能实现这一目标吗 我知道的用法ON DELETE CASCADE https stackoverflow c
  • ExtJS“日期字段”验证覆盖

    我需要一个具有一些自定义行为的日期列 特别是我需要能够在同一字段中输入日期或年龄 年龄保持呈现为年龄 日期保持呈现为日期 例如 输入 23 将使 23 在字段中保留为有效值 或者输入 22 1 88 将使 22 1 88 保留为有效值 所以
  • 在第一行有 rowspan 的情况下,在表格的第一行设置 css 样式

    我有很多表 想要在表的第一行设置 css 样式 前提是第一行有行跨度 table tbody tr td width 110 Name td td width 110 Size td td width 110 Status td tr tr
  • Vega-Lite 中的平行坐标?

    是否可以创建平行坐标维加精简版 https vega github io vega lite 我正在寻找一个简单但功能强大的 JavaScript 绘图库 并且需要支持平行坐标 I have googled https www google
  • 如何使用 PHP 将 RSS XML 提要转换为数组

    我希望标题代表全部 如何使用 PHP 将 RSS XML 提要转换为数组 如何才能做到这一点 例如 我正在使用以下网址 这导致了 XML 模式 我需要使用 PHP 将其转换为数组格式 任何帮助将不胜感激和感激 提前致谢 一步步 How to
  • 如何在没有 web.xml 的情况下将 App Engine 项目更新到 Java 11?

    我有一个应用程序引擎项目 Here https github com KevinWorkman GoogleCloudExamples tree master hello world是一个示例存储库 但它只包含几个文件 pom xml
  • viewWillAppear 子视图

    我有 UIScrollView 与多个 UIVIew 子视图 我想更新每个 UIView 显示在 UIScrollView 的可见部分中时显示的数据 触发的回调是什么 我尝试了 viewWillAppear 但似乎没有被调用 谢谢 你必须自
  • XQuery 中的 element() 与 node()

    有人可以告诉我两者之间的确切区别吗node and element XQuery 中的类型 该文档指出element 是一个元素节点 而node 是任何节点 所以如果我理解正确的话element 是一个子集node 问题是我有一个像这样的