Форум программистов, компьютерный форум, киберфорум
Наши страницы
Python
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.79/14: Рейтинг темы: голосов - 14, средняя оценка - 4.79
MonaxGT
Эксперт по компьютерным сетям
275 / 275 / 25
Регистрация: 02.08.2012
Сообщений: 1,219
1

Как из строк csv-файла сделать xml-файлы?

02.08.2013, 15:19. Просмотров 2679. Ответов 17
Метки нет (Все метки)

Добрый день. Столкнулся в проблемой парсинга csv файла и созданием конфигурационных файлов по данным таблицы. Я написал небольшой код. Программа берет csv файл и разбирает его по делителям. Выписывает в консоль и в файл построчно данные. Необходимо чтобы программа либо генерировала новый конфиг ( шаблон уже готов и есть переменные, которые в зависимости от строки менялись) или парсила уже готовый шаблон и вставляла в нужное место нужное значение. Затруднение в том, что программа выдает данные построчно:

Код
1, 2, IF-MIB::ifDescr.51 = STRING: GigabitEthernet6/0/40, 192.33.73.124/24
необходимо чтобы из первого и второго собирался HOSTNAME, из остальных так же собирался IP адрес и т.п. и вставлялся в определенные места шаблона. Побывал разные способ, читал мануал http://docs.python.org/2/library/csv.html , но не могу найти как решить проблему. Прошу помощи у спецов)

Шаблон в который вставлять ( генерировать) выглядит так :
Кликните здесь для просмотра всего текста
XML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
<?xml version="1.0" encoding="UTF-8"?>
<zabbix_export>
    <version>2.0</version>
    <date>2013-07-31T11:56:38Z</date>
    <groups>
        <group>
            <name>Object</name>
        </group>
    </groups>
    <hosts>
        <host>
            <host>HOSTNAME</host>
            <name>HOSTNAME</name>
            <proxy/>
            <status>0</status>
            <ipmi_authtype>-1</ipmi_authtype>
            <ipmi_privilege>2</ipmi_privilege>
            <ipmi_username/>
            <ipmi_password/>
            <templates>
                <template>
                    <name>Template PING </name>
                </template>
            </templates>
            <groups>
                <group>
                    <name>Object</name>
                </group>
            </groups>
            <interfaces>
                <interface>
                    <default>1</default>
                    <type>2</type>
                    <useip>1</useip>
                    <ip>192.33.73.124</ip>
                    <dns/>
                    <port>161</port>
                    <interface_ref>if1</interface_ref>
                </interface>
            </interfaces>
            <applications/>
            <items/>
            <discovery_rules/>
            <macros/>
            <inventory/>
        </host>
    </hosts>
</zabbix_export>


Код программы, которую я написал:
Кликните здесь для просмотра всего текста
Python
1
2
3
4
5
6
7
8
9
10
# -*- coding: utf-8 -*-
import csv
i = 0
with open ('csv.csv') as csvfile:
    finder = csv.reader (csvfile, delimiter = ',', quotechar =  ';')
    for row in finder :
        file = open("test"+str(i)+".xml", "w")
        i = i +1
        print ', '.join(row)
    file.close()
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
02.08.2013, 15:19
Ответы с готовыми решениями:

Парсинг xml-файла(размером в 14,6 млн строк) lxml парсером
в общем вот здесь выкладываю архивированную базу данных в xml формате...

Как импортировать в sql несколько разных таблиц из одного csv файла?
Привет, иметься ситуация когда есть одни файл формата csv, в нем находиться...

CSV файлы
Добрый день уважаемые форумчан) Недавно начала писать диплом для защиты...

Удалить дубликаты, перед этим объединив csv файлы
Есть csv файлы, пусть будет три штуки, пот 20 тыщ строк, каждая строка содержит...

Фильтрация строк в csv файле
Прошу помощи в реализации нужно удалить строки из csv содержащие определенные...

17
accept
4833 / 3255 / 455
Регистрация: 10.12.2008
Сообщений: 10,569
03.08.2013, 07:44 2
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
>>> template = """
... 
... <?xml version="1.0" encoding="UTF-8"?>
... <tag>
...     <inner>{0} {1} {0} {1}</inner>
... <tag>
... 
... """
>>> 
>>> print(template.format('value', 10))
 
 
<?xml version="1.0" encoding="UTF-8"?>
<tag>
    <inner>value 10 value 10</inner>
<tag>
 
 
>>>
вообще, xml-файлы делаются через модуль xml
python.org. xml. modifying
1
MonaxGT
Эксперт по компьютерным сетям
275 / 275 / 25
Регистрация: 02.08.2012
Сообщений: 1,219
03.08.2013, 10:24  [ТС] 3
Прощу прощения, но не могли бы Вы пояснить что Вы сделали?
Я прочитал Вашу ссылку, но так ответ на свой вопрос я не нашел...
0
accept
4833 / 3255 / 455
Регистрация: 10.12.2008
Сообщений: 10,569
03.08.2013, 10:42 4
Цитата Сообщение от MonaxGT Посмотреть сообщение
Я прочитал Вашу ссылку, но так ответ на свой вопрос я не нашел...
сформулируй задачу
приведи файл, который у тебя есть
приведи файл, который должен получиться

в твоём коде есть чтение csv-файла, но нет правильного выделения данных и правильной записи их в новый файл

Цитата Сообщение от MonaxGT Посмотреть сообщение
Прощу прощения, но не могли бы Вы пояснить что Вы сделали?
сделал текстовый шаблон, в который подставляются данные в заданные места
0
MonaxGT
Эксперт по компьютерным сетям
275 / 275 / 25
Регистрация: 02.08.2012
Сообщений: 1,219
03.08.2013, 12:22  [ТС] 5
Выше я все описал. Но да ладно, еще раз могу, может более внятно получится.

Есть файл csv в нем расположены построчно данные по каждому объекту (host'у). Выглядит он так :
Код
1, 2, IF-MIB::ifDescr.51 = STRING: GigabitEthernet6/0/40, 192.168.1.1/24
2, 3, IF-MIB::ifDescr.53 = STRING: GigabitEthernet6/0/5, 192.168.1.2/24
3, 21, IF-MIB::ifDescr.21 = STRING: GigabitEthernet6/0/44, 192.168.1.3/24
4, 24, IF-MIB::ifDescr.11 = STRING: GigabitEthernet6/0/12, 192.168.1.4/24
Первые 2 поля ( которые разделенны знаком "," ) формируют значение (переменную) HOSTNAME. Например HOSTNAME для первого объекта равен "1-Object-2-Group".

Далее 3е поле временно учитывать не будем.
4ое поле где в первом случае 192.168.1.1/24, отбрасывается /24, остается 192.168.1.1 и записывается в переменную IPADDRESS.

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

Кликните здесь для просмотра всего текста
XML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
<?xml version="1.0" encoding="UTF-8"?>
<zabbix_export>
    <version>2.0</version>
    <date>2013-07-31T11:56:38Z</date>
    <groups>
        <group>
            <name>Object</name>
        </group>
    </groups>
    <hosts>
        <host>
            <host>HOSTNAME</host>
            <name>HOSTNAME</name>
            <proxy/>
            <status>0</status>
            <ipmi_authtype>-1</ipmi_authtype>
            <ipmi_privilege>2</ipmi_privilege>
            <ipmi_username/>
            <ipmi_password/>
            <templates>
                <template>
                    <name>Template PING </name>
                </template>
            </templates>
            <groups>
                <group>
                    <name>Object</name>
                </group>
            </groups>
            <interfaces>
                <interface>
                    <default>1</default>
                    <type>2</type>
                    <useip>1</useip>
                    <ip>IPADDRESS</ip>
                    <dns/>
                    <port>161</port>
                    <interface_ref>if1</interface_ref>
                </interface>
            </interfaces>
            <applications/>
            <items/>
            <discovery_rules/>
            <macros/>
            <inventory/>
        </host>
    </hosts>
</zabbix_export>


После выполнения программы создаются 4 файла (для данного случая), где первый файл-шаблон будет выглядеть так :
Кликните здесь для просмотра всего текста
XML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
<?xml version="1.0" encoding="UTF-8"?>
<zabbix_export>
    <version>2.0</version>
    <date>2013-07-31T11:56:38Z</date>
    <groups>
        <group>
            <name>Object</name>
        </group>
    </groups>
    <hosts>
        <host>
            <host>1-Object-2-Group</host>
            <name>1-Object-2-Group</name>
            <proxy/>
            <status>0</status>
            <ipmi_authtype>-1</ipmi_authtype>
            <ipmi_privilege>2</ipmi_privilege>
            <ipmi_username/>
            <ipmi_password/>
            <templates>
                <template>
                    <name>Template PING </name>
                </template>
            </templates>
            <groups>
                <group>
                    <name>Object</name>
                </group>
            </groups>
            <interfaces>
                <interface>
                    <default>1</default>
                    <type>2</type>
                    <useip>1</useip>
                    <ip>192.168.1.1</ip>
                    <dns/>
                    <port>161</port>
                    <interface_ref>if1</interface_ref>
                </interface>
            </interfaces>
            <applications/>
            <items/>
            <discovery_rules/>
            <macros/>
            <inventory/>
        </host>
    </hosts>
</zabbix_export>


Последующие будут создаваться по аналогии.

Трудность заключается в том, что я не знаю как разобрать строчку csv-файла на переменные HOSTNAME, IPADDRESS. Я могу только создать xml файл и вставить в него тупо строчку.
0
fanatdebian
Z3JheSBoYXQ=
339 / 234 / 83
Регистрация: 08.07.2012
Сообщений: 577
03.08.2013, 19:33 6
Python
1
2
3
4
5
6
7
8
9
>>> msg
'1, 2, IF-MIB::ifDescr.51 = STRING: GigabitEthernet6/0/40, 192.168.1.1/24'
>>> hostname=msg.split(',')[0].strip()+'-Object-'+msg.split(',')[1].strip()+'-Group'
>>> hostname
'1-Object-2-Group'
>>> ipaddress = msg.split(',')[3].split('/')[0].strip()
>>> ipaddress
'192.168.1.1'
>>>
1
accept
4833 / 3255 / 455
Регистрация: 10.12.2008
Сообщений: 10,569
03.08.2013, 20:35 7
Код
[guest@localhost csvxml]$ ./csvxml.py 
ok
[guest@localhost csvxml]$
Кликните здесь для просмотра всего текста
Код
[guest@localhost csvxml]$ cat file.csv output0.xml 
1, 2, IF-MIB::ifDescr.51 = STRING: GigabitEthernet6/0/40, 192.168.1.1/24
2, 3, IF-MIB::ifDescr.53 = STRING: GigabitEthernet6/0/5, 192.168.1.2/24
3, 21, IF-MIB::ifDescr.21 = STRING: GigabitEthernet6/0/44, 192.168.1.3/24
4, 24, IF-MIB::ifDescr.11 = STRING: GigabitEthernet6/0/12, 192.168.1.4/24
<?xml version="1.0" encoding="UTF-8"?>
<zabbix_export>
    <version>2.0</version>
    <date>2013-07-31T11:56:38Z</date>
    <groups>
        <group>
            <name>Object</name>
        </group>
    </groups>
    <hosts>
        <host>
            <host>1-Object-2-Group</host>
            <name>1-Object-2-Group</name>
            <proxy/>
            <status>0</status>
            <ipmi_authtype>-1</ipmi_authtype>
            <ipmi_privilege>2</ipmi_privilege>
            <ipmi_username/>
            <ipmi_password/>
            <templates>
                <template>
                    <name>Template PING </name>
                </template>
            </templates>
            <groups>
                <group>
                    <name>Object</name>
                </group>
            </groups>
            <interfaces>
                <interface>
                    <default>1</default>
                    <type>2</type>
                    <useip>1</useip>
                    <ip>192.168.1.1</ip>
                    <dns/>
                    <port>161</port>
                    <interface_ref>if1</interface_ref>
                </interface>
            </interfaces>
            <applications/>
            <items/>
            <discovery_rules/>
            <macros/>
            <inventory/>
        </host>
    </hosts>
</zabbix_export>
[guest@localhost csvxml]$
1
Вложения
Тип файла: zip csvxml.zip (3.6 Кб, 11 просмотров)
MonaxGT
Эксперт по компьютерным сетям
275 / 275 / 25
Регистрация: 02.08.2012
Сообщений: 1,219
04.08.2013, 17:21  [ТС] 8
Спасибо большое, завтра утром прочитаю и разберусь.

Добавлено через 16 часов 41 минуту
Прошу меня простить за мою глупость но я правильно понял?

Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
hostfmt = '{0}-Object-{1}-Group' # {0} - это как бы ссылка?
ifname = 'file.csv'
ofnamefmt = 'output{}.xml'
 
with open('file.csv', encoding='utf-8') as csvfile:
    filen = 0 # "счетчик созданных файлов-шаблон"
    for row in csv.reader(csvfile): # перебираем строчки в файле csv
        row = [i.strip() for i in row] # переменная row принимает значение i.strip (), где i элемент в строчке ? - Не совсем понял
        host = hostfmt.format(row[0], row[1]) # переменная host принимает значение 1 и 2ого элемента в строчке и вставляет в ссылку шаблона переменной hostfmt
        ip = row[3].partition('/')[0] # переменная ip принимает значение 3его элемента до разделителя "/" ?
        ofname = ofnamefmt.format(filen) 
        with open(ofname, 'w', encoding='utf-8') as fout:
            print(template.format(hostname=host, ipaddress=ip), file=fout) # передает переменные в ссылки в xml шаблоне
        filen += 1
print('ok')
0
accept
4833 / 3255 / 455
Регистрация: 10.12.2008
Сообщений: 10,569
04.08.2013, 21:54 9
Цитата Сообщение от MonaxGT Посмотреть сообщение
{0} - это как бы ссылка?
{0} - это поле замены
любая строка - это объект класса str, у объекта есть свойства и методы
один из методов строки - .format()
когда он вызывается с аргументами, он начинает искать поля замены в строке и вставляет вместо них свои аргументы, а затем возвращает получившуюся строку

Цитата Сообщение от MonaxGT Посмотреть сообщение
переменная row принимает значение i.strip (), где i элемент в строчке ? - Не совсем понял
это включение (comprehension), оно для каждого элемента в ряде - списке строк - выполняет метод строки .strip() и составляет новый список, который присваивается ряду
из каждой строки в row удаляются пробельные символы по краям

Цитата Сообщение от MonaxGT Посмотреть сообщение
переменная host принимает значение 1 и 2ого элемента в строчке и вставляет в ссылку шаблона переменной hostfmt
у строки hostfmt вызывается метод .format() с аргументами
когда новая строка сформирована, она присваивается переменной host

Цитата Сообщение от MonaxGT Посмотреть сообщение
переменная ip принимает значение 3его элемента до разделителя "/" ?
четвёртого
1
MonaxGT
Эксперт по компьютерным сетям
275 / 275 / 25
Регистрация: 02.08.2012
Сообщений: 1,219
04.08.2013, 23:32  [ТС] 10
В принципе понял.

... когда он вызывается с аргументами, он начинает искать поля замены в строке и вставляет вместо них свои аргументы, а затем возвращает получившуюся строку
А как понимает, что row[1] это первое поле, row [2] второе? Это заложено в методе .format() ?
0
accept
4833 / 3255 / 455
Регистрация: 10.12.2008
Сообщений: 10,569
04.08.2013, 23:37 11
Цитата Сообщение от MonaxGT Посмотреть сообщение
А как понимает, что row[1] это первое поле, row [2] второе?
это не первое и второе, а второе и третье
первое поле - это row[0]
функция csv.reader() модуля csv уже разделила строку csv-файла на поля
1
MonaxGT
Эксперт по компьютерным сетям
275 / 275 / 25
Регистрация: 02.08.2012
Сообщений: 1,219
05.08.2013, 00:01  [ТС] 12
Все, понял. Спасибо большое Вам!
0
MonaxGT
Эксперт по компьютерным сетям
275 / 275 / 25
Регистрация: 02.08.2012
Сообщений: 1,219
16.08.2013, 12:33  [ТС] 13
Добрый день accept,
Сегодня руки дорвались до программы, запустил, он ругается на строчку

Python
1
print(template.format(hostname = host, ipad = ip), file=fout)
Код
>python -u "csvxml.py"
  File "csvxml.py", line 68
    print(template.format( hostname = host, ipad = ipad), file=fout)
                                                 ^
SyntaxError: invalid syntax
0
accept
4833 / 3255 / 455
Регистрация: 10.12.2008
Сообщений: 10,569
17.08.2013, 01:23 14
Цитата Сообщение от MonaxGT Посмотреть сообщение
он ругается на строчку
у меня эта строка написана без пробелов (не принято там пробелы писать)
поэтому что запускаешь, то сюда и копируй в точности
1
MonaxGT
Эксперт по компьютерным сетям
275 / 275 / 25
Регистрация: 02.08.2012
Сообщений: 1,219
18.08.2013, 15:53  [ТС] 15
Окей, я заменил по своему без with, все заработало.

А такой вопрос:
Есть переменная которая хранит строку "192.168.1.0", в новой строчке она может быть "192.168.2.0" ( это не особо важно)
Мы делаем программу, которая создает конфиг для например первых пяти Ip-адресов, то есть изменяется только последнее поле.

Как я решил данную проблему:
Python
1
2
3
4
5
a = '192.168.1.1'
b = a.split('.')
c = b[3]
d = int(b[3])+1
e = str(b[0])+'.'+ str(b[1])+'.'+str(b[2])+'.'+str(d)
На выходе то что нужно. Мне кажется этот способ - способом через попу, как сделать данную операцию правильной?
0
accept
4833 / 3255 / 455
Регистрация: 10.12.2008
Сообщений: 10,569
18.08.2013, 18:53 16
Цитата Сообщение от MonaxGT Посмотреть сообщение
Окей, я заменил по своему без with, все заработало.
что значит без with ? он там не просто так

Цитата Сообщение от MonaxGT Посмотреть сообщение
как сделать данную операцию правильной?
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
>>> a = '192.168.1.1'
>>> 
>>> def incoctet(ip, n):
...     assert 1 <= n <= 4
...     octets = [int(o) for o in ip.split('.')]
...     octets[n - 1] += 1
...     return '.'.join(map(str, octets))
... 
>>> incoctet(a, 1)
'193.168.1.1'
>>> incoctet(a, 2)
'192.169.1.1'
>>> incoctet(a, 3)
'192.168.2.1'
>>> incoctet(a, 4)
'192.168.1.2'
>>>
более общая
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
>>> a = '192.168.1.1'
>>> 
>>> def sumoctet(ip, on, num):
...     assert 1 <= on <= 4
...     octets = [int(o) for o in ip.split('.')]
...     octets[on - 1] += num
...     return '.'.join(map(str, octets))
... 
>>> sumoctet(a, 1, 1)
'193.168.1.1'
>>> sumoctet(a, 2, 1)
'192.169.1.1'
>>> sumoctet(a, 3, 1)
'192.168.2.1'
>>> sumoctet(a, 4, 1)
'192.168.1.2'
>>>

за переполнением(границами) октетов следишь до вызова
1
MonaxGT
Эксперт по компьютерным сетям
275 / 275 / 25
Регистрация: 02.08.2012
Сообщений: 1,219
18.08.2013, 22:36  [ТС] 17
За тупость простите, но не могу понять зачем:

Python
1
return '.'.join(map(str, octets))
мы возвращаем разделитель а после него "прицепляем" map(str,octets).
Я прочитал про функцию map, как я понял она просто применяет аргумент к значению. В octets должен лежать список, так если мы возвращаем такое значение, почему у нас не получается на выходе ".192.168.1.1' ?
0
accept
4833 / 3255 / 455
Регистрация: 10.12.2008
Сообщений: 10,569
19.08.2013, 07:51 18
Цитата Сообщение от MonaxGT Посмотреть сообщение
мы возвращаем разделитель а после него "прицепляем" map(str,octets).
каждая строка является объектом класса str, у объектов есть свойства и методы
метод .join() - метод любой строки, он принимает набор строк и объединяет их, вставляя строку (у которой вызывается метод) между ними

набери
Python
1
help(''.join)
в octets находятся числа, их нужно сначала сделать строками, поэтому map() каждое число делает строкой

функция
принимает строку
разделяет её на строки
превращает строки в числа
проводит операции с числами
превращает числа в строки
объединяет строки в строку
возвращает строку
1
19.08.2013, 07:51
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
19.08.2013, 07:51

Экранировать символы перевода строк в csv
Как сделать, чтобы символы перевода строк внутри полей были экранированы при...

Конвертация файла XML в CSV
Всем привет) я новенький в мире программирования и тут поставилась такая...

Как правильно сделать загрузку из csv файла в таблицу (WPF MVVM)
вот заготовка using System; using System.Collections.Generic; using...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
18
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru