Выражение Xpath с несколькими предикатами - PullRequest
45 голосов
/ 20 февраля 2009

Я пытаюсь создать сложное выражение xpath, которое будет отвечать следующему условию.

Из приведенных ниже данных XML возвращает объект Пользователь , который:

  1. Его логин: " user1 "
  2. Его зовут " Пользователь 1 "
  3. У него есть 2 разных значения профиля: « оператор » и « admin » (точный порядок не известен)

    <user>
      <login>user1</login>
      <name>User 1</name>
      <profile>
        <value>admin</value>
        <id>2</id>
        <description>admin users</description>
      </profile>
      <profile>
        <value>operator</value>  
        <id>1</id>
        <description>Operator</description>
      </profile>
    </user>
    
    <user>
      <login>user2</login>
      <name>User 2</name>
      <profile>
        <value>admin</value>
        <id>4</id>
        <description>admins users</description>
      </profile>
      <profile>
        <value>poweruser</value>  
        <id>5</id>
        <description>power users</description>
      </profile>
    </user>
    
    </root>
    

Может кто-нибудь привести пример для такого случая?

EDIT: добавлен объект сложного профиля

Ответы [ 4 ]

70 голосов
/ 20 февраля 2009

Следующее должно делать то, что вы после:

/root/user[login='user1' and 
           name='User 1' and 
           profile='admin' and
           profile='operator']

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

Причина, по которой вы можете сравнить profile напрямую с string, даже если это на самом деле node, заключается в том, что string-value узла элемента - это string-value всех его потомков, соединенных вместе, что в данном случае это просто содержимое value.

Если бы profile содержал больше элементов, чем value, вам пришлось бы использовать чуть более сложный тест предикатов, чтобы определить наличие соответствующего узла profile на основе только value (это должно работать с вашим обновленный вопрос):

/root/user[login='user1' and 
           name='User 1' and 
           profile[value='admin'] and
           profile[value='operator']]
6 голосов
/ 20 февраля 2009

Вот более точный ответ (в настоящее время ответ Грега Бича не проверяет условие 3. в задаче: элемент user должен иметь ровно 2 profile дочерних элементов):

/*/user
        [login='user1' 
        and            
         name='User 1' 
        and  
         not(profile[3])
        and          
         profile/value='admin' 
        and           
         profile/value='operator'
         ]
1 голос
/ 20 февраля 2009

Предполагая, users является корнем:

/users/user[login='user1' and name='User 1' 
            and (profile='admin' and profile='operator')]
0 голосов
/ 27 ноября 2013
/root/user[login='user1' and name='User 1' and profile/value='admin' and profile/value='operator'
...