我有一个如下所示的XML文件:
<?xml version="1.0" encoding="utf-8" ?>
<PrivateSchool>
<Teacher id="teacher1">
<Name>
teacher1Name
</Name>
</Teacher>
<Teacher id="teacher2">
<Name>
teacher2Name
</Name>
</Teacher>
<Student id="student1">
<Name>
student1Name
</Name>
</Student>
<Student id="student2">
<Name>
student2Name
</Name>
</Student>
<Lesson student="student1" teacher="teacher1" />
<Lesson student="student2" teacher="teacher2" />
<Lesson student="student3" teacher="teacher3" />
<Lesson student="student1" teacher="teacher2" />
<Lesson student="student3" teacher="teacher3" />
<Lesson student="student1" teacher="teacher1" />
<Lesson student="student2" teacher="teacher4" />
<Lesson student="student1" teacher="teacher1" />
</PrivateSchool>
还有一个与此XML相关的DTD,但我认为它与我的问题没有多大关系。让我们假设所有需要的老师和学生都有明确的定义。
什么是返回教师姓名的XPath查询,至少有一名学生参加了10多个课程?
我正在查看许多XPath站点/示例。对于这类问题,似乎没有什么先进的。
答案 0 :(得分:1)
在单个XPath中进行复杂的连接可能是可能的,但是你正在敲打砖墙。 XQuery或XSLT更适合这种事情。这是在XQuery中:
declare variable $doc as doc('data.xml');
declare function local:numLessons($teacher, $student) {
return count($doc//Lesson[@teacher = $teacher and @student = $student])
};
$doc//Teacher[some $s in //Lesson/@student satisfies local:numLessons(@id, $s) gt 10]/Name
完成后,如果你真的确定你可以将它减少到XPath 2.0:
doc('data.xml')//Teacher[
for $t in . return
some $s in //Lesson/@student satisfies
count(//Lesson[@teacher = $t and @student = $s]) gt 10] /Name
未经测试。
答案 1 :(得分:1)
这是一个XPath 2.0解决方案:
(/PrivateSchool
/Lesson)
[index-of(
/PrivateSchool
/Lesson
/concat(@student, '|', @teacher),
concat(@student, '|', @teacher)
)[10]
]/(for $teacher in @teacher
return /PrivateSchool
/Teacher[@id = $teacher]
/Name)
答案 2 :(得分:1)
使用此XPath 2.0表达式:
for $limit in 2,
$t in /*/Teacher,
$id in $t/@id,
$s in /*/Student/@id,
$numLessons in
count(/*/Lesson[@teacher eq $id
and @student eq $s])
return
if($numLessons gt $limit)
then
(string-join(($t/Name, $s, xs:string($numLessons)), ' '),
'
'
)
else ()
这里我将$limit
设置为2,以便在根据提供的XML文档评估此XPath表达式时:
<PrivateSchool>
<Teacher id="teacher1">
<Name>teacher1Name</Name>
</Teacher>
<Teacher id="teacher2">
<Name>teacher2Name</Name>
</Teacher>
<Student id="student1">
<Name>student1Name</Name>
</Student>
<Student id="student2">
<Name>student2Name</Name>
</Student>
<Lesson student="student1" teacher="teacher1" />
<Lesson student="student2" teacher="teacher2" />
<Lesson student="student3" teacher="teacher3" />
<Lesson student="student1" teacher="teacher2" />
<Lesson student="student3" teacher="teacher3" />
<Lesson student="student1" teacher="teacher1" />
<Lesson student="student2" teacher="teacher4" />
<Lesson student="student1" teacher="teacher1" />
</PrivateSchool>
会产生正确的结果:
teacher1Name student1 3
在您的真实表达中,您将$limit
设置为10
并且只会返回教师的姓名:
for $limit in 10,
$t in /*/Teacher,
$id in $t/@id,
$s in /*/Student/@id,
$numLessons in
count(/*/Lesson[@teacher eq $id
and @student eq $s])
return
if($numLessons gt $limit)
then ($t/Name, '
')
else ()
答案 3 :(得分:0)
Michael Kay为xpath 2.0发布的解决方案是正确的,但是近似。在问题上发布的xml的精确解决方案是(没有绝对路径):
//Teacher[
for $t in . return
some $s in //Student satisfies
count(//Lesson[@teacher = $t/@id and @student = $s/@id]) gt 1
]/Name
(我使用“gt 1”代替“gt 10”以获得一些结果)