Python поиск с использованием шаблона xpath с логическим И - PullRequest
0 голосов
/ 28 января 2020

Вот мой xpath:

<Unit>
  <_unit_type>FSP</_unit_type>
  <_logicalId>FSM1/FSP1</_logicalId>
</Unit>
<Unit>
  <_unit_type>FSP</_unit_type>
  <_logicalId>FSM1/FSP2</_logicalId>
</Unit>

Поэтому мне нужно найти len(root.findall(xpath_pattern), когда мой xpath_pattern = .//Unit[_unitType='FSP'][starts-with(_logicalId,'FSM1']

Если мой шаблон .//Unit[_unitType='FSP'], мой код работает и я могу получить длину, равную 2. Но мне нужно добавить другой квалификатор, поскольку мой файл xml намного сложнее.

Я получаю SyntaxError: недопустимый предикат при использовании этого шаблона .//Unit[_unitType='FSP'][starts-with(_logicalId,'FSM1']

Ответы [ 3 ]

1 голос
/ 29 января 2020

Вы написали

.//Unit[_unitType='FSP'][starts-with(_logicalId,'FSM1']

, и это вызывает синтаксическую ошибку Invalid Predicate. Это из-за отсутствующей закрывающей скобки. Попробуйте это:

.//Unit[_unitType='FSP'][starts-with(_logicalId,'FSM1')]
1 голос
/ 28 января 2020

Просто используйте операторы AND, чтобы добавить необходимые условия.

Пример, если вы ищете конкретную c "Единицу":

//Unit[_unit_type='FSP' AND contains(.,'S')][starts-with(_logicalid,'FSM1') AND contains(.,'FSP1')]

Вы также можете использовать " |» работать с несколькими XPath. Xpath1 | Xpath2 | Xpath3 | ... Если вы ищете что-то отличное от Unit:

//Unit[_unit_type='FSP'][starts-with(_logicalid,'FSM1')]|//Entity[_unit_type='XYZ'][starts-with(_logicalid,'FSM1')]
0 голосов
/ 29 января 2020

Проблема в том, что модуль lxml сохраняет по причинам совместимости два разных движка XPath. От l xml FAQ :

findall() является частью оригинального ElementTree API . Он поддерживает простое подмножество языка XPath , без предикатов, условий и других расширенных функций. [...]

xpath(), с другой стороны, поддерживает всю мощь языка XPath, включая предикаты, функции XPath и Python функции расширения.

Используйте метод xpath(), как в

from lxml import etree
root = etree.XML("""
<root> 
  <Unit> 
    <_unit_type>FSP</_unit_type>  
    <_logicalId>FSM1/FSP1</_logicalId> 
  </Unit>  
  <Unit> 
    <_unit_type>FSP</_unit_type>  
    <_logicalId>FSM1/FSP2</_logicalId> 
  </Unit> 
</root>""")
print(root.xpath(".//Unit[_unit_type='FSP'][starts-with(_logicalId,'FSM1')]"))

Вывод на консоль:

[<Element Unit at 0x7fa1e0413140>, <Element Unit at 0x7fa1e04130f0>]

Регистрация здесь

...