Форум сайта python.su
Добрый день!
Есть xml-документ который надо “отпарсить” и часть документа (контейнер с вложенными контейнерами)
преобразовать в текстовый файл определенного формата (не html!).
Какими средствами (читай:библиотеками) на питоне можно возпользоваться и чего почитать по теме.
Спасибо.
Офлайн
а может просто XSLT использовать? он для этого предназначен.
а на Пайтоне - надо делать связку из парсера ХМЛ (коих много) и шаблонного движка для организации правильного вывода (mako, cheetah и т.п.)
Офлайн
я думаю - вполне можно воспользоваться парсером xml.etree.ElementTree (поставляеться с питоном).
С помощью него можно довольно просто сделать вышеописанное.
Смотреть по теме можно в документации.
И туториалы здесь: http://effbot.org/zone/element-index.htm
Офлайн
Вообщем пробую сделать это через xml.parsers.expat.
Есть .xml файл:
<?xml version="1.0" encoding="UTF-8"?>
<!--Sample XML file generated by XMLSpy v2008 sp1 (http://www.altova.com)-->
<NET xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<server xmlns="">
<ro:router router_name="Router1">
<ro:cisco_series_7200>
<ro:cisco_model_7200>
<ro:model>7200</ro:model>
<ro:image>/home/ios/images/C7200-IK.BIN</ro:image>
<ro:slot0>
<ro:module_C7200-IO-2FE name_module="C7200-IO-2FE">
<ro:connect name_interface="f0/0" target_router="Router2" target_router_interface="f0/0"/>
<ro:connect name_interface="f0/1" target_router="Router3" target_router_interface="f0/1"/>
</ro:module_C7200-IO-2FE>
</ro:slot0>
<ro:slot1>
<ro:module_PA-FE-TX name_module="PA-FE-TX"/>
</ro:slot1>
</ro:cisco_model_7200>
</ro:cisco_series_7200>
</ro:router>
<ro:router router_name="Router2">
<ro:cisco_series_3600>
<ro:cisco_model_3660>
<ro:model>3660</ro:model>
<ro:image>/home/ios/images/C3660-IK.BIN</ro:image>
<ro:connect name_interface="f0/0" target_router="Router1" target_router_interface="f0/0"/>
<ro:connect name_interface="f0/1" target_router="Router3" target_router_interface="f0/0"/>
</ro:cisco_model_3660>
</ro:cisco_series_3600>
</ro:router>
<ro:router router_name="Router3">
<ro:cisco_series_7200>
<ro:cisco_model_7200>
<ro:model>7200</ro:model>
<ro:image>/home/ios/images/C7200-IK.BIN</ro:image>
<ro:slot0>
<ro:module_C7200-IO-2FE name_module="C7200-IO-2FE">
<ro:connect name_interface="f0/0" target_router="Router2" target_router_interface="f0/1"/>
<ro:connect name_interface="f0/1" target_router="Router1" target_router_interface="f0/1"/>
</ro:module_C7200-IO-2FE>
</ro:slot0>
</ro:cisco_model_7200>
</ro:cisco_series_7200>
</ro:router>
</server>
</NET>
[[router Router1]]
model=7200
image=/home/ios/images/C7200-IK.BIN
slot0=C7200-IO-2FE
f0/0=Router2 f0/0
f0/1=Router3 f0/1
slot1=PA-FE-TX
[[router Router2]]
model=3660
image=/home/ios/images/C3660-IK.BIN
f0/0=Router1 f0/0
f0/1=Router3 f0/0
[[router Router3]]
model=7200
image=/home/ios/images/C7200-IK.BIN
slot0=C7200-IO-FE
f0/0=Router2 f0/1
f0/1=Router1 f0/1
#!/usr/bin/python
# -*- coding:utf-8 -*-
from xml.parsers import expat
file = '/opt/test_socket/example.xml'
def start_element(name, attr):
if name == 'ro:router':
print '[[router %s]]'%(attr['router_name'])
p = expat.ParserCreate()
p.StartElementHandler = start_element
h = open(file,'r')
p.ParseFile(h)
h.close
[[router Router1]]
[[router Router2]]
[[router Router3]]
Офлайн
Metheo
я бы сделал проще
сначала разбил бы исходный текст на разделы-роутеры - split('<ro:router')
дальше пробежался бы циклом по полученным разделам, выдерая из строк информацию,
здесь же в этом цикле добавил бы все в массив, уже в том виде, в котором будет новый файл
вроде задача элементарна
Офлайн
:( :( :\ не получается!
Вот этот код выводит мне построчно списки с элементами состоящими из слов строк xml файла.
Как разбивать файл на части по опред. признаку (тэгу <ro:router), как обращаться к формируемым string.split() спискам - не понимаю! =(
file = '/opt/test_socket/example.xml'
h = open(file,'r')
for lines in h:
ln = string.split(lines)
print ln
h.close
['<?xml', 'version="1.0"', 'encoding="UTF-8"?>']
['<!--Sample', 'XML', 'file', 'generated', 'by', 'XMLSpy', 'v2008', 'sp1', '(http://www.altova.com)-->']
['<NET', 'xsi:schemaLocation="http://www.avalon.ru', 'Schema.xsd"']
['xmlns="http://www.avalon.ru"']
['xmlns:dev="http://www.avalon.ru/devices"']
['xmlns:ht="http://www.avalon.ru/host"']
['xmlns:in="http://www.avalon.ru/interface"']
['xmlns:net="http://www.avalon.ru/network"']
['xmlns:os="http://www.avalon.ru/os"']
['xmlns:port="http://www.avalon.ru/port"']
['xmlns:ro="http://www.avalon.ru/router"']
['xmlns:sw="http://www.avalon.ru/switch"']
['xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">']
[]
['<server', 'xmlns="">']
['<ro:router', 'router_name="Router1">']
['<ro:cisco_series_7200>']
['<ro:cisco_model_7200>']
['<ro:model>7200</ro:model>']
['<ro:image>http://www.altova.com</ro:image>']
['<ro:slot0>']
['<ro:module_C7200-IO-2FE', 'name_module="C7200-IO-2FE">']
['<ro:connect', 'name_interface="f0/0"', 'target_router="Router2"', 'target_router_interface="f0/0"/>']
['<ro:connect', 'name_interface="f0/1"', 'target_router="Router3"', 'target_router_interface="f0/1"/>']
['</ro:module_C7200-IO-2FE>']
['</ro:slot0>']
['<ro:slot1>']
['<ro:module_PA-FE-TX', 'name_module="PA-FE-TX"/>']
['</ro:slot1>']
['</ro:cisco_model_7200>']
['</ro:cisco_series_7200>']
['</ro:router>']
['<ro:router', 'router_name="Router2">']
['<ro:cisco_series_3600>']
['<ro:cisco_model_3660>']
['<ro:model>3660</ro:model>']
['<ro:image>http://www.altova.com</ro:image>']
['<ro:connect', 'name_interface="f0/0"', 'target_router="Router1"', 'target_router_interface="f0/0"/>']
['<ro:connect', 'name_interface="f0/1"', 'target_router="Router3"', 'target_router_interface="f0/0"/>']
['</ro:cisco_model_3660>']
['</ro:cisco_series_3600>']
['</ro:router>']
['<ro:router', 'router_name="Router3">']
['<ro:cisco_series_7200>']
['<ro:cisco_model_7200>']
['<ro:model>7200</ro:model>']
['<ro:image>http://www.altova.com</ro:image>']
['<ro:slot0>']
['<ro:module_C7200-IO-2FE', 'name_module="C7200-IO-2FE">']
['<ro:connect', 'name_interface="f0/0"', 'target_router="Router2"', 'target_router_interface="f0/1"/>']
['<ro:connect', 'name_interface="f0/1"', 'target_router="Router1"', 'target_router_interface="f0/1"/>']
['</ro:module_C7200-IO-2FE>']
['</ro:slot0>']
['</ro:cisco_model_7200>']
['</ro:cisco_series_7200>']
['</ro:router>']
['<sw:switch>text</sw:switch>']
['</server>']
['</NET>']
Отредактировано (Янв. 15, 2009 14:09:28)
Офлайн
Зря бросили первый вариант, были почти у цели:
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from xml.parsers import expat
class Handler():
def __init__(self, parser):
parser.StartElementHandler = self.start_element
parser.CharacterDataHandler = self.char_data
self.key = None
self.slot = None
def start_element(self, name, attr):
if name == 'ro:router':
print '[[router %s]]' % (attr['router_name'])
elif name in ('ro:model', 'ro:image'):
self.key = name[3:]
elif name.startswith('ro:slot'):
self.slot = name[3:]
elif name.startswith('ro:module'):
print '%s=%s' % (self.slot, attr['name_module'])
elif name == 'ro:connect':
print '%s=%s %s' % (attr['name_interface'], attr['target_router'], attr['target_router_interface'])
def char_data(self, data):
if self.key:
print '%s=%s' % (self.key, data.strip())
self.key = None
p = expat.ParserCreate()
handler = Handler(p)
h = open('test.xml','r')
p.ParseFile(h)
h.close
Офлайн
PooHPooH! Спасибо за наводку! =) Вообщем, попробовал разобраться с вариантом через XSLT. Для питона использую библиотеку 4Suite. Исходный .xml файл, который надо отпарсить - в треде выше.
Зря бросили первый вариант, были почти у цели:
Хотя такие маленькие файлы проще было через DOM обрабатывать, ну а самый красивый вариант был бы XSLT
[root@gamma test_socket]# cat stylesheet6.xsl
<xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform'
xmlns:ro='http://mydomain.ru/router' version='1.0'>
<xsl:output method="text" indent="no"/>
<xsl:template match="server">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="ro:router">
[[router <xsl:value-of select="@router_name"/>]]
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="ro:model">
model=<xsl:value-of select="."/>
</xsl:template>
<xsl:template match="ro:image">
image=<xsl:value-of select="."/>
</xsl:template>
<xsl:template match="ro:connect">
<xsl:value-of select="@name_interface"/>=<xsl:value-of select="@target_router"/><xsl:text> </xsl:text><xsl:value-of select="@target_router_interface"/>
</xsl:template>
<xsl:template match="ro:slot0">
slot0=<xsl:call-template name="modules"/>
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="ro:slot1">
slot1=<xsl:call-template name="modules"/>
<xsl:apply-templates/>
</xsl:template>
<xsl:template name="modules">
<xsl:for-each select="ro:module_C7200-IO-2FE">
<xsl:value-of select="@name_module"/>
</xsl:for-each>
<xsl:for-each select="ro:module_PA-FE-TX">
<xsl:value-of select="@name_module"/>
</xsl:for-each>
</xsl:template>
#!/usr/bin/python
# -*- coding:utf-8 -*-
from Ft.Xml.Xslt import Processor
from Ft.Xml import InputSource
from Ft.Lib.Uri import OsPathToUri
processor = Processor.Processor()
srcAsUri = OsPathToUri('/opt/test_socket/example.xml')
source = InputSource.DefaultFactory.fromUri(srcAsUri)
ssAsUri = OsPathToUri('/opt/test_socket/stylesheet.xsl')
transform = InputSource.DefaultFactory.fromUri(ssAsUri)
processor.appendStylesheet(transform)
result = processor.run(source)
print result
[root@gamma test_socket]# python parser3
[[router Router1]]
model=7200
image=http://www.altova.com
slot0=C7200-IO-2FE
f0/0=Router2 f0/0
f0/1=Router3 f0/1
slot1=PA-FE-TX
[[router Router2]]
model=3660
image=http://www.altova.com
f0/0=Router1 f0/0
f0/1=Router3 f0/0
[[router Router3]]
model=7200
image=http://www.altova.com
slot0=C7200-IO-2FE
f0/0=Router2 f0/1
f0/1=Router1 f0/1
Офлайн