2015-08-26 3 views
0

Я пытаюсь разобрать XML-документ, чтобы вернуть <input> узлы, которые содержат атрибут ref. Пример игрушки, но сам документ возвращает пустой массив, когда он должен показывать совпадение.Анализ XML с помощью lxml и elementtree

игрушка пример

import elementtree.ElementTree 
from lxml import etree 
tree = etree.XML('<body><input ref="blabla"><label>Cats</label></input><input ref="blabla"><label>Dogs</label></input><input ref="blabla"><label>Birds</label></input></body>') 
# I can return the relevant input nodes with: 
print len(tree.findall(".//input[@ref]")) 
2 

Но работа со следующим (пониженные) файл по каким-либо причинам не удается:

example.xml

<?xml version="1.0"?> 
<h:html xmlns="http://www.w3.org/2002/xforms" xmlns:ev="http://www.w3.org/2001/xml-events" xmlns:h="http://www.w3.org/1999/xhtml" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
    <h:head> 
    <h:title>A title</h:title> 
    </h:head> 
    <h:body> 
    <group ref="blabla"> 
     <label>Group 1</label> 
     <input ref="blabla"> 
     <label>Field 1</label> 
     </input> 
    </group> 
    </h:body> 
</h:html> 

сценарий

import elementtree.ElementTree 
from lxml import etree 
with open ("example.xml", "r") as myfile: 
    xml = myfile.read() 
tree = etree.XML(xml) 
print len(tree.findall(".//input[@ref]")) 
0 

Любая идея, почему это не удается, и как обходиться? Я думаю, что это может иметь какое-то отношение к заголовку XML. Очень благодарен за любую помощь.

+0

Что сообщение об ошибке? Что именно не удается? – refi64

ответ

2

Я думаю, что проблема заключается в том, что элементы всего документа в конкретных пространствах имен, так что не-пространстве именами .findall(".//input[@ref]")) выражения не соответствует input элемента в документе, который на самом деле является пространством имен input элемента, в http://www.w3.org/2002/xforms пространство имен.

Так что, возможно, попробуйте следующее:

.findall(".//{http://www.w3.org/2002/xforms}input[@ref]") 

Обновлено после моего первоначального ответа, чтобы использовать XForms пространство имен вместо пространства имен XHTML (как это было отмечено в другом ответе).

+0

Hi sidehowbarker. Извините, все еще пустой массив для меня. – geotheory

+0

Хорошо, я на самом деле не тестировал его, но сделаю это прямо сейчас и посмотрю, что я получаю – sideshowbarker

+0

Ха-ха! '.findall (" .//{http://www.w3.org/2002/xforms}input[@ref] ")' это билет :) – geotheory

2

Как видно из вашего XML, XML,-пространство имен для не-приставкой элементов - "http://www.w3.org/2002/xforms", Это происходит потому, что определяется как xmlns без префикса в родительском элементе h:html, только элементы приставкой h: имеют пространство имен как .

Таким образом, вам также необходимо использовать это пространство имен в своем запросе. Пример -

root.findall(".//{http://www.w3.org/2002/xforms}input[@ref]") 

Пример/Demo -

>>> s = """<?xml version="1.0"?> 
... <h:html xmlns="http://www.w3.org/2002/xforms" xmlns:ev="http://www.w3.org/2001/xml-events" xmlns:h="http://www.w3.org/1999/xhtml" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
... <h:head> 
...  <h:title>A title</h:title> 
... </h:head> 
... <h:body> 
...  <group ref="blabla"> 
...  <label>Group 1</label> 
...  <input ref="blabla"> 
...   <label>Field 1</label> 
...  </input> 
...  </group> 
... </h:body> 
... </h:html>""" 
>>> import xml.etree.ElementTree as ET 
>>> root = ET.fromstring(s) 
>>> root.findall(".//{http://www.w3.org/1999/xhtml}input[@ref]") 
>>> root.findall(".//{http://www.w3.org/2002/xforms}input[@ref]") 
[<Element '{http://www.w3.org/2002/xforms}input' at 0x02288EA0>] 
Смежные вопросы