С помощью PYTHON конвертировать CSV-файл в XML-файл

#python #xml #csv

#python #xml #csv

Вопрос:

Я хочу преобразовать CSV-файл в XML-файл с помощью Python. Я хочу сгруппировать одинаковые идентификаторы в файле CSV вместе и преобразовать csv в преобразование xml (см. Желаемый вывод). Это немного сложнее, чем кажется с отступами, циклами и группировкой csv в xml. Любая помощь приветствуется.

 My CSV file:

id,x1,y1,z1,x2,y2,z2,c1,R
a1,1.3,2.1,3.6,4.5,5.1,6.8,B,7.3
b2,1.1,2.1,3.1,4.1,5.1,6.1,G,7.1
c1,2.1,3.1,4.1,5.1,2.1,7.1,G,8.1
a1,2.2,3.2,4.2,5.2,6.2,7.2,S,8.2
b2,4.1,5.1,2.1,7.1,8.1,9.1,S,2.5
b2,3.6,4.5,5.1,6.3,7.4,8.2,G,3.1
c2,6.1,7.1,8.1,9.1,2.1,11.1,S,3.2
c1,1.5,1.5,1.5,1.5,1.5,1.5,A,1.5


my code:

import itertools
import csv
import os

csvFile = r'C:UsersDesktoptest XMLcsvfile.csv'
xmlFile = r'C:UsersDesktoptest XMLmyData.xml'

csvData = csv.reader(open(csvFile))
xmlData = open(xmlFile, 'w')
xmlData.write('<?xml version="1.0" encoding="UTF-8"?>'   "n"  '<Roughness-Profiles xmlns="http://WKI/Roughness-Profiles/1">'   "n" )
xmlData.write(' ' '<Roughness-Profile>'   "n")

rowNum = 0
for row in csvData:
    if rowNum == 0:
        tags = row
        # replace spaces w/ underscores in tag names
        for i in range(len(tags)):
            tags[i] = tags[i].replace(' ', '_')
    else: 
        xmlData.write('  ' '<surfaces>'  "n" '   ' '<surface>'   "n")
        for i in range (len(tags)):
            xmlData.write('    '  '<'   tags[i]   '>' 
                        row[i]   '</'   tags[i]   '>'   "n")

        xmlData.write('   ' '</surface>'   "n"   '  ' '</surfaces>'   "n"   ' ' '</Roughness-Profile>'   "n")

    rowNum  =1

xmlData.write('</Roughness-Profiles>'   "n")
xmlData.close()
  

мой вывод XML:

 <?xml version="1.0" encoding="UTF-8"?>
<Roughness-Profiles xmlns="http://WKI/Roughness-Profiles/1">
 <Roughness-Profile>
  <surfaces>
   <surface>
    <id>a1</id>
    <x1>1.3</x1>
    <y1>2.1</y1>
    <z1>3.6</z1>
    <x2>4.5</x2>
    <y2>5.1</y2>
    <z2>6.8</z2>
    <c1>B</c1>
    <R>7.3</R>
   </surface>
  </surfaces>
 </Roughness-Profile>
  <surfaces>
   <surface>
    <id>b2</id>
    <x1>1.1</x1>
    <y1>2.1</y1>
    <z1>3.1</z1>
    <x2>4.1</x2>
    <y2>5.1</y2>
    <z2>6.1</z2>
    <c1>G</c1>
    <R>7.1</R>
   </surface>
  </surfaces>
 </Roughness-Profile>
  <surfaces>
   <surface>
    <id>c1</id>
    <x1>2.1</x1>
    <y1>3.1</y1>
    <z1>4.1</z1>
    <x2>5.1</x2>
    <y2>2.1</y2>
    <z2>7.1</z2>
    <c1>G</c1>
    <R>8.1</R>
   </surface>
  </surfaces>
 </Roughness-Profile>
  <surfaces>
   <surface>
    <id>a1</id>
    <x1>2.2</x1>
    <y1>3.2</y1>
    <z1>4.2</z1>
    <x2>5.2</x2>
    <y2>6.2</y2>
    <z2>7.2</z2>
    <c1>S</c1>
    <R>8.2</R>
   </surface>
  </surfaces>
 </Roughness-Profile>
  <surfaces>
   <surface>
    <id>b2</id>
    <x1>4.1</x1>
    <y1>5.1</y1>
    <z1>2.1</z1>
    <x2>7.1</x2>
    <y2>8.1</y2>
    <z2>9.1</z2>
    <c1>S</c1>
    <R>2.5</R>
   </surface>
  </surfaces>
 </Roughness-Profile>
  <surfaces>
   <surface>
    <id>b2</id>
    <x1>3.6</x1>
    <y1>4.5</y1>
    <z1>5.1</z1>
    <x2>6.3</x2>
    <y2>7.4</y2>
    <z2>8.2</z2>
    <c1>G</c1>
    <R>3.1</R>
   </surface>
  </surfaces>
 </Roughness-Profile>
  <surfaces>
   <surface>
    <id>c2</id>
    <x1>6.1</x1>
    <y1>7.1</y1>
    <z1>8.1</z1>
    <x2>9.1</x2>
    <y2>2.1</y2>
    <z2>11.1</z2>
    <c1>S</c1>
    <R>3.2</R>
   </surface>
  </surfaces>
 </Roughness-Profile>
  <surfaces>
   <surface>
    <id>c1</id>
    <x1>1.5</x1>
    <y1>1.5</y1>
    <z1>1.5</z1>
    <x2>1.5</x2>
    <y2>1.5</y2>
    <z2>1.5</z2>
    <c1>A</c1>
    <R>1.5</R>
   </surface>
  </surfaces>
 </Roughness-Profile>
</Roughness-Profiles>
  

Желаемый результат должен быть:

 <?xml version="1.0" encoding="UTF-8"?>
<R-Profiles xmlns="http://WKI/R-Profiles/1">
 <R-Profile>
  <id>a1</id>
  <surfaces>
   <surface>
    <x1>1.3</x1>
    <y1>2.1</y1>
    <z1>3.6</z1>
    <x2>4.5</x2>
    <y2>5.1</y2>
    <z2>6.8</z2>
    <c1>B</c1>
    <R>7.3</R>
   </surface>
   <surface>
    <x1>2.2</x1>
    <y1>3.2</y1>
    <z1>4.2</z1>
    <x2>5.2</x2>
    <y2>6.2</y2>
    <z2>7.2</z2>
    <c1>S</c1>
    <R>8.2</R>
   </surface>
    </surfaces>
 </R-Profile>
 <R-Profile>
  <id>b2</id>
  <surfaces>
   <surface>
    <x1>1.1</x1>
    <y1>2.1</y1>
    <z1>3.1</z1>
    <x2>4.1</x2>
    <y2>5.1</y2>
    <z2>6.1</z2>
    <c1>G</c1>
    <R>7.1</R>
   </surface>
   <surface>
    <x1>4.1</x1>
    <y1>5.1</y1>
    <z1>2.1</z1>
    <x2>7.1</x2>
    <y2>8.1</y2>
    <z2>9.1</z2>
    <c1>S</c1>
    <R>2.5</R>
   </surface>
   <surface>
    <x1>3.6</x1>
    <y1>4.5</y1>
    <z1>5.1</z1>
    <x2>6.3</x2>
    <y2>7.4</y2>
    <z2>8.2</z2>
    <c1>G</c1>
    <R>3.1</R>
   </surface>
    </surfaces>
 </R-Profile>
 <R-Profile>
  <id>c1</id>
  <surfaces>
   <surface>
    <x1>2.1</x1>
    <y1>3.1</y1>
    <z1>4.1</z1>
    <x2>5.1</x2>
    <y2>2.1</y2>
    <z2>7.1</z2>
    <c1>G</c1>
    <R>8.1</R>
   </surface>
   <surface>
    <x1>1.5</x1>
    <y1>1.5</y1>
    <z1>1.5</z1>
    <x2>1.5</x2>
    <y2>1.5</y2>
    <z2>1.5</z2>
    <c1>A</c1>
    <R>1.5</R>
   </surface>
   </surfaces>
 </R-Profile>
 <R-Profile>
  <id>c2</id>
  <surfaces>
   <surface>
    <x1>6.1</x1>
    <y1>7.1</y1>
    <z1>8.1</z1>
    <x2>9.1</x2>
    <y2>2.1</y2>
    <z2>11.1</z2>
    <c1>S</c1>
    <R>3.2</R>
   </surface>
  </surfaces>
 </R-Profile>
</R-Profiles>
  

Комментарии:

1. сначала прочитайте все строки из CSV и отсортируйте их по id

2. проблема вовсе не в этом. необходимо сгруппировать одинаковые идентификаторы, см. Структуру XML в желаемом выводе

3. группировка не является проблемой

Ответ №1:

Я бы сделал что-то очень похожее на то, что предложил @Parfait; используйте csv.DictReader и lxml для создания XML.

Однако в этом ответе чего-то не хватает; surface элементы не сгруппированы по id .

Если мне нужно сгруппировать XML во время преобразования, первое, о чем я думаю, это XSLT.

Как только вы освоитесь с этим, группировка станет простой с помощью XSLT; особенно 2.0 или выше. К сожалению, lxml поддерживает только XSLT 1.0. В 1.0 вам нужно использовать группировку по-мюнхенски.

Вот полный пример создания промежуточного XML и преобразования его с помощью XSLT.

Ввод CSV (test.csv)

 id,x1,y1,z1,x2,y2,z2,c1,R
a1,1.3,2.1,3.6,4.5,5.1,6.8,B,7.3
b2,1.1,2.1,3.1,4.1,5.1,6.1,G,7.1
c1,2.1,3.1,4.1,5.1,2.1,7.1,G,8.1
a1,2.2,3.2,4.2,5.2,6.2,7.2,S,8.2
b2,4.1,5.1,2.1,7.1,8.1,9.1,S,2.5
b2,3.6,4.5,5.1,6.3,7.4,8.2,G,3.1
c2,6.1,7.1,8.1,9.1,2.1,11.1,S,3.2
c1,1.5,1.5,1.5,1.5,1.5,1.5,A,1.5
  

XSLT 1.0 (test.xsl)

 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:rp="http://WKI/Roughness-Profiles/1">
  <xsl:output indent="yes"/>
  <xsl:strip-space elements="*"/>

  <xsl:key name="surface" match="rp:surface" use="rp:id"/>

  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="/*">
    <xsl:copy>
      <xsl:apply-templates select="@*"/>
      <xsl:for-each select="rp:surface[count(.|key('surface',rp:id)[1])=1]">
        <xsl:element name="Roughness-Profile" namespace="http://WKI/Roughness-Profiles/1">
          <xsl:copy-of select="rp:id"/>
          <xsl:element name="surfaces" namespace="http://WKI/Roughness-Profiles/1">
            <xsl:apply-templates select="key('surface',rp:id)"/>
          </xsl:element>
        </xsl:element>
      </xsl:for-each>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="rp:id"/>

</xsl:stylesheet>
  

Python

 import csv
import lxml.etree as etree

# INITIALIZING XML FILE WITH ROOT IN PROPER NAMESPACE
nsmap = {None: "http://WKI/Roughness-Profiles/1"}
root = etree.Element('Roughness-Profiles', nsmap=nsmap)

# READING CSV FILE
with open("test.csv") as f:
    reader = csv.DictReader(f)

    # WRITE INITIAL XML NODES
    for row in reader:
        surface_elem = etree.SubElement(root, "surface", nsmap=nsmap)
        for elem_name, elem_value in row.items():
            etree.SubElement(surface_elem, elem_name.strip(), nsmap=nsmap).text = str(elem_value)

# PARSE XSLT AND CREATE TRANSFORMER
xslt_root = etree.parse("test.xsl")
transform = etree.XSLT(xslt_root)

# TRANSFORM
#  (Note the weird use of tostring/fromstring. This was used so
#   namespaces in the XSLT would work the way they're supposed to.)
final_xml = transform(etree.fromstring(etree.tostring(root)))

# WRITE OUTPUT TO FILE
final_xml.write_output("test.xml")
  

Вывод XML (test.xml )

 <?xml version="1.0"?>
<Roughness-Profiles xmlns="http://WKI/Roughness-Profiles/1">
  <Roughness-Profile>
    <id>a1</id>
    <surfaces>
      <surface>
        <x1>1.3</x1>
        <y1>2.1</y1>
        <z1>3.6</z1>
        <x2>4.5</x2>
        <y2>5.1</y2>
        <z2>6.8</z2>
        <c1>B</c1>
        <R>7.3</R>
      </surface>
      <surface>
        <x1>2.2</x1>
        <y1>3.2</y1>
        <z1>4.2</z1>
        <x2>5.2</x2>
        <y2>6.2</y2>
        <z2>7.2</z2>
        <c1>S</c1>
        <R>8.2</R>
      </surface>
    </surfaces>
  </Roughness-Profile>
  <Roughness-Profile>
    <id>b2</id>
    <surfaces>
      <surface>
        <x1>1.1</x1>
        <y1>2.1</y1>
        <z1>3.1</z1>
        <x2>4.1</x2>
        <y2>5.1</y2>
        <z2>6.1</z2>
        <c1>G</c1>
        <R>7.1</R>
      </surface>
      <surface>
        <x1>4.1</x1>
        <y1>5.1</y1>
        <z1>2.1</z1>
        <x2>7.1</x2>
        <y2>8.1</y2>
        <z2>9.1</z2>
        <c1>S</c1>
        <R>2.5</R>
      </surface>
      <surface>
        <x1>3.6</x1>
        <y1>4.5</y1>
        <z1>5.1</z1>
        <x2>6.3</x2>
        <y2>7.4</y2>
        <z2>8.2</z2>
        <c1>G</c1>
        <R>3.1</R>
      </surface>
    </surfaces>
  </Roughness-Profile>
  <Roughness-Profile>
    <id>c1</id>
    <surfaces>
      <surface>
        <x1>2.1</x1>
        <y1>3.1</y1>
        <z1>4.1</z1>
        <x2>5.1</x2>
        <y2>2.1</y2>
        <z2>7.1</z2>
        <c1>G</c1>
        <R>8.1</R>
      </surface>
      <surface>
        <x1>1.5</x1>
        <y1>1.5</y1>
        <z1>1.5</z1>
        <x2>1.5</x2>
        <y2>1.5</y2>
        <z2>1.5</z2>
        <c1>A</c1>
        <R>1.5</R>
      </surface>
    </surfaces>
  </Roughness-Profile>
  <Roughness-Profile>
    <id>c2</id>
    <surfaces>
      <surface>
        <x1>6.1</x1>
        <y1>7.1</y1>
        <z1>8.1</z1>
        <x2>9.1</x2>
        <y2>2.1</y2>
        <z2>11.1</z2>
        <c1>S</c1>
        <R>3.2</R>
      </surface>
    </surfaces>
  </Roughness-Profile>
</Roughness-Profiles>
  

Комментарии:

1. Привет, Дэниел, твой совет работает хорошо. Это работает для этого примера файла, но если я запускаю скрипт, я получаю в ‘ строке 16’ ошибку значения: недопустимое имя тега. У вас есть какие-либо идеи, как избавиться от его ошибки?

2. @Ram — это означает, что одно из значений вашего заголовка не может использоваться как есть для имени элемента. Можете ли вы сказать мне, как выглядит первая строка, чтобы я мог предложить исправление?

3. @Ram — все это допустимые имена, если в них нет начальных / конечных пробелов. Я добавил strip() к elem_name в Python ( elem_name.strip() ). Попробуйте и дайте мне знать, устраняет ли это проблему.

4. @Ram — Я также удалил некоторый отладочный код из XSLT. Упс. 🙂

5. кажется, все хорошо, за исключением пары мелочей, я только что заметил, что в первой строке я пропустил ‘ encoding =»UTF-8″? ‘ и следующий — это если запустить скрипт, который я получаю — x1, y2, x2, z2, R, c1, z1, y1. Порядок должен быть — x1, y1, z1, x2, y2, z2, c1, R. Возможно ли определить порядок столбцов путем индексации, я имею в виду, вместо итерации по всем столбцам? и следующий, возможно ли отсортировать «идентификатор»?

Ответ №2:

Сначала прочитайте все строки из CSV и отсортируйте их.

Позже вы сможете использовать переменную previous_id для открытия и закрытия Roughness-Profile / surfaces только тогда, id когда новая строка отличается от предыдущей.

Я использовал StringIO для имитации CSV-файла и sys.stdout для имитации XML-файла — так что каждый может скопировать код и запустить его, чтобы увидеть, как он работает

 text ='''id,x1,y1,z1,x2,y2,z2,c1,R
a1,1.3,2.1,3.6,4.5,5.1,6.8,B,7.3
b2,1.1,2.1,3.1,4.1,5.1,6.1,G,7.1
c1,2.1,3.1,4.1,5.1,2.1,7.1,G,8.1
a1,2.2,3.2,4.2,5.2,6.2,7.2,S,8.2
b2,4.1,5.1,2.1,7.1,8.1,9.1,S,2.5
b2,3.6,4.5,5.1,6.3,7.4,8.2,G,3.1
c2,6.1,7.1,8.1,9.1,2.1,11.1,S,3.2
c1,1.5,1.5,1.5,1.5,1.5,1.5,A,1.5'''

from io import StringIO
import csv
import sys

#csvFile = r'C:UsersDesktoptest XMLcsvfile.csv'
#xmlFile = r'C:UsersDesktoptest XMLmyData.xml'

#csvData = csv.reader(open(csvFile))
#xmlData = open(xmlFile, 'w')

csvData = csv.reader(StringIO(text))
xmlData = sys.stdout

# read all data to sort them
csvData = list(csvData)
tags = [item.replace(' ', '_') for item in csvData[0]] # headers
csvData = sorted(csvData[1:]) # sort data without headers

xmlData.write('<?xml version="1.0" encoding="UTF-8"?>n<Roughness-Profiles xmlns="http://WKI/Roughness-Profiles/1">n')

previous_id = None

for row in csvData:
    row_id = row[0]
    if row_id != previous_id:
        # close previous group - but only if it is not first group
        if previous_id is not None: 
            xmlData.write('</surfaces>n</Roughness-Profile>n')
        # open new group  
        xmlData.write('<Roughness-Profile>n<id>{}</id>n<surfaces>n'.format(row_id))
        # remeber new group's id
        previous_id = row_id

    # surface
    xmlData.write('<surface>n')
    for value, tag in zip(row[1:], tags[1:]): 
        xmlData.write('<{}>{}</{}>n'.format(tag, value, tag))
    xmlData.write('</surface>n')

# close last group
xmlData.write('</surfaces>n</Roughness-Profile>n')
xmlData.write('</Roughness-Profiles>n')

#xmlData.close()
  

Версия без StringIO и sys.stdout

 import csv

csvFile = r'C:UsersDesktoptest XMLcsvfile.csv'
xmlFile = r'C:UsersDesktoptest XMLmyData.xml'

csvData = csv.reader(open(csvFile))
xmlData = open(xmlFile, 'w')

# read all data to sort them
csvData = list(csvData)
tags = [item.replace(' ', '_') for item in csvData[0]] # headers
csvData = sorted(csvData[1:]) # sort data without headers

xmlData.write('<?xml version="1.0" encoding="UTF-8"?>n<Roughness-Profiles xmlns="http://WKI/Roughness-Profiles/1">n')

previous_id = None

for row in csvData:
    row_id = row[0]
    if row_id != previous_id:
        # close previous group - but only if it is not first group
        if previous_id is not None: 
            xmlData.write('</surfaces>n</Roughness-Profile>n')
        # open new group  
        xmlData.write('<Roughness-Profile>n<id>{}</id>n<surfaces>n'.format(row_id))
        # remeber new group's id
        previous_id = row_id

    # surface
    xmlData.write('<surface>n')
    for value, tag in zip(row[1:], tags[1:]): 
        xmlData.write('<{}>{}</{}>n'.format(tag, value, tag))
    xmlData.write('</surface>n')

# close last group
xmlData.write('</surfaces>n</Roughness-Profile>n')
xmlData.write('</Roughness-Profiles>n')

xmlData.close()
  

Комментарии:

1. Привет, Фурас, сначала я не понимаю ваш StringIO и sys.stdout. объясните это дальше, чтобы я мог следовать. Я запустил скрипт без строк StringIO и sys.stdout. Все данные приведены в желаемом порядке, но в выходных данных отсутствует необходимый синтаксический анализ XML.

2. Первое: не используйте StringIO и sys.stdout — используйте ваши файлы. Я использовал StringIO и sys.stdout, потому что у меня нет вашего файла, и мне пришлось его сравнивать. А с помощью StringIO и sys.stdout другие пользователи могут запустить этот код и посмотреть, как он работает — им не нужен ваш файл с данными.

3. теперь я вижу, что забыл закрыть ‘</Roughness-Profiles>’. Я добавляю его сейчас. Остальное кажется таким же. Я использовал program meld , чтобы сравнить ваш результат с моим.

4. Я добавил его до того, как написал предыдущий комментарий.

5. @Furas- вывод XML через ваш скрипт хорош. У меня не было проблем при загрузке xml в модуль., Еще раз спасибо.

Ответ №3:

Поскольку XML-файлы — это не текстовые файлы, а специальные текстовые документы со структурированными данными, соответствующие спецификациям W3C, что позволяет избежать создания документа путем конкатенации строк.

Вместо этого используйте соответствующие библиотеки DOM, доступные практически на всех современных языках программирования, включая Python со встроенным xml.etree или более надежным сторонним модулем lxml . Фактически, поскольку желаемый результат включает группировку узлов по идентификатору, рассмотрите возможность запуска XSLT, языка специального назначения, предназначенного для преобразования XML-файлов. Модуль lxml может запускать скрипты XSLT 1.0.

Ниже используется DictReader встроенный csv модуль для построения вложенного словаря идентификаторов (все столбцы сгруппированы по ключам идентификаторов). Затем XML создается путем перебора содержимого этого словаря для записи данных в узлы элементов.

 import csv
from collections import OrderedDict
import lxml.etree as ET

# BUILD NESTED ID DICTIONARY FROM CSV
with open("Input.csv") as f:
    reader = csv.DictReader(f)      

    id_dct = OrderedDict({})
    for dct in reader:      
        if dct["id"] not in id_dct.keys():
            id_dct[dct["id"]] = [OrderedDict({k:v for k,v in dct.items() if k!= "id"})]
        else:
            id_dct[dct["id"]].append(OrderedDict({k:v for k,v in dct.items() if k!= "id"}))         

# INITIALIZING XML FILE WITH ROOT AND NAMESPACE
root = ET.Element('R-Profiles', nsmap={None: "http://WKI/Roughness-Profiles/1"})

# WRITING TO XML NODES
for k,v in id_dct.items():  
    rpNode = ET.SubElement(root, "R-Profile")
    ET.SubElement(rpNode, "id").text = str(k)
    surfacesNode = ET.SubElement(rpNode, "surfaces")

    for dct in v:
        surfaceNode = ET.SubElement(surfacesNode, "surface")
        for k,v in dct.items():         
            ET.SubElement(surfaceNode, k).text = str(v)

# OUTPUT XML CONTENT TO FILE
tree_out = ET.tostring(root, pretty_print=True, xml_declaration=True, encoding="UTF-8")

with open('Output.xml','wb') as f:
    f.write(tree_out)
  

Ввод.csv

 id,x1,y1,z1,x2,y2,z2,c1,R
a1,1.3,2.1,3.6,4.5,5.1,6.8,B,7.3
b2,1.1,2.1,3.1,4.1,5.1,6.1,G,7.1
c1,2.1,3.1,4.1,5.1,2.1,7.1,G,8.1
a1,2.2,3.2,4.2,5.2,6.2,7.2,S,8.2
b2,4.1,5.1,2.1,7.1,8.1,9.1,S,2.5
b2,3.6,4.5,5.1,6.3,7.4,8.2,G,3.1
c2,6.1,7.1,8.1,9.1,2.1,11.1,S,3.2
c1,1.5,1.5,1.5,1.5,1.5,1.5,A,1.5
  

Output.xml

 <?xml version='1.0' encoding='UTF-8'?>
<R-Profiles xmlns="http://WKI/Roughness-Profiles/1">
  <R-Profile>
    <id>a1</id>
    <surfaces>
      <surface>
        <x1>1.3</x1>
        <y1>2.1</y1>
        <z1>3.6</z1>
        <x2>4.5</x2>
        <y2>5.1</y2>
        <z2>6.8</z2>
        <c1>B</c1>
        <R>7.3</R>
      </surface>
      <surface>
        <x1>2.2</x1>
        <y1>3.2</y1>
        <z1>4.2</z1>
        <x2>5.2</x2>
        <y2>6.2</y2>
        <z2>7.2</z2>
        <c1>S</c1>
        <R>8.2</R>
      </surface>
    </surfaces>
  </R-Profile>
  <R-Profile>
    <id>b2</id>
    <surfaces>
      <surface>
        <x1>1.1</x1>
        <y1>2.1</y1>
        <z1>3.1</z1>
        <x2>4.1</x2>
        <y2>5.1</y2>
        <z2>6.1</z2>
        <c1>G</c1>
        <R>7.1</R>
      </surface>
      <surface>
        <x1>4.1</x1>
        <y1>5.1</y1>
        <z1>2.1</z1>
        <x2>7.1</x2>
        <y2>8.1</y2>
        <z2>9.1</z2>
        <c1>S</c1>
        <R>2.5</R>
      </surface>
      <surface>
        <x1>3.6</x1>
        <y1>4.5</y1>
        <z1>5.1</z1>
        <x2>6.3</x2>
        <y2>7.4</y2>
        <z2>8.2</z2>
        <c1>G</c1>
        <R>3.1</R>
      </surface>
    </surfaces>
  </R-Profile>
  <R-Profile>
    <id>c1</id>
    <surfaces>
      <surface>
        <x1>2.1</x1>
        <y1>3.1</y1>
        <z1>4.1</z1>
        <x2>5.1</x2>
        <y2>2.1</y2>
        <z2>7.1</z2>
        <c1>G</c1>
        <R>8.1</R>
      </surface>
      <surface>
        <x1>1.5</x1>
        <y1>1.5</y1>
        <z1>1.5</z1>
        <x2>1.5</x2>
        <y2>1.5</y2>
        <z2>1.5</z2>
        <c1>A</c1>
        <R>1.5</R>
      </surface>
    </surfaces>
  </R-Profile>
  <R-Profile>
    <id>c2</id>
    <surfaces>
      <surface>
        <x1>6.1</x1>
        <y1>7.1</y1>
        <z1>8.1</z1>
        <x2>9.1</x2>
        <y2>2.1</y2>
        <z2>11.1</z2>
        <c1>S</c1>
        <R>3.2</R>
      </surface>
    </surfaces>
  </R-Profile>
</R-Profiles>
  

Комментарии:

1. Спасибо, Парфе, в выходном файле «идентификатор» указан не в том месте.

2. Я неправильно истолковал ваш фактический результат для желаемого результата. См. раздел редактирование создание словаря идентификаторов и перебор его содержимого.

3. @Parafait, спасибо за совет, можете ли вы изменить сценарий, чтобы я мог лучше понимать.

4. @Ram, что еще тебе нужно? Я включаю встроенные комментарии.

5. @Parafiat, еще раз спасибо. Все основные вещи кажутся хорошими, за исключением пары мелочей. элементы поверхности не в порядке, если запустить скрипт, который я получаю — x1, y2, x2, z2, R, c1, z1, y1. Порядок должен быть — x1, y1, z1, x2, y2, z2, c1, R. Возможно ли определить порядок столбцов вместо итерации по всем столбцам? и следующий, возможно ли отсортировать «идентификатор»?