Разделение XML-файла на несколько по заданным тегам

Я хочу разделить файл XML на несколько файлов. Моя рабочая станция очень ограничена Eclipse Mars с Xalan 2.7.1.

Я также могу использовать Python, но никогда не использовал его раньше.

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <row>
        <NAME>Doe</NAME>
        <FIRSTNAME>Jon</FIRSTNAME>
        <GENDER>M</GENDER>
    </row>
    <row>
        <NAME>Mustermann</NAME>
        <FIRSTNAME>Max</FIRSTNAME>
        <GENDER>M</GENDER>
    </row>
</root>

Как я могу преобразовать их, чтобы они выглядели так

<?xml version="1.0" encoding="UTF-8"?>
    <root>
        <row>
            <NAME>Doe</NAME>
            <FIRSTNAME>Jon</FIRSTNAME>
            <GENDER>M</GENDER>
        </row>
    </root>

Мне нужны все данные "строки" в одном файле с заголовком. Приведенные выше данные являются лишь примером. Большая часть «строчных» данных имеет 16 атрибутов, но время от времени они меняются.


person Roger Sánchez    schedule 22.03.2016    source источник
comment
Вы делаете разделение в java или python?   -  person vtd-xml-author    schedule 06.05.2016


Ответы (3)


Используйте Python ElementTree.

Создайте файл, например. xmlsplitter.py. Добавьте приведенный ниже код (где file.xml — это ваш XML-файл, при условии, что каждая строка имеет уникальный элемент NAME).

import xml.etree.ElementTree as ET
context = ET.iterparse('file.xml', events=('end', ))
for event, elem in context:
    if elem.tag == 'row':
        title = elem.find('NAME').text
        filename = format(title + ".xml")
        with open(filename, 'wb') as f:
            f.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
            f.write(ET.tostring(elem))

Запустите его с

python xmlsplitter.py

Или, если имена не уникальны:

import xml.etree.ElementTree as ET
context = ET.iterparse('file.xml', events=('end', ))
index = 0
for event, elem in context:
    if elem.tag == 'row':
        index += 1
        filename = format(str(index) + ".xml")
        with open(filename, 'wb') as f:
            f.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
            f.write(ET.tostring(elem))
person Dan-Dev    schedule 22.03.2016
comment
Спасибо, Дэн-Дев, я немного отредактировал ваш код и добавил корневой тег. Еще один вопрос: как я могу добавить .xml к выходным файлам? - person Roger Sánchez; 22.03.2016
comment
Я отредактировал его минуту назад, теперь он гласит: имя файла = формат (название + .xml). Это должно добавить расширение файла .xml к вашим файлам, если вы снова запустите его с отредактированным кодом. - person Dan-Dev; 22.03.2016
comment
Ладно, еще одна проблема. Некоторые NAME встречаются более одного раза. Можно ли перебирать имя выходного файла, начиная, например, с. 1.xml? - person Roger Sánchez; 22.03.2016
comment
Отредактировано добавление кода после Или, если имена не уникальны: - person Dan-Dev; 22.03.2016

Это код, который работает идеально.

import xml.etree.ElementTree as ET

context = ET.iterparse('filname.xml', events=('end', ))
for event, elem in context:
if elem.tag == 'row':
    title = elem.find('NAME').text
    filename = format(title + ".xml")
    with open(filename, 'wb') as f:
        f.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
        f.write("<root>\n")
        f.write(ET.tostring(elem))
        f.write("</root>")
person Roger Sánchez    schedule 22.03.2016
comment
Похоже, что в Python3 вам нужно написать такую ​​строку f.write(b‹root›\n) отметить букву b перед ‹root›\n - person Rafał Pydyniak; 06.03.2017

Существует отличный инструмент http://xmlstar.sourceforge.net/docs.php, который может выполнять много с xml (однако это не pythonic).

Учитывая, что у вас есть файл 1.xml с данными, как указано выше. И вам нужно разбить его на отдельные файлы с именами NNN.xml с элементом /root/row.

Просто вызовите в оболочке:

    $ for ((i=1; i<=`xmlstarlet sel -t -v 'count(/root/row)'  1.xml`; i++)); do \
          echo '<?xml version="1.0" encoding="UTF-8"?><root>' > NAME.xml;
          NAME=$(xmlstarlet sel -t -m '/root/row[position()='$i']' -v './NAME' 1.xml); \
          xmlstarlet sel -t -m '/root/row[position()='$i']' -c . -n 1.xml >> $NAME.xml; \
          echo '</root>' >> NAME.xml
       done

Теперь у вас есть куча XML-файлов, таких как Joe.xml.

person Eugene Lisitsky    schedule 22.03.2016