Ошибка при использовании выражений xpath с eXist-db

Я использую xpath для запроса XML-файлов, содержащих пьесы Шекспира (я изучаю xpath). Теперь я хочу знать, сколько раз Джульетта отвечает Ромео (говорит сразу после него). Я использовал это выражение xpath:

1: count(doc('r_and_j.xml')//SPEAKER[. = "JULIET" and ../preceding-sibling::SPEECH[1]/SPEAKER = "ROMEO"])

но это возвращает мне 4, хотя это, очевидно, не может быть правильным... Однако это работает:

2: count(doc('r_and_j.xml')//SPEECH[SPEAKER = "JULIET" and (preceding-sibling::SPEECH[1]/SPEAKER = "ROMEO")]

еще один вопрос, в котором все идет не так, звучит следующим образом: я хочу знать названия актов, у которых нет общих говорящих со следующим актом в «Ромео и Джульетте».

3: doc('r_and_j.xml')//ACT[not(.//SPEAKER = ./following-sibling::ACT[1]//SPEAKER)]/TITLE

не дает правильного результата, в то время как этот делает:

4: doc('r_and_j.xml')//ACT[not(distinct-values(.//SPEAKER) = distinct-values(./following-sibling::ACT[1]//SPEAKER))]/TITLE

Я не понимаю, почему выражения xpath 1,3 не дают ответа, а 2,4 - нет? Может ли это быть как-то связано с существованием, так как мне дали 3 в качестве решения, пока оно, похоже, не работает.

Поскольку на это сложно ответить (по крайней мере, для 1,2), если вы не знаете xml, над которым я работаю, я опубликую dtd здесь:

<!-- DTD for Shakespeare    J. Bosak    1994.03.01, 1997.01.02 -->
<!-- Revised for case sensitivity 1997.09.10 -->
<!-- Revised for XML 1.0 conformity 1998.01.27 (thanks to Eve Maler) -->

<!ENTITY amp "&#38;#38;">
<!ELEMENT PLAY     (TITLE, FM, PERSONAE, SCNDESCR, PLAYSUBT, INDUCT?,
                             PROLOGUE?, ACT+, EPILOGUE?)>
<!ELEMENT TITLE    (#PCDATA)>
<!ELEMENT FM       (P+)>
<!ELEMENT P        (#PCDATA)>
<!ELEMENT PERSONAE (TITLE, (PERSONA | PGROUP)+)>
<!ELEMENT PGROUP   (PERSONA+, GRPDESCR)>
<!ELEMENT PERSONA  (#PCDATA)>
<!ELEMENT GRPDESCR (#PCDATA)>
<!ELEMENT SCNDESCR (#PCDATA)>
<!ELEMENT PLAYSUBT (#PCDATA)>
<!ELEMENT INDUCT   (TITLE, SUBTITLE*, (SCENE+|(SPEECH|STAGEDIR|SUBHEAD)+))>
<!ELEMENT ACT      (TITLE, SUBTITLE*, PROLOGUE?, SCENE+, EPILOGUE?)>
<!ELEMENT SCENE    (TITLE, SUBTITLE*, (SPEECH | STAGEDIR | SUBHEAD)+)>
<!ELEMENT PROLOGUE (TITLE, SUBTITLE*, (STAGEDIR | SPEECH)+)>
<!ELEMENT EPILOGUE (TITLE, SUBTITLE*, (STAGEDIR | SPEECH)+)>
<!ELEMENT SPEECH   (SPEAKER+, (LINE | STAGEDIR | SUBHEAD)+)>
<!ELEMENT SPEAKER  (#PCDATA)>
<!ELEMENT LINE     (#PCDATA | STAGEDIR)*>
<!ELEMENT STAGEDIR (#PCDATA)>
<!ELEMENT SUBTITLE (#PCDATA)>
<!ELEMENT SUBHEAD  (#PCDATA)>

ссылки на xml (и другие пьесы помимо Ромео и Джульетты) здесь: http://metalab.unc.edu/bosak/xml/eg/shaks200.zip


person codelidoo    schedule 01.06.2011    source источник


Ответы (1)


Я не знаю, как вы получаете 4 из первого запроса, так как вы просите (частично) найти элементы SPEAKER внутри элементов SPEAKER, а DTD не разрешает этого.

Я использую текст воспроизведения XML, доступный по адресу http://www.ibiblio.org/xml/examples/shakespeare/

Если вы хотите найти все речи Джульетты, которым предшествовали речи R, то (давайте создадим это)

все выступления:

//SPEECH (возвращает 841 элемент)

все выступления Джульетты:

//SPEECH[SPEAKER='JULIET'] (возвращает 118 элементов)

и наконец:

//SPEECH[SPEAKER='JULIET' and preceding-sibling::SPEECH[1][SPEAKER='ROMEO']] (возвращает 37 элементов)

Ваша вторая задача довольно сложная, но ее можно выполнить с помощью оператора =, который при сравнении наборов узлов возвращает true, если какое-либо значение в наборах является общим, поэтому:

//ACT[ following-sibling::ACT and not(.//SPEAKER = following-sibling::ACT[1]//SPEAKER)]/TITLE

Неудивительно, что все смежные акты в пьесе имеют несколько общих говорящих, поэтому ничего не возвращается.

person alexbrn    schedule 01.06.2011
comment
Я исправил опечатки... Я также сделал ошибку в строке 1, вложенный SPEAKER должен был быть '.' Я знаю, почему запросы 2,4 работают, но меня больше интересует, почему 1,3 не работают. Тем более, что единственная разница в 3 и 4 - это разные значения. - person codelidoo; 02.06.2011
comment
что ваши 3 и 4 возвращают для вас? - person alexbrn; 02.06.2011
comment
3: ничего, 4: ACT V (последний акт) оба имеют семантический смысл, но если вы посмотрите на запросы, я чувствую, что они оба должны возвращать ACT V, так как для последнего акта не ((динамики в ACTV) = ()) правда, и я не понимаю, как это могло бы измениться без использования различных значений (как в 3). - person codelidoo; 02.06.2011
comment
Интересно - я ожидаю, что 3 вернет Act V (и мой тест - с использованием oXygen - сделал это, поэтому я исключил это из своего выражения) - person alexbrn; 02.06.2011
comment
Да, именно мои мысли, может быть, вещь Exist, так как в школе мне дали 3 как правильное решение. А что с моей исправленной версией 1? Так как я только что нашел кое-что весьма любопытное об этом. Если я переключаю два условия (A и B на B и A), возвращаемое значение равно 1 вместо 4 (оба неверны, но все же ..)? Разве «и» не коммутативно, или есть побочные эффекты, о которых я не знаю? (Если это также то, что вы не испытываете, мне может понадобиться найти что-то еще, чтобы проверить мой xpath. - person codelidoo; 02.06.2011