XPath-запрос с несколькими переменными условиями - PullRequest
0 голосов
/ 20 декабря 2011

Постоянный слушатель, впервые звонящий. Я относительно новичок в 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' или чем-то еще. Не повезло и с | профсоюзами.

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

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

Ответы [ 3 ]

3 голосов
/ 20 декабря 2011

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

/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]... с вашими различными ограничениями.Каждый новый тест действует как фильтр.

1 голос
/ 22 декабря 2011

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

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

</xsl:for-each>

Труба (|) будет объединять каждый результат

1 голос
/ 20 декабря 2011

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

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

содержит (../ title, 'Brothers') и ../@lang = 'en']

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

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

 /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 должны быть заменены данными, которыеуказанный пользователем должен содержаться в соответствующих полях.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...