我想知道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返回三个元素
<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)仅返回具有有效ID的两个元素
<foo xml:id="f1">foo 1</foo>
<foo xml:id="f4">foo 4</foo>
XmlPrime拒绝查询,
XQDY0091:构造的xml:id属性可能没有值'2'。它 必须为NCName。
这似乎是https://www.w3.org/TR/xquery-31/#ERRXQDY0091中的一个选项。
对于id
函数本身,似乎在https://www.w3.org/TR/xpath-functions/#func-id中明确指出:“如果任何标记不是词法上有效的IDREF(即,如果不是词法上的xs,则为: NCName),它将被忽略”,因此基于Saxon所做的正确操作,而BaseX应该忽略2
函数的参数序列中的if
参数。
结论正确吗?
答案 0 :(得分:2)
是的,我认为您对规范的阅读是正确的。不需要处理器在构造属性时就拒绝该属性,但是如果该属性无效,则要求id()函数将其忽略。
XQuery规范实际上在§3.9.1.1中说过:
如果属性名称为xml:id,则按照[XML ID]中的定义执行xml:id处理。这样可以确保属性的类型为xs:ID,并且其值已正确规范化。如果在xml:id处理期间遇到错误,则实现可能会引发动态错误[err:XQDY0091]。
如果属性名称为xml:id,则结果属性节点的is-id属性设置为true;否则,属性设置为true。否则,is-id属性设置为false。属性节点的is-idrefs属性无条件地设置为false。
可以说这有点不完整:它说“执行了xml:id处理”;它没有说如果xml:id处理失败并且实现选择不引发动态错误,处理器应该怎么做。它还建议即使是非验证处理器也应将属性键入为xs:ID,但这是没有意义的,因为在整个规范中有很多语句表明,使用非验证处理器,所有节点都将是无类型的。 / p>
只要规范允许,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属性的值;这就是撒克逊人处理它的方式。