我遇到了一个看似简单的XQuery练习。在一个XML文件下面。
<Ships>
<Class name = "Kongo" type = "bc" country = "Japan" numGuns = "8"
bore = "14" displacement = "32000">
<Ship name = "Kongo" launched = "1913" />
<Ship name = "Hiei" launched = "1914" />
<Ship name = "Kirishima" launched = "1915">
<Battle outcome = "sunk">Guadalcanal</Battle>
</Ship>
<Ship name = "Haruna" launched = "1915" />
</Class>
</Ships>
我正在尝试将XML转换为带有类名称属性(Kongo)作为标题的XHTML以及子邮件名称和启动年份的枚举列表:
<h1>Kongo</h1>
<table>
<tr><th>Name</th><th>Launched</th><tr>
<tr><td>Kongo</td><td>1913</td></tr>
<tr><td>Hiei</td><td>1914</td></tr>
<tr><td>Kirishima</td><td>1915</td></tr>
<tr><td>Haruna</td><td>1915</td></tr>
<h1>Next Class name</h1>
....
我坚持使用以下嵌套的返回-FLOWR XQuery:
declare option output "method=xml";
declare option output "doctype-public=-//W3C//DTD XHTML 1.0 Strict//EN";
declare option output "doctype-system=http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd";
declare option output "omit-xml-declaration=no";
declare option output "indent=yes";
<html xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>XQ-7</title>
</head>
<body>
{for $class in doc("xml/battleships.xml")/Ships/Class
let $cname := data($class/@name)
let $sname := data($class/Ship/@name)
let $slaunched := data($class/Ship/@launched)
return
<h1>{$cname}</h1>
<table>
{for $ship in doc("xmlbattleships.xml")/Ships/Class/Ship
where data($ship/../@name) eq $cname
let $sname := data($ship/@name)
let $slaunched := data($ship/@launched)
return
<tr><td>{$sname}</td><td>{$slaunched}</td></tr>
}
</table>
}
</body>
</html>
答案 0 :(得分:5)
我认为您遇到的问题是,当您想同时返回<h1>
和<table>
元素时,返回需要单个元素或序列。在这里使用序列:
return
(
<h1>{$cname}</h1>,
<table>
[snip]
)
注意标题后面的括号和冒号。您的where
子句还有另一个问题,我将其移入谓词中。
您想要的输出不是有效的XHTML:您必须在标题之前关闭表格。你也会得到一张桌子而不是一个枚举,你究竟在寻找什么?
这个清理过的和修复过的代码对我有用,我删除了你的文档和一些声明,但你将能够找到这些变化:
<html xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<title>XQ-7</title>
</head>
<body>
{
for $class in /Ships/Class
let $cname := data($class/@name)
let $sname := data($class/Ship/@name)
let $slaunched := data($class/Ship/@launched)
return
(
<h1>{$cname}</h1>,
<table>
{
for $ship in /Ships/Class/Ship[@name = $cname]
let $sname := data($ship/@name)
let $slaunched := data($ship/@launched)
return
<tr>
<td>{$sname}</td>
<td>{$slaunched}</td>
</tr>
}
</table>
)
}
</body>
</html>
答案 1 :(得分:2)
这一点最终成功了,在其他地方进行了调节并进行了小调整。 Xquery,你必须喜欢它;):P。
declare namespace output = "http://www.w3.org/2010/xslt-xquery-serialization";
declare option output:method "xml";
<html xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<title>XQ-7</title>
</head>
<body>
{
for $class in doc("xml/battleships.xml")/Ships/Class
let $cname := data($class/@name)
let $sname := data($class/Ship/@name)
let $slaunched := data($class/Ship/@launched)
return
(
<h1>{$cname}</h1>,
<table>
<tr><th>Name</th><th>Launched</th></tr>
{
for $ship in doc("xml/battleships.xml")/Ships/Class/Ship[../@name = $cname]
let $sname := data($ship/@name)
let $slaunched := data($ship/@launched)
return
<tr>
<td>{$sname}</td>
<td>{$slaunched}</td>
</tr>
}
</table>
)
}
</body>
</html>