我有以下代码:
let $pl := doc("playlist.xml")//Song
for $s in $pl
where some $c in $s/Comment satisfies contains($s/Comment, "LP")
return $c/Album
当我尝试运行它时,它输出一个错误:
Variable $c has not been declared
,我知道我应该返回$s/Album
。这个错误是由于变量的范围吗?它是如何工作的?
XML文件是:
<PlaylistCollection>
<Playlist name="Piano Jazz" numberOfEntries="2">
<Entries>
<Song filename="israel.mp3" songID="israel"
artist="bevans">
<Title>Israel</Title>
<Album>Explorations</Album>
<Year>1961</Year>
<Comment>From the original LP</Comment>
<Genre>Jazz</Genre>
</Song>
<Song filename="debby.mp3" songID="debby" artist="bevans">
<Title>Waltz For Debby</Title>
<Album>Waltz For Debby</Album>
<Year>1961</Year>
<Genre>Jazz</Genre>
</Song>
</Entries>
</Playlist>
<Artist artistID="bevans" songs="israel debby">
<FirstName>Bill</FirstName>
<LastName>Evans</LastName>
</Artist>
</PlaylistCollection>
在这种情况下,$c
是无用的?
答案 0 :(得分:2)
我通过说出名字替换了所有单个字母变量。单字母变量使得很难理解所有其他人(以及编写代码后两周)的情况,并且在解释代码的文本中引用它们也变得更加复杂。
XQuery表达式some ... in ... satisfies ...
和all ... in ... satisfies ...
被认为以另一种方式工作。在您的情况下,$c
仅绑定在satisfies
子句中。而不是
where some $comment in $song/Comment satisfies contains($song/Comment, "LP")
你可以写
where some $comment in $song/Comment satisfies contains($comment, "LP")
还要重新考虑范围:where
子句中的表达式是子表达式,这意味着其中的变量声明会隐藏flwor表达式的表达式,但之后不再可见对子表达式进行了评估。
此外,绑定in
不应与let
表达式进行比较,但功能更强大,可以执行隐式循环。这对于多首歌曲尤其有用。例如,如果您要做的就是测试是否存在任何包含多条评论的歌曲,您可以
some $song in $songs satisfies count($song/comment) > 1
隐式循环遍历所有$songs
并测试其中一个是否满足条件。
XQuery知道一个名为有效布尔值的概念。除此之外,这可以用于区分空序列和具有内容的序列。换句话说,你可以替换
where some $comment in $song/Comment satisfies contains($comment, "LP")
与
where $song/Comment[contains(., "LP")]
。只要有一条包含LP的注释,序列就不再为空,过滤器表达式的计算结果为true
。
最后,在这种情况下,一个简单的XPath表达式也会这样做。谓词非常强大,通常会使代码更容易阅读。
doc("playlist.xml")//Song[contains(Comment,"LP")]/Album
或者在纯文本中:在playlist.xml
中,查找歌曲并过滤那些包含LP的评论。返回他们的专辑名称。