Текстовые строки новообращенного к XML

У меня есть текстовая строка, подобная той ниже:

statistics:
    time-started: Tue Feb  5 15:33:35 2013
    time-sampled: Thu Feb  7 12:25:39 2013
    statistic:
        active: 0
        interactive: 0
    count: 0
    up:
        packets: 0
        bytes: 0
    down:
        packets: 0
        bytes: 0

Я должен разобрать последовательности, такие как та выше (последовательности, которые я должен разобрать, на самом деле намного большие/более глубокие, здесь я просто обеспечил пример). Самым легким способом разобрать некоторые элементы, я думаю, была бы <сильному> новообращенному эта последовательность к последовательности xml и использование xml.etree. ElementTree , чтобы выбрать элемент я ищу.

Таким образом, я хотел бы преобразовать последовательность выше в последовательность xml как та ниже:


    Tue Feb  5 15:33:35 2013
    Thu Feb  7 12:25:39 2013
    
        0
        0
    
    0
    
        0
        0
    
    
        0
        0
    

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

0
nl ja de
@isedev, именно поэтому я надеялся, что будет модуль, доступный, который может сделать это!
добавлено автор theAlse, источник
Работа you' ll сделать, чтобы преобразовать в XML, вероятно, будет достаточно, чтобы интерпретировать последовательность непосредственно: необходимо разобрать последовательность, чтобы преобразовать в XML, и затем вы хотите разобрать XML, чтобы получить доступ к ценностям, но you' у ll есть ценности однажды you' ve разобрал последовательность:)
добавлено автор isedev, источник

2 ответы

Вы в основном пытаетесь преобразовать YAML в XML. Можно использовать PyYAML для парсинга входной строки питону dict и затем использовать xml генератор, чтобы преобразовать dict в XML.

2
добавлено
есть двойные признаки во внутренней части дерева. PyYAML будет работать или нет? (как признаки пакетов выше)
добавлено автор theAlse, источник
@user2050283, может вы обеспечивать пример или связь с обучающей программой питона о том, как использовать PyYAML.
добавлено автор theAlse, источник
@user2050283, я использовал PyYAML, и это работало как очарование над моим unittest, но управление им для реального, я заметил, что есть на самом деле некоторые, наклеивает тот же самый уровень с тем же самым именем и так как PyYaml, кажется, использует Dic, только последняя стоимость сохранена в ее словаре. Что я могу сделать в этом пункте, если есть элемент с тем же самым именем на том же самом уровне?
добавлено автор theAlse, источник
Принятие там не двойные признаки...
добавлено автор isedev, источник
признак пакетов только повторяется в отдельном отделении, это только будет проблема если вы тот же самый признак под той же самой ветвью. : пакеты: 0 пакетов: 1
добавлено автор user2050283, источник
добавлено автор user2050283, источник

user2050283 определенно правильный, это - yaml, и это делает парсинг легким. Главным образом, по образовательным причинам я пытался разобрать его сам. Нетерпеливое ожидание некоторой обратной связи.

Структура ваших данных иерархическая, подобная дереву. Так позволяет, определяют дерево в Пайтоне, максимально простом (ссылка):

from collections import defaultdict

def tree(): return defaultdict(tree)

Затем, давайте использовать это дерево в функции парсинга. Это повторяет по линиям, смотрит на углубление, ведет учет, если это и текущего пути (иначе крошки) и пытается разделить линию на ключ и стоимость (если это существует), и заполняет наше дерево. Где соответствующее, я извлек логические куски как отдельные функции, которые следуют ниже. Если углубление не соответствует никакому предыдущему углублению, оно бросает ошибку - в основном как Пайтон, делает для ее исходного кода.

def load_data(f):
    doc = tree()
    previous_indents = [""]
    path = [""]

    for line in map(lambda x: x.rstrip("\n"), 
                    filter( is_valid_line, f)
                ):
        line_wo_indent = line.lstrip(" ")
        indent = line[:(len(line) - len(line_wo_indent))]

        k, v = read_key_and_value(line_wo_indent)

        if len(indent) > len(previous_indents[-1]):
            previous_indents.append(indent)
            path.append(k)

        elif len(indent) == len(previous_indents[-1]):    
            path[-1] = k

        else: # indent is shorter
            try:
                while previous_indents[-1] != indent:
                    previous_indents.pop()
                    path.pop()            
            except IndexError:
                raise IndentationError("Indent doesn't match any previous indent.")
            path[-1] = k

        if v is not None:
            set_leaf_value_from_path(doc, path, v)
    return doc

Помощник функционирует, я создал:

  • set_leaf_value_from_path: takes a tree, a path (list of keys) and a value. It uses recursion to descent into the tree and set the value of the leaf defined by path.
  • read_key_and_value: splitting a line into key and value, at first ":"
  • is_valid_line: used to check whether a line is not empty or starts with a number sign

Вот полный сценарий

from collections import defaultdict

def tree(): return defaultdict(tree)

def dicts(t): 
    if isinstance(t, dict):
        return {k: dicts(t[k]) for k in t}
    else:
        return t

def load_data(f):
    doc = tree()
    previous_indents = [""]
    path = [""]

    for line in map(lambda x: x.rstrip("\n"), 
                    filter( is_valid_line, f)
                ):
        line_wo_indent = line.lstrip(" ")
        indent = line[:(len(line) - len(line_wo_indent))]

        k, v = read_key_and_value(line_wo_indent)

        if len(indent) > len(previous_indents[-1]):
            previous_indents.append(indent)
            path.append(k)

        elif len(indent) == len(previous_indents[-1]):    
            path[-1] = k

        else: # indent is shorter
            try:
                while previous_indents[-1] != indent:
                    previous_indents.pop()
                    path.pop()            
            except IndexError:
                raise IndentationError("Indent doesn't match any previous indent.")
            path[-1] = k

        if v is not None:
            set_leaf_value_from_path(doc, path, v)
    return doc

def set_leaf_value_from_path(tree_, path, value):
    if len(path)==1:
        tree_[path[0]] = value
    else:
        set_leaf_value_from_path(tree_[path[0]], path[1:], value)

def read_key_and_value(line):
    pos_of_first_column = line.index(":")
    k = line[:pos_of_first_column].strip()
    v = line[pos_of_first_column+1:].strip()
    return k, v if len(v) > 0 else None

def is_valid_line(line):
    if line.strip() == "":
        return False
    if line.lstrip().startswith("#"):
        return False
    return True


if __name__ == "__main__":
    import cStringIO

    document_str = """
statistics:
    time-started: Tue Feb  5 15:33:35 2013
    time-sampled: Thu Feb  7 12:25:39 2013
    statistic:
        active: 0
        interactive: 0
    count: 1
    up:
        packets: 2
        bytes: 2
    down:
        packets: 3
        bytes: 3
"""
    f = cStringIO.StringIO(document_str)
    doc = load_data(f)

    from pprint import pprint
    pprint(dicts(doc))

Известные ограничения:

  • Только скаляры поддерживается как ценности
  • Только скаляры последовательности как ценности
  • скаляры Мультилинии не поддерживается
  • Комментирует, не осуществляются как в определении, т.е., они могут не начать нигде в линии; только линии, начинающиеся со знака номера, рассматривают как комментарии

Это только известный ограничения. Я уверен, что другие части YAML не поддерживаются также. Но это, кажется, достаточно для ваших данных.

0
добавлено
Python
Python
7 654 участник(ов)

Уютный чат для профессионалов, занимающихся поиском питоньих мудростей. Как не получить бан: https://t.me/ru_python/577926

Python beginners
Python beginners
4 449 участник(ов)

Вопросы про Python для чайников. Cпам и троллинг неприемлем. Не злоупотребляйте стикерами. Частозадаваемые вопросы: https://github.com/ru-python-beginners/faq/blob/master/README.md Статистика тут: https://grstats.me/chat/x4qym2k5uvfkr3al6at7

pro.python
pro.python
1 090 участник(ов)

Сообщество разработчиков под Python Создатель: @rodgelius

Rude Python
Rude Python
971 участник(ов)

Python без „девочек”, здесь матерятся и унижают Django. Not gay friendly. Правила: t.me/rudepython/114107 @rudepython | t.me/rudepython

rupython
rupython
509 участник(ов)

Группа создана с целью оперативного получения ответов на возникающие вопросы по разработке на яп python, смежные темы, а также человеческого общения. Приветствую!

Python-programming
Python-programming
266 участник(ов)

Чат группы вконтакте https://vk.com/python_community