Синтаксический анализ XML в Python


Цель этого кода возвращает объект, который содержит все фильмы. Где атрибуты не нашли, они должны вернуться Не скорее, чем быть неопределенным и вызывает исключение.

у attrs - список всех возможных свойств этого класса. Каждый класс перебирает и пытается вам атрибута. Если атрибут не существует, setattr(self,в том,видео.введите attrib.вам(м)) вернется никто.

Конечный результат-это объект, на который можно ссылаться так:

Рекламный блок.фильмы[0].Видео.название вернется "30 минут или меньше".

Структура XML-файла выглядит следующим образом:

  • Каждый фильм возвращается в виде XML
  • Каждый фильм имеет подраздел, который может содержать несколько элементов
  • В каждую подразделу подразделы. Там также может быть несколько записей здесь.

Я уверен, что есть лучше / проще способ сделать это.

Образец на Python исходный код следующим образом, наряду с образец XML-кода вернулся / сканируется на рекламный блок класса после этого:

import httplib
import xml.etree.ElementTree as ElementTree

def getUrl(server,url):
    c=httplib.HTTPConnection(server.ip,server.port)
    c.request("GET",url)
    r=c.getresponse()
    return r.read()

def getxml(server,serverPath,tag):
    responseData=getUrl(server,serverPath)
    e=ElementTree.XML(responseData)
    if not tag:
        return e
    else:
        return e.findall(tag)

class Video():
    class Media():
        class Part():
            def __init__(self,part):
                attrs=['key',
                       'duration',
                       'file',
                       'size',
                       ]
                for attr in attrs:
                    setattr(self,attr,part.attrib.get(attr))

        def __init__(self,media):
            attrs=['id',
                   'duration',
                   'bitrate',
                   'width',
                   'height',
                   'aspectRatio',
                   'audioChannels',
                   'audioCodec',
                   'videoCodec',
                   'videoResolution',
                   'container',
                   'videoFrameRate',
                   'optimizedForStreaming',
                   ]
            for attr in attrs:
                setattr(self,attr,media.attrib.get(attr))

            xmlParts=media.findall("Part")
            self.parts=[]
            for part in xmlParts:
                p=self.Part(part)
                self.parts.append(p)



    def __init__(self,server,video):
        # Get the detail
        self.key=video.attrib.get('key')
        x=getxml(server,self.key,"Video")
        video=x[0]

        self.video=video

        attrs=['ratingKey',
               'key',
               'studio',
               'type',
               'title',
               'contentRating',
               'summary',
               'rating',
               'year',
               'tagline',
               'thumb',
               'art',
               'duration',
               'originallyAvailableAt',
               'addedAt',
               'updatedAt',
               'titleSort',
               'viewCount',
               'viewOffset',
               'guid',
               'lastViewedAt',
               'index',
               ]
        for attr in attrs:
            setattr(self,attr,video.attrib.get(attr))


        self.media=None
        for subitem in self.video:
            if subitem.tag=="Media":
                self.media=self.Media(subitem)

class Server:
    def __init__(self,ip,port):
        self.ip=ip
        self.port=port

    def movielisturl(self,key):
        return "/library/sections/%s/all" % key

class Movielist:

    def __init__(self,server,key):
        x=getxml(server,server.movielisturl(key),"Video")
        print x
        self.movies=[]
        for item in x:
            m=Video(server,item)
            self.movies.append(m)

def main():
    s=Server("localhost",32400)
    l=Movielist(s,4)
    for video in l.movies:
        print video.title

if __name__ == "__main__":
    main()

Образец XML

<?xml version="1.0" ?>
<MediaContainer art="/:/resources/movie-fanart.jpg" identifier="com.plexapp.plugins.library" mediaTagPrefix="/system/bundle/media/flags/" mediaTagVersion="1323514612" size="260" title1="Movies" viewGroup="movie" viewMode="65592">
  <Video addedAt="1323265351" art="/library/metadata/242/art?t=1324432778" contentRating="R" duration="4980000" key="/library/metadata/242" originallyAvailableAt="2011-08-12" ratingKey="242" studio="Media Rights Capital" summary="30 Minutes or Less is a 2011 American action comedy crime film directed by Ruben Fleischer starring Jesse Eisenberg, Aziz Ansari, Danny McBride and Nick Swardson. It is produced by Columbia Pictures and funded by Media Rights Capital." thumb="/library/metadata/242/thumb?t=1324432778" title="30 Minutes or Less" type="movie" updatedAt="1324432778" year="2011">
    <Media aspectRatio="2.35" audioChannels="6" audioCodec="dca" bitrate="1500" container="mkv" duration="4983000" height="534" id="242" optimizedForStreaming="0" videoCodec="h264" videoFrameRate="24p" videoResolution="720" width="1280">
      <Part duration="4983000" file="/mnt/raid/Entertainment/Movies/30 Minutes Or Less (2011).mkv" key="/library/parts/249/file.mkv" size="3521040154"/>
    </Media>
    <Genre tag="Comedy"/>
    <Genre tag="Action"/>
    <Writer tag="Michael Diliberti"/>
    <Director tag="Ruben Fleischer"/>
    <Country tag="USA"/>
    <Role tag="Jesse Eisenberg"/>
    <Role tag="Danny McBride"/>
    <Role tag="Nick Swardson"/>
  </Video>
  <Video addedAt="1323265356" art="/library/metadata/375/art?t=1324432778" contentRating="PG-13" duration="7140000" key="/library/metadata/375" originallyAvailableAt="2010-06-11" rating="7.8" ratingKey="375" studio="Dune Entertainment" summary="The A-Team is an American action film based on the television series of the same name. It was released in cinemas in the United States on June 11, 2010, by 20th Century Fox. The film was directed by Joe Carnahan and produced by Stephen J. Cannell and the Scott brothers Ridley and Tony. The film has been in development since the mid 1990s, having gone through a number of writers and story ideas, and being put on hold a number of times. Producer Stephen J. Cannell wished to update the setting, perhaps using the first Gulf War as part of the backstory. The film stars Liam Neeson, Bradley Cooper, Quinton Jackson, and Sharlto Copley as The A-Team, former U.S. Army Rangers, imprisoned for a crime they did not commit. They escape and set out to clear their names. Jessica Biel, Patrick Wilson, and Brian Bloom fill supporting roles. The film received mixed reviews from critics and performed slightly below expectations at the box office. The reception from the cast of the original television series was also mixed." tagline="There Is No Plan B" thumb="/library/metadata/375/thumb?t=1324432778" title="The A-Team" titleSort="A-Team" type="movie" updatedAt="1324432778" year="2010">
    <Media aspectRatio="2.35" audioChannels="6" audioCodec="dca" bitrate="1500" container="mkv" duration="8013000" height="544" id="375" optimizedForStreaming="0" videoCodec="h264" videoFrameRate="24p" videoResolution="720" width="1280">
      <Part duration="8013000" file="/mnt/raid/Entertainment/Movies/The A-Team Extended 720P Bluray X264-Zmg.mkv" key="/library/parts/382/file.mkv" size="8531243656"/>
    </Media>
    <Genre tag="Thriller"/>
    <Genre tag="Action"/>
    <Writer tag="Skip Woods"/>
    <Writer tag="Joe Carnahan"/>
    <Director tag="Joe Carnahan"/>
    <Country tag="USA"/>
    <Role tag="Patrick Wilson"/>
    <Role tag="Liam Neeson"/>
    <Role tag="Sharlto Copley"/>
  </Video>
</MediaContainer>


12027
5
задан 21 декабря 2011 в 01:12 Источник Поделиться
Комментарии
2 ответа

import httplib
import xml.etree.ElementTree as ElementTree

def getUrl(server,url):
c=httplib.HTTPConnection(server.ip,server.port)
c.request("GET",url)
r=c.getresponse()
return r.read()

Во-первых, функции не соответствует ее названию. препинания заставляет меня думать, что он должен возвращать URL-адрес, не берите мой URL-адрес и загрузить его. Во-вторых, есть функция urllib.urlоткрыть, который делает все, что делает эта функция, минус последняя строка. И он принимает URL-адрес в качестве аргумента, так что вы можете совместить здесь два параметра.

def getxml(server,serverPath,tag):
responseData=getUrl(server,serverPath)
e=ElementTree.XML(responseData)

Но некоторые пробелы вокруг =. Я также думаю, что вы не должны использовать одну букву переменных (как правило).

    if not tag:

При проверке не рекомендую тег не просто, чтобы быть явным.

        return e
else:
return e.findall(tag)

class Video():

Либо опустить скобки здесь, или поместить объект в них.

    class Media():
class Part():

Я не фанат классы вложенности (как правило). Я бы отделился от них.

            def __init__(self,part):
attrs=['key',
'duration',
'file',
'size',
]
for attr in attrs:
setattr(self,attr,part.attrib.get(attr))

Я бы не рекомендовал загрузки из XML в конструкторе классов. Он связывает свои внутренние объекты слишком много в структуре файла XML. Я хотел бы предложить, имея внешнюю функцию, которая извлекает данные из XML, а затем передать его в конструктор.

        def __init__(self,media):

Вот почему занятия гнездиться проблематично. Трудно сказать, какой у меня класс сейчас.

            attrs=['id',
'duration',
'bitrate',
'width',
'height',
'aspectRatio',
'audioChannels',
'audioCodec',
'videoCodec',
'videoResolution',
'container',
'videoFrameRate',
'optimizedForStreaming',
]
for attr in attrs:
setattr(self,attr,media.attrib.get(attr))

Мы видим этот кусок кода точно в предыдущем конструктор. Вы должны переместить его в функцию.

            xmlParts=media.findall("Part")
self.parts=[]
for part in xmlParts:
p=self.Part(part)
self.parts.append(p)

Вместо этого вы можете делать самостоятельно.части = карте(самовыдвижение.Части, средства массовой информации.метод findAll("часть")). Что сделает их менее сложными, здесь.

    def __init__(self,server,video):
# Get the detail
self.key=video.attrib.get('key')

Вы действительно хотите, чтобы вам не сюда, если ключ отсутствует?

        x=getxml(server,self.key,"Video")
video=x[0]

Причин не объединить эти две линии? Конструктор получает данные от сервера. Как с разбора XML-я думаю, лучше всего это делать за пределами конструктора.

        self.video=video

Почему вы хотите сохранить ссылку на XML-узла? Разве вы не должны просто бросить его после того, как вы закончили чтение из него?

        attrs=['ratingKey',
'key',
'studio',
'type',
'title',
'contentRating',
'summary',
'rating',
'year',
'tagline',
'thumb',
'art',
'duration',
'originallyAvailableAt',
'addedAt',
'updatedAt',
'titleSort',
'viewCount',
'viewOffset',
'guid',
'lastViewedAt',
'index',
]
for attr in attrs:
setattr(self,attr,video.attrib.get(attr))

self.media=None
for subitem in self.video:
if subitem.tag=="Media":
self.media=self.Media(subitem)

Есть найти функцию или что-то, чтобы сделать это проще?

class Server:

Имя класса должно, наверное, быть более конкретным, то просто сервер

    def __init__(self,ip,port):
self.ip=ip
self.port=port

def movielisturl(self,key):
return "/library/sections/%s/all" % key

Я бы, наверное, класс сервера определить метод, который возвращает XML, а не просто предоставляя URL-адрес. Что так сервер вообще может принести в xml-в любом случае он любит не только подключения по протоколу HTTP.

class Movielist:

def __init__(self,server,key):
x=getxml(server,server.movielisturl(key),"Video")
print x
self.movies=[]
for item in x:
m=Video(server,item)
self.movies.append(m)

У меня не было бы класса рекламный блок. Я просто список фильмов. Я есть функция, которая возвращает список фильмов с конкретного сервера.

def main():
s=Server("localhost",32400)
l=Movielist(s,4)
for video in l.movies:

Вы смешиваете видео и видео, я рекомендую выбрать терминологию и придерживаться его.

        print video.title

if __name__ == "__main__":
main()

4
ответ дан 21 декабря 2011 в 08:12 Источник Поделиться

Вы можете использовать этот пакет содержит файлы Либ

from cStringIO import StringIO
from lxml import etree

xml = StringIO(''' YOUR XML ''')

def main():
tree = etree.parse(xml)
print tree.xpath("//Video/@title")

Выходы:

['30 Minutes or Less', 'The A-Team']

0
ответ дан 22 декабря 2011 в 06:12 Источник Поделиться