Я работаю над перемещением соседних xml-данных в иерархический фрейм данных. Я смог получить все данные из xml благодаря помощи в SO. Однако теперь я работаю над очисткой данных, которые я извлекаю и формирую их перед выходом, потому что я буду делать это тысячи раз.Динамический поиск по атрибутам xml с использованием lxml и xpath в python
ОБНОВЛЕНО: ЭТО, ЧТО Я ВЕЧЕР ВСТРЕЧА. Кажется, я не могу получить только Time
и value
для channel
динамически. Имена каналов будут изменены для каждого файла.
Когда channel = txt1[0]
(для этого файла, txt1[0]="blah"
) через когда channel = txt1[8]
(для этого файла, txt1[8]="lir"
)
channel Time value
0 blah 2013-05-01 00:00:00 258
1 blah 2013-05-01 00:01:00 259
...
n-2 lir 2013-05-01 23:57:00 58
n-1 lir 2013-05-01 23:58:00 37
n lir 2013-05-01 23:59:00 32
Вот как мой файл XML извлекается и структурирована:
import requests
from lxml import etree, objectify
r = requests.get('https://api.stuff.us/place/getData? security_key=key&period=minutes&startTime=2013-05-01T00:00&endTime=2013-05-01T23:59&sort=channel') #edited for privacy
root = etree.fromstring(r.text)
xml_new = etree.tostring(root, pretty_print=True)
print xml_new[300:900] #gives xml output to show structure
<startTime>2013-05-01 00:00:00</startTime>
<endTime>2013-05-01 23:59:00</endTime>
<summaryPeriod>minutes</summaryPeriod>
<data>
<channel channel="97925" name="blah">
<Time Time="2013-05-01 00:00:00">
<value>258</value>
</Time>
<Time Time="2013-05-01 00:01:00">
<value>259</value>
</Time>
<Time Time="2013-05-01 00:02:00">
<value>258</value>
</Time>
<Time Time="2013-05-01 00:03:00">
<value>257</value>
</Time>
Вчера, Я спросил здесь о SO и решил проблему получения значений time
и value
в кадре данных: Parsing xml to pandas data frame throws memory error
dTime=[]
dvalue=[]
for df in root.xpath('//channel/Time'):
## Iterate over attributes of Time but Time only has one attrib [@Time]
for attrib in df.attrib:
dTime.append(df.attrib[attrib])
## value is a child of time, and iterate
subfields = df.getchildren()
for subfield in subfields:
dvalue.append(subfield.text)
pef=DataFrame({'Time':dTime,'values':dvalue})
pef
<class 'pandas.core.frame.DataFrame'>
Int64Index: 12960 entries, 0 to 12959
Data columns (total 2 columns):
Time 12960 non-null values
value 12960 non-null values
dtypes: object(2)
pef[:5]
Time value
0 2013-05-01 00:00:00 258
1 2013-05-01 00:01:00 259
2 2013-05-01 00:02:00 258
3 2013-05-01 00:03:00 257
4 2013-05-01 00:04:00 257
Теперь, я работаю на эти данные для каждого из каналов (структура channel
->Time
->value
) по отдельности, так что можно вставить канал в качестве столбца набора данных.
Итак, я решил динамически получить имена каналов и выполнить поиск по данным. Для этого файла существует девять отдельных допустимых имен каналов, но это не то же самое для всех файлов (число или имена).
txt1 = root.xpath('//channel/@name') #this prints all channel names!
len(txt1)
Out[67]: 9
print txt1
['blah', 'b', 'c', 'd', 'vd', 'ef', 'fg', 'kc', 'lir']
Я думал, что я мог бы динамически получать данные (с использованием ранее решения, но добавление @name=txt1[0]
) и в конечном счете делает for i = 0 to len(txt1), ...
, чтобы пройти через все из них. Но я получаю пустой кадр данных:
dTime=[]
dchannel = txt1[0] # can hardcode, but need to be able to get all
dvalue=[]
for df in root.xpath('//channel[@name=txt1[0]]/Time'):
#CODE NEEDED: to get dchannel to dynamically = channel[@name]
## Iterate over attributes of time for specific channel
for attrib in df.attrib:
dTime.append(df.attrib[attrib])
## value is a child of time, and iterate
subfields = df.getchildren()
for subfield in subfields:
dvalue.append(subfield.text)
perf=DataFrame({'Channel': dchannel,'Time':dTime,'values':dvalue})
perf
Int64Index([], dtype=int64)
Empty DataFrame
Если я жесткий код нужного атрибута, как for df in root.xpath('/*/*/*/channel[@name="blah"]/Time'):
он будет печатать его для одного атрибута, но я не могу заставить его работать ссылки txt1[]
.
Я пытался со ссылкой на {0}..., txt1[]
, но затем он выплевывает кортеж для атрибута dchannel (потому что она становится все txt1 вместо того, чтобы получение txt1 имя, которое является родителем времени узла атрибута.
I просмотрел документацию XPath, и я прошел через учебник lxml, и я не могу понять, почему мой динамический поиск не работает. Мне нужно вернуться к .findall()
? Как я могу использовать этот динамический поиск для получения данных для каждого значение в txt1
?
Возможно, существует более питонический подход к этому, например, создание функции, которая получает attr ibute [@name]
родителя, атрибут [@Time]
ребенка, а затем текст внука value
, но я еще не понял, как это сделать.