2011-12-20 2 views
0

Долгосрочный слушатель, впервые вызывающий. Я относительно новичок в XPath и посмотрел на несколько других потоков здесь и в других местах, но я не могу заставить запрос работать, любая помощь будет отличной.Запрос XPath с переменными множественными условиями

У меня есть XML следующим образом:

<catalog> 
    <book pgid="28054" lang="en"> 
    <title>The Brothers Karamazov</title> 
    <author>Dostoyevsky, Fyodor</author> 
    <friendly_title>The Brothers Karamazov by Fyodor Dostoyevsky</friendly_title> 
    <file> 
     <type>ePub</type> 
     <path>cache/generated/28054/</path> 
     <name>pg28054.epub</name> 
     <size>800</size> 
    </file> 
    <file> 
     <type>PDF</type> 
     <path>2/8/0/5/28054/</path> 
     <name>28054-pdf.pdf</name> 
     <size>5829</size> 
    </file> 
    <file> 
     <type compression="zipped">PDF</type> 
     <path>2/8/0/5/28054/</path> 
     <name>28054-pdf.zip</name> 
     <size>1693</size> 
    </file> 
    <file> 
     <type encoding="utf-8" compression="zipped">Text</type> 
     <path>2/8/0/5/28054/</path> 
     <name>28054-0.zip</name> 
     <size>726</size> 
    </file> 
    </book> 
</catalog> 

(каталог является корневым элементом, и в этом примере нет <contributor> элементов)

У меня есть запрос, работающий на автора, вкладчик, название, и поиск по языку, но я получаю зависание при добавлении условия типа файла. Этот запрос, чтобы найти книги с автором или вкладчиком, содержащие «Достоевский» и заголовок, содержащие «Братья» с языком «en», - , работающий (т. Е. Ожидающие результаты), но если есть лучший способ написать это, я все уши:

/catalog//book/*[(contains(self::author,'Dostoyevsky') or contains(self::contributor,'Dostoyevsky')) and contains(../title,'Brothers') and ../@lang = 'en'] 

Что я не может приступить к работе ограничивает результаты запроса к файлам определенного типа, т.е. прилагаемой and ../file/type='PDF' или что-то. Не было удачи с | союзами.

Заранее спасибо.

О, и если это имеет значение, запрос должен быть построен динамически (из ввода формы), поэтому ему необходимо сохранить универсальный синтаксис, который будет работать с любым количеством критериев, предоставленных пользователем.

+0

Пожалуйста, сделайте свою домашнюю работу и в как минимум, обеспечивают реальный, хорошо сформированный и значимый XML-документ. –

+0

Что ты хочешь, Димитрий? Это _is_ мой настоящий XML. Я не думал, что содержание релевантно. – swornabsent

+0

@swornabsent: Dimitre прав, ваш XML не очень хорошо сформирован. То, как вы пишете свой атрибут lang, не является XML. Вы должны обновить свой вопрос, чтобы сделать его действительным (например, lang = "..."). –

ответ

3

Если я вас правильно, это должно работать:

/catalog[file/type='PDF']//book/*[(contains(self::author,'Dostoyevsky') or contains(self::contributor,'Dostoyevsky')) and contains(../title,'Brothers') and ../@lang = 'en'] 

Обратите внимание, что фильтр находится прямо на catalog элемента.

Если вы попытаетесь получить book элементов, возможно, вам следует использовать /catalog[file/type=...]//book[test1][test2][test3]... с различными ограничениями. Каждый новый тест действует как фильтр.

+0

Спасибо, Винсент, что проясняет ситуацию. Я опередил себя. – swornabsent

+0

Эта же логика работает также, когда вы хотите проверить что-то на следующих братьях и сестрах, то есть '... и содержит (текст(), 'Some text 1') и ../td[4] = 'Некоторый текст ...' –

1

Этого запрос, чтобы найти книги с автором или вкладчиком, содержащими «Достоевский» и названием, содержащим «Brothers» с языком «ан» является работает (т.е. дают ожидаемые результаты), но если есть лучший способ записи это я все уши:

/catalog//book/*[(contains(self::author,'Dostoyevsky') or contains(self::contributor,'Dostoyevsky')) and 

содержит (../ название, 'Братья') и ../@lang = 'ан']

выражение XPath выше не только довольно несовершенный d абсолютно не отформатирован и нечитабелен, но, что более важно, он не (как указано) вообще не выбирает элемент book (он может выбрать author). Кроме того, псевдо-оператор // не является необходимым и может значительно снизить эффективность оценки XPath на любом реальном мире с умеренным или большим XML-документом.

Вот это выражение XPath, который выбирает то, что вы хотите:

/catalog/book 
    [@lang='en' 
    and 
    file/type='PDF' 
    and 
    *[self::author 
     or 
     self::contributor 
     ] 
     [contains(., 'Dostoyevsky')] 
     and 
     contains(title, 'Brothers') 
    ] 

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

Этот «универсальный синтаксис может выглядеть следующим образом:

/*/book 
    [ 
    contains(*[name() = $pName1], $pString1) 
    and 
    contains(*[name() = $pName2], $pString2) 
. . . . . . 
    and 
    contains(*[name() = $pNameK], $pStringK) 
    ] 

где $pName1, $pName2 ..., $pNameK следует заменить имена полей конечный пользователь указал в поиске форма и

$pString1, $pString2, ..., $pStringK должны быть заменены данными, которые пользователь указал, должны содержаться в соответствующих полях.

+0

Спасибо Димитрию. Это было немного skunkworks, и изначально у меня была некоторая логика PHP на стороне сервера, в которой был найден желаемый родительский элемент в зависимости от того, какие результаты были созданы. Это полезно, так же как и ваши другие ответы. – swornabsent

+0

@swornabsent: Добро пожаловать. Я просто обновил свой ответ, чтобы дать вам представление о запрошенном «универсальном синтаксисе» - наслаждайтесь :) –

1

Более простой способ сделать это состоит в фильтр для двух/трех условий по отдельности и присоединиться к ним,

<xsl:for-each select="//catalog//title[contains(., 'Dostoyevsky')] | //catalog//author[contains(., 'Brothers')]"> 

</xsl:for-each> 

Труба (|) будет сочетать в себе каждый результат

Смежные вопросы