id 函数和无效 xml:id 属性的不同结果
Different results with id function and invalid xml:id attribute
我想知道 XQuery 实现应该如何正确处理 id
函数和具有 xml:id
属性的元素无效,例如<foo xml:id="2">foo 2</foo>
.
像
这样的简单测试用例
document {<root>
<foo xml:id="f1">foo 1</foo>
<foo xml:id="2">foo 2</foo>
<foo xml:id="f3">foo 3</foo>
<foo xml:id="f4">foo 4</foo>
</root>}/id(('f1', '2', 'f4'))
给我不同的结果,BaseX returns 三个元素
<foo xml:id="f1">foo 1</foo>
<foo xml:id="2">foo 2</foo>
<foo xml:id="f4">foo 4</foo>
所以它并不关心 2
不是一个有效的 ID 值。
Saxon (9.9 HE Java) returns 只有两个具有有效 ID 的元素
<foo xml:id="f1">foo 1</foo>
<foo xml:id="f4">foo 4</foo>
XmlPrime 拒绝
的查询
XQDY0091: A constructed xml:id attribute may not have value '2'. It
must be an NCName.
这似乎是 https://www.w3.org/TR/xquery-31/#ERRXQDY0091 中允许的选项。
至于 id
函数本身,它似乎在 https://www.w3.org/TR/xpath-functions/#func-id 中阐明 "If any of the tokens is not a lexically valid IDREF (that is, if it is not lexically an xs:NCName), it is ignored" 所以基于 Saxon 是正确的,而 BaseX 应该忽略 2
参数序列中的参数到 if
函数。
这是正确的结论吗?
是的,我认为您对规范的阅读是正确的。处理器不需要在构造时拒绝该属性,但如果它无效,则要求 id() 函数忽略它。
XQuery 规范实际上在 §3.9.1.1 中说:
如果属性名称是xml:id,则xml:id处理按照[XML ID]中的定义执行。这可确保该属性具有 xs:ID 类型并且其值已正确规范化。如果在 xml:id 处理期间遇到错误,实现可能会引发动态错误 [err:XQDY0091].
如果属性名称为xml:id,则结果属性节点的is-id属性设置为true;否则 is-id 属性 设置为 false。属性节点的is-idrefs属性无条件设置为false
可以说这有点不完整:它说 xml:id 处理 "is performed";如果 xml:id 处理失败并且实现选择不引发动态错误,它没有说明处理器应该做什么。它还建议即使 non-validating 处理器也应将该属性键入为 xs:ID,但这没有任何意义,因为整个规范中有很多语句使用 non-validating 处理器,所有节点将被取消类型化。
只要规范允许,Saxon 就会尽可能以相同的方式为 XQuery 和 XSLT 做事。因此,总是值得看看这两种规格的说法。 XSLT 是这样说的:
如果构造属性的名称是 xml:id,处理器必须通过有效地将 normalize-space 函数应用于属性值来执行属性值规范化,并且结果属性节点必须被赋予 is-id 属性。无论属性是使用 xsl:attribute 指令构造的还是使用文字结果元素的属性构造的,这都适用。这并不意味着对属性的值或其唯一性有任何限制,并且它不会影响属性的类型注释,除非包含的文档经过验证。
注:
设置is-id属性的效果是可以使用idFO30函数在包含的文档中定位父元素。实际上,XSLT 在构建文档时执行 [xml:id 处理器的某些功能,如 [xml:id] 中所定义; xml:id 处理的其他方面在验证期间执行。
因此 XSLT 选择不验证 xml:id 属性的值,除非在构造的树上执行模式验证;这就是撒克逊人处理它的方式。
我想知道 XQuery 实现应该如何正确处理 id
函数和具有 xml:id
属性的元素无效,例如<foo xml:id="2">foo 2</foo>
.
像
这样的简单测试用例document {<root>
<foo xml:id="f1">foo 1</foo>
<foo xml:id="2">foo 2</foo>
<foo xml:id="f3">foo 3</foo>
<foo xml:id="f4">foo 4</foo>
</root>}/id(('f1', '2', 'f4'))
给我不同的结果,BaseX returns 三个元素
<foo xml:id="f1">foo 1</foo>
<foo xml:id="2">foo 2</foo>
<foo xml:id="f4">foo 4</foo>
所以它并不关心 2
不是一个有效的 ID 值。
Saxon (9.9 HE Java) returns 只有两个具有有效 ID 的元素
<foo xml:id="f1">foo 1</foo>
<foo xml:id="f4">foo 4</foo>
XmlPrime 拒绝
的查询XQDY0091: A constructed xml:id attribute may not have value '2'. It must be an NCName.
这似乎是 https://www.w3.org/TR/xquery-31/#ERRXQDY0091 中允许的选项。
至于 id
函数本身,它似乎在 https://www.w3.org/TR/xpath-functions/#func-id 中阐明 "If any of the tokens is not a lexically valid IDREF (that is, if it is not lexically an xs:NCName), it is ignored" 所以基于 Saxon 是正确的,而 BaseX 应该忽略 2
参数序列中的参数到 if
函数。
这是正确的结论吗?
是的,我认为您对规范的阅读是正确的。处理器不需要在构造时拒绝该属性,但如果它无效,则要求 id() 函数忽略它。
XQuery 规范实际上在 §3.9.1.1 中说:
如果属性名称是xml:id,则xml:id处理按照[XML ID]中的定义执行。这可确保该属性具有 xs:ID 类型并且其值已正确规范化。如果在 xml:id 处理期间遇到错误,实现可能会引发动态错误 [err:XQDY0091].
如果属性名称为xml:id,则结果属性节点的is-id属性设置为true;否则 is-id 属性 设置为 false。属性节点的is-idrefs属性无条件设置为false
可以说这有点不完整:它说 xml:id 处理 "is performed";如果 xml:id 处理失败并且实现选择不引发动态错误,它没有说明处理器应该做什么。它还建议即使 non-validating 处理器也应将该属性键入为 xs:ID,但这没有任何意义,因为整个规范中有很多语句使用 non-validating 处理器,所有节点将被取消类型化。
只要规范允许,Saxon 就会尽可能以相同的方式为 XQuery 和 XSLT 做事。因此,总是值得看看这两种规格的说法。 XSLT 是这样说的:
如果构造属性的名称是 xml:id,处理器必须通过有效地将 normalize-space 函数应用于属性值来执行属性值规范化,并且结果属性节点必须被赋予 is-id 属性。无论属性是使用 xsl:attribute 指令构造的还是使用文字结果元素的属性构造的,这都适用。这并不意味着对属性的值或其唯一性有任何限制,并且它不会影响属性的类型注释,除非包含的文档经过验证。
注:
设置is-id属性的效果是可以使用idFO30函数在包含的文档中定位父元素。实际上,XSLT 在构建文档时执行 [xml:id 处理器的某些功能,如 [xml:id] 中所定义; xml:id 处理的其他方面在验证期间执行。
因此 XSLT 选择不验证 xml:id 属性的值,除非在构造的树上执行模式验证;这就是撒克逊人处理它的方式。