2016-05-25 7 views
0

У меня есть XML-документ вроде следующего:Как выбрать следующие конкретные узлы XML с помощью XPath?

<Objects> 
    <object distName="a/b"> </object> 
    <object distName="a/b/c1"> </object> 
    <object distName="a/b/c4/d/e"> </object> 
    <object distName="a/b/c2"> </object> 
    <object distName="a/b/c6/d"> </object> 
</Objects> 

И мне нужно, чтобы выбрать все узлы, которые имеет путь, который заканчивается «с» + номер. Как: "A/B/с1" и "а/б/с2", но не как "A/B/с6/д", ни "A/B/с4/д/е" ,

Если я стараюсь следующее:

 `cNodes = xmlDoc.xpath("//object[contains(@path, `a/b/c`)]")` 

Тогда это будет включать в себя "A/B/с6/д" и "а/б/c4/D/E", который не то, что я требую.

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

PS: Python 2.7, LXML

+0

Нет, путь - это всего лишь атрибут. Это не имеет никакого отношения к контенту. – AhmedWas

+0

@JeffMercado Я изменил имя с 'path' на' distName'. Потому что я просто приведу пример. это не совсем похоже на документ XML, который у меня есть. – AhmedWas

+0

@JeffMercado Извините, моя ошибка. Я отредактирую. – AhmedWas

ответ

1

К сожалению, не очень просто выразить условие, которое соответствует шаблонам с использованием XPath 1.0. Но если вы можете сделать определенные предположения о том, что вы ищете, вы можете создать такой запрос.

//object[starts-with(@distName, 'a/b/c') and substring-after(@distName, 'a/b/c') >= 0] 

ломки, мы первые проверки, если атрибут distName начинается с a/b/c. Тогда, если все после этой строки - некоторое число. В зависимости от ваших потребностей этого может быть достаточно.

+0

Идеальный чувак, работает как шарм :) – AhmedWas

1

Я боюсь, что это не может быть сделано с помощью чистого XPath 1.0, который является XPath версии, lxml подставок.

В качестве альтернативы, вы можете попытаться разбить атрибут на /, получить последний раздвоение результат, и проверить, если он начинается с c, все в одной строке, используя список понимание, например:

>>> raw = '''<Objects> 
... <object distName="a/b"> </object> 
... <object distName="a/b/c1"> </object> 
... <object distName="a/b/c4/d/e"> </object> 
... <object distName="a/b/c2"> </object> 
... <object distName="a/b/c6/d"> </object> 
... </Objects>''' 
... 
>>> from lxml import etree 
>>> xmlDoc = etree.fromstring(raw) 
>>> cNodes = xmlDoc.xpath("//object[contains(@path, 'a/b/c')]") 
>>> result = [etree.tostring(n) for n in cNodes if n.attrib["distName"].split('/')[-1].startswith("c")] 
>>> print result 
['<object distName="a/b/c1"> </object>\n ', '<object distName="a/b/c2"> </object>\n '] 
+0

Дело в том, что эти cNodes являются родителями других узлов в реальном XML-файле. И я забочусь о выборе самих узлов. Но похоже, что нет другого пути, кроме как пройти цикл. В любом случае, спасибо за ответ :) – AhmedWas

+0

Нет, похоже, что есть решение. Принятый ответ - это то, что мне нужно. – AhmedWas

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