Содержание

lxml — Парсинг xml Python

Вопрос задан

Изменён 2 года 1 месяц назад

Просмотрен 300 раз

Есть файл xml, который нужно парсить на python, для нахождения тегов. Подскажите, как посчитать количество повторений этих тегов? Вывести в самом конце сам тег — количество. Вот файл xml:

<?xml version="1.0"?>
<catalog>
        <book>
            <author>Gambardella, Matthew</author>
            <title>XML Developer's Guide</title>
            <genre>Computer</genre>
            <price>44.95</price>
            <publish_date>2000-10-01</publish_date>
            <description>An in-depth look at creating applications
            with XML.
</description> </book> <book> <author>Ralls, Kim</author> <title>Midnight Rain</title> <genre>Fantasy</genre> <price>5.95</price> <publish_date>2000-12-16</publish_date> <description>A former architect battles corporate zombies, an evil sorceress, and her own childhood to become queen of the world.</description> </book> <book> <author>Corets, Eva</author> <title>Maeve Ascendant</title> <genre>Fantasy</genre> <price>5.95</price> <publish_date>2000-11-17</publish_date> <description>After the collapse of a nanotechnology society in England, the young survivors lay the foundation for a new society.</description> </book> </catalog>

Ниже код:

# -*- coding: utf-8 -*-
from lxml import etree
def parseBookXML(xmlFile):
    with open(xmlFile) as fobj:
        xml = fobj. read()
    root = etree.fromstring(xml)
    book_dict = {}
    books = []
    for book in root.getchildren():
        for elem in book.getchildren():
            if not elem.text:
                text = "None"
            else:
                text = elem.text
            print(elem.tag + " => " + text)
            book_dict[elem.tag] = text
        if book.tag == "book":
            books.append(book_dict)
            book_dict = {}
    return books
if __name__ == "__main__":
    parseBookXML("books.xml")
  • python
  • lxml

Интересненько. Формализую задачу: вам нужно найти количество повторений тегов. Непонятно каких… Например для всех:

import re
from collections import Counter
def parseBookXML(xmlFile):
    with open(xmlFile) as fobj:
        xml = fobj.read()
    # понимаю, что все тэги парные и смысла включать все нет смысла,
    # буду забирать только открывающиеся
    pattern = r"<\w{1,}" 
    
    how_many_tags = Counter(re.findall(pattern, k))
    
    # что содержит how_many_tags
    # Counter({'<book': 3, '<author': 3, '<title': 3, '<genre': 3, '<price': 3, '<publish_date': 3, '<description': 3, '<catalog': 1})
    # если напрягают символы в начале ключей, то можно почистить
    clear = {}
    for i in how_many_tags:
        key = i[1:]
        clear[key] = how_many_tags[i]
    
    # ну, и переменная clear {'catalog': 1, 'book': 3, 'author': 3, 'title': 3, 'genre': 3, 'price': 3, 'publish_date': 3, 'description': 3}

Если нужен подсчет вместе с закрывающими, то умножьте на 2 все значения и будет вам счастье.

Зарегистрируйтесь или войдите

Регистрация через Google

Регистрация через Facebook

Регистрация через почту

Отправить без регистрации

Почта

Необходима, но никому не показывается

Отправить без регистрации

Почта

Необходима, но никому не показывается

By clicking “Отправить ответ”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

python — Парсинг XML файла таблицы с передачей в DataFrame

Воспользуйтесь данным решением (с) Austin Taylor:

import xml. etree.ElementTree as ET
import pandas as pd
class XML2DataFrame:
    def __init__(self, xml_data):
        self.root = ET.XML(xml_data)
    def parse_root(self, root):
        return [self.parse_element(child) for child in iter(root)]
    def parse_element(self, element, parsed=None):
        if parsed is None:
            parsed = dict()
        for key in element.keys():
            parsed[key] = element.attrib.get(key)
        if element.text:
            parsed[element.tag] = element.text
        for child in list(element):
            self.parse_element(child, parsed)
        return parsed
    def process_data(self):
        structure_data = self.parse_root(self.root)
        return pd.DataFrame(structure_data)
xml2df = XML2DataFrame(xml_data)
df = xml2df.process_data()

Пример:

with open(r"D:\download\20200915_ED807_full.xml") as f:
    xml_data = f.read()
xml2df = XML2DataFrame(xml_data)
df = xml2df.process_data()

результат:

In [32]: df
Out[32]:
            BIC                                    NameP CntrCd Rgn     Ind  . ..        SWBIC DefaultSWBIC  \
0     041280103              УФК по Астраханской области     RU  12  414056  ...          NaN          NaN
1     044525597     КУ "МИЛЛЕНИУМ БАНК" (ЗАО) - ГК "АСВ"     RU  45  109240  ...          NaN          NaN
2     044525603          КУ ЗАО "ИПОТЕК БАНК" - ГК "АСВ"     RU  45  109240  ...          NaN          NaN
3     044525608        КУ ООО КБ "ДОРИС БАНК" - ГК "АСВ"     RU  45  109240  ...          NaN          NaN
4     044525652  КУ КБ "ПРИСКО КАПИТАЛ БАНК", АО - ГК...     RU  45  109240  ...          NaN          NaN
...         ...                                      ...    ...  ..     ...  ...          ...          ...
2368  298003187          Департамент финансов г. Якутска     RU  98  677000  ...          NaN          NaN
2369  015354008              УФК по Оренбургской области     RU  53  460014  ...          NaN          NaN
2370  200000099  Территориальная избирательная комисс...     RU  36  443110  ...          NaN          NaN
2371  200001413  Территориальная избирательная комисс.
.. RU 36 445011 ... NaN NaN 2372 047516949 БАНК "КУБ" (АО) RU 75 455044 ... CRDURU4CXXX 1 EnglName AccRstr AccRstrDate 0 NaN NaN NaN 1 NaN NaN NaN 2 NaN NaN NaN 3 NaN NaN NaN 4 NaN NaN NaN ... ... ... ... 2368 NaN NaN NaN 2369 NaN NaN NaN 2370 NaN NaN NaN 2371 NaN NaN NaN 2372 "Credit Ural Bank" Joint Stock Compa... NaN NaN [2373 rows x 28 columns]

столбцы DataFrame:

In [33]: df. columns
Out[33]:
Index(['BIC', 'NameP', 'CntrCd', 'Rgn', 'Ind', 'Tnp', 'Nnp', 'Adr', 'DateIn', 'PtType', 'Srvcs', 'XchType', 'UID',
       'ParticipantStatus', 'Account', 'RegulationAccountType', 'CK', 'AccountCBRBIC', 'AccountStatus', 'RegN', 'Rstr',
       'RstrDate', 'PrntBIC', 'SWBIC', 'DefaultSWBIC', 'EnglName', 'AccRstr', 'AccRstrDate'],
      dtype='object')

все значения первой строки фрейма:

In [34]: pd.set_option("display.max_rows", 30)
In [35]: df.iloc[0]
Out[35]:
BIC                                        041280103
NameP                    УФК по Астраханской области
CntrCd                                            RU
Rgn                                               12
Ind                                           414056
Tnp                                                г
Nnp                                        Астрахань
Adr                                 ул Латышева, 6 Г
DateIn                                    2013-01-09
PtType                                            52
Srvcs                                              3
XchType                                            1
UID                                       1280002005
ParticipantStatus                               PSAC
Account                         40116810600000010015
RegulationAccountType                           TRSA
CK                                                99
AccountCBRBIC                              041280002
AccountStatus                                   ACAC
RegN                                             NaN
Rstr                                             NaN
RstrDate                                         NaN
PrntBIC                                          NaN
SWBIC                                            NaN
DefaultSWBIC                                     NaN
EnglName                                         NaN
AccRstr                                          NaN
AccRstrDate                                      NaN

Как разобрать файлы XML с помощью python? [Код включен]

От заказа продуктов через Instamart и покупки гардероба в Myntra до бронирования отпуска на MakemyTrip — в этом десятилетии веб-сайты стали незаменимыми! Вы когда-нибудь задумывались, как эти веб-сайты отображают информацию для клиентов в легко интерпретируемом виде, а также обрабатывают и взаимодействуют с данными в бэкэнде?

Существуют определенные форматы файлов, которые восполняют этот пробел, будучи интерпретируемыми как для машинного языка, так и для человека. Одним из таких широко используемых форматов является XML, сокращение от Extensible Markup Language.

Что такое файлы XML и как их использовать?

Файлы XML используются для хранения и передачи данных между клиентами и серверами. Это позволяет нам определять данные в структурированном формате с помощью тегов, атрибутов и значений. Одним из основных преимуществ XML является его гибкость. Его можно использовать для представления данных во многих форматах и ​​легко адаптировать для новых целей. Это делает его популярным выбором для таких приложений, как веб-службы, обмен данными и файлы конфигурации. В этой статье я познакомлю вас с различными методами Python для анализа XML-файла на практическом примере.


Вы ищете автоматизированный анализ XML? Попробуйте автоматизированные рабочие процессы Nanonets. Начните бесплатную пробную версию прямо сейчас.


Понимание структуры XML-файлов

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

Гарри Поттер и Философский камень

Я буду использовать пример файла «travel_pckgs.xml», который содержит сведения о различных турпакетах, предлагаемых компанией. Я буду продолжать использовать один и тот же файл в блоге для ясности.

 
<турпакеты>
<пакет>
Ощутите великолепную красоту Парижа и французскую культуру.
Париж, Франция
<цена>3000
<длительность>7
<платеж>
да
<возврат>да


<пакет>
Отправляйтесь в захватывающее приключение на гавайских пляжах!

Гавайи, США
<цена>4000
<длительность>10
<платеж>
нет
<возврат>нет


<пакет>
Побалуйте себя красотой и очарованием Италии и получите все-
инклюзивный тур по настоящей итальянской кухне!
Италия
<цена>2000
<длительность>8
<платеж>
да
<возврат>нет


<пакет>
Ощутите красоту пляжей острова, включая подводное плавание. 
дайвинг и ночное плавание на байдарках по мангровым зарослям.
Андаманские и Никобарские острова
<цена>800
<длительность>8
<платеж>
нет
<возврат>да


 

В файле содержатся данные о 4 турпакетах с подробной информацией о пункте назначения, описании, цене и способах оплаты, предоставленных агентством. Давайте посмотрим на разбивку различных частей приведенного выше XML:

  • Корневой элемент: Элемент самого верхнего уровня называется корневым, который в нашем файле равен . Он содержит все остальные элементы (предлагаются различные туры)
  • Атрибут: «id» — это атрибут каждого элемента в нашем файле. Обратите внимание, что атрибут должен иметь уникальные значения («Отпуск в Париже», «Приключение на Гавайях» и т. д.) для каждого элемента. Как видите, атрибут и его значение обычно упоминаются внутри начального тега.
  • Дочерние элементы : Элементы, завернутые в корень, являются дочерними элементами. В нашем случае все теги   являются дочерними элементами, каждый из которых хранит сведения о турпакете.
  • Подэлементы: Дочерний элемент может иметь больше подэлементов внутри своей структуры. Дочерний элемент имеет подэлементы , , , и . Преимущество XML в том, что он позволяет хранить иерархическую информацию с помощью нескольких вложенных элементов. Подэлемент дополнительно имеет подэлементы и , которые обозначают, есть ли у конкретного пакета варианты оплаты через EMI и возврата или нет.

Совет: Вы можете создать древовидное представление XML-файла, чтобы получить четкое представление об этом инструменте. Посмотрите на иерархическое древовидное представление нашего XML-файла!

Отлично! Мы хотим читать данные, хранящиеся в этих полях, искать, обновлять и вносить изменения по мере необходимости для веб-сайта, верно? Это называется синтаксическим анализом, при котором XML-данные разбиваются на части и идентифицируются разные части.

Существует несколько способов анализа XML-файла в Python с помощью разных библиотек. Давайте погрузимся в первый метод!


Попробуйте Nanonets анализировать файлы XML. Начните бесплатную пробную версию без данных кредитной карты.


Использование Mini DOM для анализа XML-файлов

Я уверен, что вы сталкивались с DOM (Document Object Model), стандартным API для представления XML-файлов. Mini DOM — это встроенный модуль Python, который минимально реализует DOM.

Как работает мини-ДОМ?

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

Давайте посмотрим, как импортировать пакет с помощью приведенного ниже кода. Вы можете проанализировать файл XML, используя функцию xml.dom.minidom.parse() , а также получить корневой элемент.

 импорт xml.dom.minidom
# разбираем XML-файл
xml_doc = xml.dom.minidom.parse('travel_pckgs.xml')
# получить корневой элемент
корень = xml_doc.documentElement
print('Root is',root) 

Вывод, который я получил для приведенного выше кода:

 >> Корень  

Допустим, я хочу распечатать место, продолжительность и цена.

Функцию getAttribute() можно использовать для получения значения атрибута элемента.

Если вы хотите получить доступ ко всем элементам под определенным тегом, используйте метод getElementsByTagName() и укажите тег в качестве входных данных. Самое приятное то, что getElementsByTagName() можно использовать рекурсивно для извлечения вложенных элементов.

 # получить все элементы пакета
пакеты = xml_doc.getElementsByTagName («пакет»)
# перебираем пакеты и извлекаем данные
для пакета в пакетах:
package_id = package.getAttribute('id')
описание = package.getElementsByTagName('описание')[0].childNodes[0].data
цена = package.getElementsByTagName('price')[0].childNodes[0].data
продолжительность = package.getElementsByTagName('длительность')[0].childNodes[0].data
print('Идентификатор пакета:', package_id)
print('Описание:', описание)
print('Цена:', цена) 

Здесь показан вывод приведенного выше кода с извлеченными и напечатанными идентификатором, текстом описания и ценой каждого пакета.

 Код пакета: Парижские каникулы
Описание: Испытайте великолепную красоту Парижа и французскую культуру.
Цена: 3000
ID пакета: Приключения на Гавайях
Описание: Отправляйтесь в захватывающее приключение на гавайских пляжах!
Цена: 4000
ID пакета: Бегство по-итальянски
Описание: Насладитесь красотой и очарованием Италии и получите тур по итальянской кухне по системе «все включено»!
Цена: 2000
ID пакета: Ретрит на Андаманских островах
Описание: Испытайте красоту пляжей острова, включая подводное плавание. 
дайвинг и ночной каякинг через мангровые заросли.
Цена: 800 

Анализатор Minidom также позволяет нам перемещаться по дереву DOM от одного элемента к его родительскому элементу, его первому дочернему элементу, последнему дочернему элементу и так далее. Вы можете получить доступ к первому потомку элемента , используя атрибут firstChild . Имя и значение узла извлеченного дочернего элемента также можно распечатать с помощью атрибутов nodeName и nodeValue , как показано ниже.

 # получить первый элемент пакета
paris_package = xml_doc.getElementsByTagName('пакет')[0]
# получить первый дочерний элемент пакета
first_child = париж_пакет.firstChild
#print(first_child)
>>
<Элемент DOM: описание по адресу 0x7f2e4800d9д0>
Имя узла: описание
Node Value: None 

Вы можете убедиться, что «описание» является первым дочерним элементом . Также есть атрибут с именем childNodes , который возвращает все дочерние элементы, присутствующие внутри текущего узла. Проверьте приведенный ниже пример и его вывод.

 child_elements=paris_package.childNodes
печать (дочерние_элементы)
>>
[<Элемент DOM: описание по адресу 0x7f057938e940>, <Элемент DOM: пункт назначения по адресу 0x7f057938e9d0>, <Элемент DOM: цена по адресу 0x7f057938ea60>, <Элемент DOM: продолжительность по адресу 0x7f057938eaf0>, <Элемент DOM: оплата по адресу 0x7f057938eb80>] 

Подобно этому, minidom предоставляет больше способов обхода, таких как parentNode, lastChild nextSibling и т. д. Вы можете проверить все доступные функции библиотека здесь.

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


Автоматизировать синтаксический анализ XML Nanonets. Начните бесплатную пробную версию сегодня. Кредитная карта не требуется.


Использование библиотеки ElementTree для анализа XML-файлов

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

Начнем с импорта библиотеки и вызова функции parse() нашего файла XML. Вы также можете предоставить входной файл в строковом формате и использовать функцию fromstring() . После того, как мы инициализируем проанализированное дерево, мы можем использовать получить root () функция для получения корневого тега, как показано ниже.

 импортировать xml.etree.ElementTree как ET
дерево = ET.parse('travel_pkgs.xml')
#вызов корневого элемента
корень = дерево.getroot()
print("Корень есть",корень)
Выход:
>>
Корневой элемент  

Извлечен корневой тег ‘travelPackages’!

Допустим, теперь мы хотим получить доступ ко всем первым дочерним тегам корня. Мы можем использовать простой цикл for и перебирать его, печатая дочерние теги, такие как пункт назначения, цена и т. д. Обратите внимание, что если бы мы указали значение атрибута внутри открывающего тега описания, круглые скобки не были бы пустыми. Посмотрите приведенный ниже фрагмент!

 для x в корне[0]:
печать (x.tag, x.attrib)
Выход:
>>
описание {}
место назначения {}
цена {}
продолжительность {}
payment {} 

Кроме того, функция iter() может помочь вам найти любой интересующий элемент во всем дереве. Давайте используем это для извлечения описаний каждого пакета туров в нашем файле. Не забудьте использовать атрибут text для извлечения текста элемента.

 Для x в root.iter('описание'):
печать (x.текст)
Выход:
>>
«Ощутите великолепную красоту Парижа и французскую культуру».
«Отправляйтесь в захватывающее приключение на пляжах Гавайев!»
"Побалуйте себя красотой и очарованием Италии и получите тур по итальянской кухне по системе "все включено"!"
«Насладитесь красотой пляжей острова, подводным плаванием с аквалангом и ночным каякингом через мангровые заросли.  

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

Анализ XML-файлов с помощью цикла for

Вы можете просто перебирать дочерние элементы с помощью цикла for, извлекая атрибуты, как показано ниже.

 для тура в корень:
распечатать(тур.атриб)
Выход:
>>
{'id': 'Отпуск в Париже'}
{'id': 'Гавайские приключения'}
{'id': 'Побег из Италии'}
{'id': 'Andaman Island Retreat'} 

Для обработки сложных запросов и фильтрации ElementTee имеет метод findall() . Этот метод позволяет получить доступ ко всем дочерним элементам тега, переданным в качестве параметров. Допустим, вы хотите узнать о турпакетах стоимостью менее 4000 долларов, а также иметь EMIoption как «да». Проверьте фрагмент.

 для пакета в root.findall('package'):
цена = int(package.find('price').text)
возврат = package.find('платеж/возврат').text.strip("'")
если цена < 4000 и возврат == 'да':
print(package. attrib['id']) 

Мы в основном перебираем пакеты через root.findall(‘package’), а затем извлекаем цену и возмещение с помощью метод find() . После этого мы проверяем ограничения и отфильтровываем подходящие пакеты, которые напечатаны ниже.

Вывод:

>>

Отпуск в Париже

Отдых на Андаманских островах

Используя ElementTree, вы можете легко изменять и обновлять элементы и значения XML-файла, в отличие от miniDOM и SAX. Давайте проверим, как в следующем разделе.

Как изменить файлы XML с помощью ElementTree?

Допустим, пришло время рождественских каникул и агентство хочет удвоить стоимость пакета. ElementTree предоставляет set() функция, которую мы можем использовать для обновления значений элементов. В приведенном ниже коде я получил доступ к цене каждого пакета через функцию iter() и манипулировал ценами. Вы можете использовать функцию write() для записи нового XML-файла с обновленными элементами.

 для цены в root.iter('price'):
новая_цена = интервал (цена.текст)*2
цена.текст = ул(новая_цена)
price.set('обновлено', 'да')
tree.write('christmas_packages.xml') 

Вы сможете найти выходной файл, подобный тому, что показан на изображении ниже. Если вы помните, цены на «Отпуск в Париже» и «Приключения на Гавайях» в исходном файле составляют 3000 и 4000 долларов.

Но что, если мы захотим добавить новый тег к пакету Andaman, чтобы обозначить, что предлагаемое пребывание — это «частная вилла премиум-класса». Функция SubElement() ElementTree позволяет нам добавлять новые вложенные теги по мере необходимости, как показано в приведенном ниже фрагменте. Вы должны передать элемент, который хотите изменить, и новый тег в качестве параметров функции.

 ET.SubElement(корень[3], 'остаться')
для x в root.iter('оставаться'):
курорт = 'Частная вилла Премиум'
x.text = ул(курорт) 

Надеюсь, вы тоже получили результаты! Пакет также предоставляет функцию pop() , с помощью которой можно удалить атрибуты и подэлементы, если они не нужны.


Простой API для XML (SAX)

SAX — еще один синтаксический анализатор Python, который устраняет недостаток miniDOM за счет последовательного чтения документа. Он не загружает все дерево в свою память, а также позволяет отбрасывать элементы, уменьшая использование памяти.

Во-первых, давайте создадим объект парсера SAX и зарегистрируем функции обратного вызова для различных событий, которые вы хотите обрабатывать в XML-документе. Для этого я определяю собственный класс TravelPackageHandler, как показано ниже, путем подкласса ContentHandler SAX.

 импорт xml.sax
# Определите собственный класс SAX ContentHandler для обработки событий
класс TravelPackageHandler (xml.sax.ContentHandler):
защита __init__(сам):
self.packages = []
self.current_package = {}
self.current_element = ""
self.current_payment = {}
def startElement (я, имя, атрибуты):
self.current_element = имя
если имя == "пакет":
self.current_package = {"id": attrs.getValue("id")}
символы определения (я, содержание):
если self. current_element в ["описание", "назначение", "цена", "продолжительность", "вариант EMI", "возврат"]:
self.current_package[self.current_element] = content.strip()
если self.current_element == "оплата":
self.current_payment = {}
def endElement(я, имя):
если имя == "пакет":
self.current_package["платеж"] = self.current_payment
self.packages.append (self.current_package)
если имя == "оплата":
self.current_package["платеж"] = self.current_payment
def startElementNS(self, name, qname, attrs):
проходить
def endElementNS (я, имя, qname):
пройти 

В приведенном выше фрагменте используются методы startElement(), character(), и endElement() для извлечения данных из элементов и атрибутов XML. Когда синтаксический анализатор SAX читает документ, он запускает зарегистрированные функции обратного вызова для каждого встречающегося события. Например, если он встречает начало нового элемента, он вызывает функцию startElement(). Теперь давайте воспользуемся нашим настраиваемым обработчиком, чтобы получить различные идентификаторы пакетов, проанализировав XML-файл нашего примера.

 # Создать объект парсера SAX
парсер = xml.sax.make_parser()
обработчик = TravelPackageHandler()
parser.setContentHandler(обработчик)
parser.parse ("путешествие_pckgs.xml")
для пакета в handler.packages:
print(f'Package: {package["id"]}') 

Output >>

Package: Paris Vacation

Package: Hawaii Adventure

Package: Italian Getaway

Package: Andaman Island Retreat

SAX can использоваться для больших файлов и потоковой передачи из-за его эффективности. Но это неудобно при работе с глубоко вложенными элементами. Что делать, если вы хотите получить доступ к любому произвольному узлу дерева? Поскольку он не поддерживает произвольный доступ, синтаксическому анализатору придется последовательно читать весь документ, чтобы получить доступ к определенному элементу.


Синхронизируйте все ваши двойные записи с Nanonets. Держите все свои счета сбалансированными, 24×7. Настройте процессы учета менее чем за 15 минут. Смотри как.


Потоковый синтаксический анализатор для XML

Это библиотека Python pulldom , которая предоставляет API потокового синтаксического анализатора с DOM-подобным интерфейсом.

Как это работает?

Обрабатывает XML-данные методом «вытягивания». То есть вы явно запрашиваете у синтаксического анализатора следующее событие (например, начальный элемент, конечный элемент, текст и т. д.) в данных XML.

Синтаксис знаком тому, что мы видели в предыдущих библиотеках. В приведенном ниже коде я демонстрирую, как импортировать библиотеку и использовать ее для печати туров продолжительностью 4 дня и более, а также обеспечить возврат средств при отмене.

 из синтаксического анализа импорта xml.dom.pulldom
события = разбор ("travel_pkgs.xml")
для события, узел в событиях:
если событие == pulldom.START_ELEMENT и node.tagName == 'package':
продолжительность = int(node.getElementsByTagName('длительность')[0]. firstChild.data)
возврат = node.getElementsByTagName('refund')[0].firstChild.data.strip("'")
если продолжительность > 4 и возврат == 'да':
print(f"Пакет: {node.getAttribute('id')}")
print(f"Продолжительность: {длительность}")
print(f"Возврат: {возврат}") 

Вы должны получить результат вида:

Пакет: Парижские каникулы

Продолжительность: 7

Возврат: да

Пакет: Ретрит на Андаманских островах

Продолжительность: 8

Возврат: да 90 003

Проверьте результаты! Парсер pull сочетает в себе несколько функций miniDOM и SAX, что делает его относительно эффективным.

Резюме

Я уверен, что вы уже хорошо разбираетесь в различных парсерах, доступных в Python. Не менее важно знать, когда выбрать парсер, чтобы сэкономить время и ресурсы. Среди всех парсеров, которые мы видели, ElementTree обеспечивает максимальную совместимость с выражениями XPath, помогающими выполнять сложные запросы. Minidom имеет простой в использовании интерфейс и может быть выбран для работы с небольшими файлами, но он слишком медленный в случае больших файлов. В то же время SAX используется в ситуациях, когда файл XML постоянно обновляется, как в случае машинного обучения в реальном времени.

Одной из альтернатив для анализа ваших файлов является использование инструментов автоматического анализа, таких как Nanonets. Наносети могут помочь вам извлечь данные из любого документа за считанные секунды, не написав ни одной строки кода.

O Оптимизируйте эффективность своего бизнеса, сократите расходы и ускорьте рост. Узнайте , как варианты использования Nanonets могут применяться к вашему продукту.


Разбор XML в Swift: Учебник с примерами

Поделиться

Ответить

  • 0

Арджуна Скай Кок Подписаться Я инженер-программист, ютубер и писатель. Я создаю PredictSalary, SailorCoin и Pembangun.

7 минут чтения 2190 110

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

Вам не нужно искать стороннюю библиотеку для управления файлом XML с помощью Swift. В стандартной библиотеке Swift есть XMLParser для всех ваших XML-потребностей.

Перейти вперед:

  • Настройка XMLParser и XMLParserDelegate
  • Обработка элементов данных XML
  • Обработка атрибутов элементов данных XML
  • Обработка пространства имен в данных XML
  • Получение текстового содержимого при разборе данных XML
  • Обработка ошибок при анализе данных XML

Настройка

XMLParser и XMLParserDelegate

Создайте проект Playground в XCode и назовите его XMLParsingPlayground . Обратитесь к этой статье, чтобы узнать больше об этом шаге.

Чтобы проанализировать данные XML, необходимо преобразовать строку XML в Данные . Добавьте следующий код:

 пусть xmlContent =
"""

<корень>
    <статья>
        Начало работы со Swift
    
    <статья>
        Как анализировать XML с помощью Rust
    

""";
пусть xmlData = данные (xmlContent.utf8)
 

В приведенном выше коде вы инициализировали экземпляр Data строкой XML. Теперь вам нужно инициализировать экземпляр XMLParser с помощью этого экземпляра Data :

.
 пусть xmlParser = XMLParser (данные: xmlData)
 

XMLParser делегирует логику синтаксического анализа своему классу делегирования. Вам нужно будет реализовать этот класс, который наследует NSObject и XMLParserDelegate . Добавьте следующий код для создания класса и его экземпляра:

 класс Parser1: NSObject, XMLParserDelegate {
    func parserDidStartDocument(_ парсер: XMLParser) {
        print("Начало документа")
        print("Номер строки: \(parser. lineNumber)")
    }
    func parserDidEndDocument(_ парсер: XMLParser) {
        print("Конец документа")
        print("Номер строки: \(parser.lineNumber)")
    }
}
пусть парсер1 = парсер1()
 

В делегированном классе вы настроили логику, чтобы что-то делать, когда вы нажимаете начало документа и конец документа в процессе синтаксического анализа. Если вы столкнетесь с ними, вы напечатаете несколько строк и номер строки, где парсер сейчас находится. Оба метода принимают Экземпляр XMLParser в аргументах. Многие методы в делегированном классе принимают в качестве аргументов экземпляр XMLParser .

После завершения экземпляра делегирования синтаксического анализатора вы должны установить его как класс делегирования экземпляра XMLParser :

 xmlParser.delegate = парсер1
 

Последний шаг — разобрать его:

 xmlParser.parse()
 

Если вы скомпилировали и запустили программу, вы должны получить следующий вывод:

 Начало документа
Номер строки: 1
Конец документа
Номер строки: 9
 

Код выше означает, что когда парсер встретил событие начала документа , он был в строке 1. Затем он перешел к содержимому документа. Он прошел через элементы, но поскольку вы не реализовали методы для обработки этого, ничего не произошло. Наконец, когда он столкнулся с событием конца документа , он проинформировал нас через реализованный вами метод parserDidEndDocument .

Обработка элементов данных XML

При синтаксическом анализе XML вам необходимо реализовать методы для обработки интересующих вас узлов или событий. Если вас интересуют комментарии, вам необходимо реализовать метод, когда синтаксический анализатор встречает комментарии в данных XML.

Теперь вы хотите реализовать методы, когда синтаксический анализатор встречает такие элементы, как article и title . Метод, который вам нужно реализовать, — это метод парсера со следующей сигнатурой:

 анализатор функций(
        _ парсер: XMLParser,
        didStartElement elementName: строка,
        namespaceURI: Строка?,
        квалифицированное имя qName: строка?,
        атрибуты attributeDict: [String : String] = [:]
    )
 

Создать новый делегированный класс парсера:

 класс Parser2: NSObject, XMLParserDelegate {
    анализатор функций(
        _ парсер: XMLParser,
        didStartElement elementName: строка,
        namespaceURI: Строка?,
        квалифицированное имя qName: строка?,
        атрибуты attributeDict: [String : String] = [:]
    ) {
        печать (имя элемента)
    }
}
 

В новом делегированном классе вы не реализовали parserDidStartDocument и parserDidEndDocument , потому что вы сосредоточены только на разборе элементов.

Как обычно, вам нужно установить делегированный экземпляр класса нового экземпляра XMLParser и снова вызвать метод parse :

 пусть парсер2 = парсер2()
пусть xmlParser2 = XMLParser (данные: xmlData)
xmlParser2.delegate = парсер2
xmlParser2.parse()
 

Скомпилируйте и запустите программу, она напечатает имена элементов:

 корень
статья
заголовок
статья
заголовок
 

Как видите, элементов пять. Если вы хотите различать элементов заголовка , потому что их два, вам нужно добавить больше логики. Один из примеров — отследить, сколько элементов article встретилось при синтаксическом анализе.

Создать другой делегированный класс:

 класс Parser3: NSObject, XMLParserDelegate {
    переменная статьяNth = 0
    анализатор функций(
        _ парсер: XMLParser,
        didStartElement elementName: строка,
        namespaceURI: Строка?,
        квалифицированное имя qName: строка?,
        атрибуты attributeDict: [String : String] = [:]
    ) {
        если (elementName=="статья") {
            статьяNth += 1
        } иначе если (elementName=="название") {
            print("'\(elementName)' в номере элемента статьи \(articleNth)")
        }
    }
}
 

На этот раз вы отслеживали, сколько элементов статьи вы встретили, поэтому, когда вы встречаете элемент title , вы знаете, в каком элементе статьи вы находитесь.

Создайте новый экземпляр XMLParser и установите для делегированного класса значение Parser3 :

 пусть парсер3 = парсер3()
пусть xmlParser3 = XMLParser (данные: xmlData)
xmlParser3.delegate = парсер3
xmlParser3.parse()
 

Если вы скомпилируете и запустите программу, вы должны увидеть этот вывод:

 'заголовок' в элементе статьи номер 1
'заголовок' в элементе статьи номер 2
 

Обработка атрибутов элементов данных XML

Элементы данных XML также могут иметь атрибуты. Возможно, вы захотите запросить атрибуты. Недавно выполненный метод имеет еще один аргумент, который ссылается на атрибуты. Но сначала вам нужно создать другие XML-данные, потому что сейчас данные не имеют атрибутов:

.
 пусть xmlContent_attributes =
"""

<корень>
    <тег статьи="быстро">
        Начало работы со Swift
    
    <тег статьи="ржавчина">
        Как анализировать XML с помощью Rust
    

""";
пусть xmlData_attributes = данные (xmlContent_attributes. utf8)
 

На этот раз вы добавили атрибуты к элементам статьи . Атрибуты id и tag .

Теперь вам нужно создать делегированный класс для обработки атрибутов:

 класс Parser4: NSObject, XMLParserDelegate {
    анализатор функций(
        _ парсер: XMLParser,
        didStartElement elementName: строка,
        namespaceURI: Строка?,
        квалифицированное имя qName: строка?,
        атрибуты attributeDict: [String : String] = [:]
    ) {
        for (attr_key, attr_val) в attributeDict {
            print("Ключ: \(attr_key), значение: \(attr_val)")
        }
    }
}
 

Метод аналогичен ранее реализованному методу. Но на этот раз вы не проигнорировали аргумент attributeDict .


Более 200 000 разработчиков используют LogRocket для улучшения цифрового взаимодействия

Подробнее →


Мы еще не закончили! Теперь вам нужно создать новый экземпляр XMLParser , который использует этот экземпляр делегированного класса:

.
 пусть парсер4 = парсер4()
пусть xmlParser4 = XMLParser (данные: xmlData_attributes)
xmlParser4.delegate = парсер4
xmlParser4.parse()
 

Если вы скомпилировали и запустили программу, вы увидите следующие атрибуты:

 Ключ: идентификатор, значение: 1
Ключ: тег, значение: swift
Ключ: идентификатор, значение: 2
Ключ: тег, значение: ржавчина
 

Обработка пространства имен в данных XML

Теперь есть два аргумента, которые вы не рассмотрели в методе синтаксического анализатора . Это namespaceURI и qName , которые связаны друг с другом.

Во-первых, вам нужно добавить пространства имен в данные XML:

 пусть xmlContent_namespace =
"""

<корневой xmlns:t="http://logrocket.com/tech" xmlns:m="http://logrocket.com/marketing">
    
        Начало работы со Swift
    
    
        Как анализировать XML с помощью Rust
    

""";
пусть xmlData_namespace = данные (xmlContent_namespace. utf8)
 

В этих XML-данных есть два пространства имен: http://logrocket.com/tech и http://logrocket.com/marketing . Элементы внутри корневого элемента используют пространства имен. Это уже не артикул , а т:артикул или м:артикул .

t ссылается на xmlns:t , который имеет значение http://logrocket.com/tech . m относится к xmlns:m , имеющему значение http://logrocket.com/marketing .

Затем вам нужно создать делегированный класс для обработки пространства имен:

 класс Parser5: NSObject, XMLParserDelegate {
    анализатор функций(
        _ парсер: XMLParser,
        didStartElement elementName: строка,
        namespaceURI: Строка?,
        квалифицированное имя qName: строка?,
        атрибуты attributeDict: [String : String] = [:]
    ) {
        print("URI пространства имен: \(URI пространства имен!), полное имя: \(qName!)")
    }
}
 

Чтобы получить URI пространства имен, например, http://logrocket. com/tech , вы можете использовать namespaceURI аргумент. Чтобы получить полное имя, например, t:article , можно использовать аргумент qName .

Следующий важный шаг. Создайте новый экземпляр XMLParser для обработки пространства имен:

 пусть парсер5 = парсер5()
пусть xmlParser5 = XMLParser (данные: xmlData_namespace)
xmlParser5.delegate = парсер5
xmlParser5.shouldProcessNamespaces = истина
xmlParser5.parse()
 

Прежде чем скомпилировать и запустить программу, обратите внимание на строку, которая указывает синтаксическому анализатору обрабатывать пространство имен. Чтобы включить пространство имен в данных XML, вам нужно установить shouldProcessNamespaces свойство синтаксического анализатора на true . В противном случае пространства имен будут игнорироваться.

Скомпилируйте и запустите программу. Затем вы получите URI пространства имен и полные имена:

.
 URI пространства имен: полное имя: корень
URI пространства имен: http://logrocket.com/tech, полное имя: t:article
URI пространства имен: http://logrocket.com/tech, полное имя: t:title
URI пространства имен: http://logrocket.com/marketing, полное имя: m:article
URI пространства имен: http://logrocket.com/marketing, полное имя: m:title
 

Получение текстового содержимого при разборе данных XML

Теперь пришло время получить текстовое содержимое из данных XML. Метод, который вам нужно реализовать, — это метод парсера со следующей сигнатурой:

.
 анализатор функций(
        _ парсер: XMLParser,
        строка foundCharacters: строка
    )
 

Добавьте следующие данные XML:

 пусть xmlContent_text =
"""

<корень>
    <статья>
        Начало работы со Swift
        <опубликовано>правда
    
    <статья>
        Как анализировать XML с помощью Rust
        <опубликовано>ложь
    

""";
пусть xmlData_text = данные (xmlContent_text. utf8)
 

Затем вам нужно реализовать делегированный класс, у которого есть метод для обработки текстового содержимого:

 класс Parser6: NSObject, XMLParserDelegate {
    анализатор функций(
        _ парсер: XMLParser,
        строка foundCharacters: строка
    ) {
        если (string.trimmingCharacters(in: .whitespacesAndNewlines) != "") {
            печать (строка)
        }
    }
}
 

Вас интересует только текстовое содержимое, содержащее несколько символов. Если бы вы не реализовали фильтр, это привело бы к большому количеству пустого текстового контента. Текстовый контекст определяется как текст между узлами элемента. Это включает в себя пустой текст между артикул элемент и заголовок элемент а также:

 <артикул>
        Как анализировать XML с помощью Rust
 

Это не просто пробелы, между статья и заголовок есть новая строка. Вот почему вы сначала обрезали его, а затем проверили, пустая это строка или нет.

Наконец, создайте экземпляр XMLParser для обработки текстового содержимого:

 пусть парсер6 = парсер6()
пусть xmlParser6 = XMLParser (данные: xmlData_text)
xmlParser6.delegate = парсер6
xmlParser6.parse()
 

Если вы скомпилировали и запустили программу, вы должны получить следующее текстовое содержимое:

 Начало работы со Swift
истинный
Как парсить XML с помощью Rust
ЛОЖЬ
 

Обработка ошибок при анализе данных XML

Жизнь не идеальна. Иногда вы получаете несовершенные данные XML, и данные повреждены. Но не волнуйтесь! Вы можете обрабатывать ошибки с помощью метода парсера со следующей сигнатурой:

 анализатор функций(
        _ парсер: XMLParser,
        parseErrorOccurred parseError: Ошибка
    )
 

Но сначала вам нужно записать поврежденные данные XML:

 пусть xmlContent_corrupted =
"""

<корень>
    <статья>
        Начало работы со Swift
    
    <статья>
        Как анализировать XML с помощью Rust
    </статья>
</корень>
""";
пусть xmlData_corrupted = данные (xmlContent_corrupted.<img class="lazy lazy-hidden" loading='lazy' src="//ylianova.ru/wp-content/plugins/a3-lazy-load/assets/images/lazy_placeholder.gif" data-lazy-type="image" data-src='/800/600/https/cf.ppt-online.org/files/slide/j/jGuzxNVhTR4gZdqCM2/slide-24.jpg' /><noscript><img loading='lazy' src='/800/600/https/cf.ppt-online.org/files/slide/j/jGuzxNVhTR4gZdqCM2/slide-24.jpg' /></noscript> utf8)
 </pre><p> Обратите внимание, что отсутствует закрывающий <code> заголовок </code> тег.</p><p> Затем создайте делегированный класс для обработки ошибки:</p><pre> класс Parser7: NSObject, XMLParserDelegate {
    анализатор функций(
        _ парсер: XMLParser,
        parseErrorOccurred parseError: Ошибка
    ) {
        печать (parseError)
    }
}
 </pre><p> Этот метод выдал аргумент <code> parseError </code>, содержащий информацию об ошибке. В этом случае вы напечатали саму ошибку.</p><p> Как выглядит ошибка? Вам нужно создать <code> XMLParser </code> экземпляр, чтобы взять этот делегированный класс:</p><pre> пусть парсер7 = парсер7()
пусть xmlParser7 = XMLParser (данные: xmlData_corrupted)
xmlParser7.delegate = парсер7
xmlParser7.parse()
 </pre><p> Если вы скомпилировали и запустили программу, вы должны увидеть ошибку:</p><pre> Error Domain=NSXMLParserErrorDomain Code=76 "(null)" UserInfo={NSXMLParserErrorColumn=15, NSXMLParserErrorLineNumber=8, NSXMLParserErrorMessage=Открывающий и закрывающий теги не совпадают: строка заголовка 7 и статья
}
 </pre><p> Вы получили номер строки и номер столбца, где произошла ошибка.<img class="lazy lazy-hidden" loading='lazy' src="//ylianova.ru/wp-content/plugins/a3-lazy-load/assets/images/lazy_placeholder.gif" data-lazy-type="image" data-src='/800/600/https/image2.slideserve.com/4219131/xml-parser-api-feature-summary-l.jpg' /><noscript><img loading='lazy' src='/800/600/https/image2.slideserve.com/4219131/xml-parser-api-feature-summary-l.jpg' /></noscript> Вы также получили сообщение об ошибке, в котором говорилось, что открывающий и закрывающий теги не совпадают.</p><h3><span class="ez-toc-section" id="i-7"> Заключение </span></h3><p> В этой статье вы узнали, как анализировать XML-данные. Вы начали с создания экземпляра <code> XMLParser </code>. Затем вы создали делегированный класс <code> XMLParserDelegate </code> для обработки логики процесса синтаксического анализа. Оттуда вы обрабатывали элементы, атрибуты и текстовое содержимое. Вы также устранили ошибку в процессе синтаксического анализа и настроили синтаксический анализатор для обработки пространства имен.</p><hr/><h4><span class="ez-toc-section" id="_LogRocket"> Другие замечательные статьи от LogRocket: </span></h4><ul><li> Не упустите момент с The Replay, кураторским информационным бюллетенем от LogRocket</li><li> Узнайте, как Galileo компании LogRocket преодолевает шум, чтобы заблаговременно решать проблемы в вашем приложении</li><li> Используйте useEffect React для оптимизации производительности вашего приложения</li><li> Переключение между несколькими версиями узла</li><li> Узнайте, как анимировать приложение React с помощью AnimXYZ</li><li> Изучите Tauri, новую платформу для создания двоичных файлов</li><li> Консультативные советы предназначены не только для руководителей.<img class="lazy lazy-hidden" loading='lazy' src="//ylianova.ru/wp-content/plugins/a3-lazy-load/assets/images/lazy_placeholder.gif" data-lazy-type="image" data-src='/800/600/https/image1.slideserve.com/2049694/slide5-l.jpg' /><noscript><img loading='lazy' src='/800/600/https/image1.slideserve.com/2049694/slide5-l.jpg' /></noscript><div class='yarpp-related yarpp-related-none'><p>No related posts.</p></div></div></div><div class="post-sharrre group"><div id="twitter" data-url="https://ylianova.ru/raznoe-2/parsing-xml-xml-parser-i-obekt-xmlhttprequest.html" data-text="Парсинг xml: XML парсер и объект XMLHttpRequest" data-title="Tweet"></div><div id="facebook" data-url="https://ylianova.ru/raznoe-2/parsing-xml-xml-parser-i-obekt-xmlhttprequest.html" data-text="Парсинг xml: XML парсер и объект XMLHttpRequest" data-title="Like"></div><div id="googleplus" data-url="https://ylianova.ru/raznoe-2/parsing-xml-xml-parser-i-obekt-xmlhttprequest.html" data-text="Парсинг xml: XML парсер и объект XMLHttpRequest" data-title="+1"></div><div id="pinterest" data-url="https://ylianova.ru/raznoe-2/parsing-xml-xml-parser-i-obekt-xmlhttprequest.html" data-text="Парсинг xml: XML парсер и объект XMLHttpRequest" data-title="Pin It"></div></div></div></article><ul class="post-nav group"><li class="next"><a href="https://ylianova.ru/raznoe-2/bekap-bd-mysql-sozdanie-rezervnoj-kopii-bazy-dannyh-mysql.html" rel="next"><i class="fa fa-chevron-right"></i><strong>Вперед</strong> <span>Бэкап бд mysql: Создание резервной копии базы данных MySQL</span></a></li><li class="previous"><a href="https://ylianova.ru/http/https-ww-federalnaya-nalogovaya-sluzhba.html" rel="prev"><i class="fa fa-chevron-left"></i><strong>Назад</strong> <span>Https ww: Федеральная налоговая служба</span></a></li></ul><section id="comments" class="themeform"><div id="respond" class="comment-respond"><h3 id="reply-title" class="comment-reply-title">Добавить комментарий <small><a rel="nofollow" id="cancel-comment-reply-link" href="/raznoe-2/parsing-xml-xml-parser-i-obekt-xmlhttprequest.html#respond" style="display:none;">Отменить ответ</a></small></h3><form action="https://ylianova.ru/wp-comments-post.php" method="post" id="commentform" class="comment-form"><p class="comment-notes"><span id="email-notes">Ваш адрес email не будет опубликован.</span> <span class="required-field-message">Обязательные поля помечены <span class="required">*</span></span></p><p class="comment-form-comment"><label for="comment">Комментарий <span class="required">*</span></label><textarea id="comment" name="comment" cols="45" rows="8" maxlength="65525" required="required"></textarea></p><p class="comment-form-author"><label for="author">Имя <span class="required">*</span></label> <input id="author" name="author" type="text" value="" size="30" maxlength="245" autocomplete="name" required="required" /></p><p class="comment-form-email"><label for="email">Email <span class="required">*</span></label> <input id="email" name="email" type="text" value="" size="30" maxlength="100" aria-describedby="email-notes" autocomplete="email" required="required" /></p><p class="comment-form-url"><label for="url">Сайт</label> <input id="url" name="url" type="text" value="" size="30" maxlength="200" autocomplete="url" /></p><p class="form-submit"><input name="submit" type="submit" id="submit" class="submit" value="Отправить комментарий" /> <input type='hidden' name='comment_post_ID' value='42484' id='comment_post_ID' /> <input type='hidden' name='comment_parent' id='comment_parent' value='0' /></p></form></div></section></div></section><div class="sidebar s1"> <a class="sidebar-toggle" title="Развернуть боковую панель"><i class="fa icon-sidebar-toggle"></i></a><div class="sidebar-content"><div id="search-2" class="widget widget_search"><form method="get" class="searchform themeform" action="https://ylianova.ru/"><div> <input type="text" class="search" name="s" onblur="if(this.value=='')this.value='Введите поисковую фразу';" onfocus="if(this.value=='Введите поисковую фразу')this.value='';" value="Введите поисковую фразу" /></div></form></div><div id="nav_menu-2" class="widget widget_nav_menu"><h3>Рубрики</h3><div class="menu-2-container"><ul id="menu-2" class="menu"><li id="menu-item-5370" class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-5370"><a href="https://ylianova.ru/category/css">Css</a></li><li id="menu-item-5371" class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-5371"><a href="https://ylianova.ru/category/html">Html</a></li><li id="menu-item-5372" class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-5372"><a href="https://ylianova.ru/category/http">Http</a></li><li id="menu-item-5373" class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-5373"><a href="https://ylianova.ru/category/javascript">Javascript</a></li><li id="menu-item-5374" class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-5374"><a href="https://ylianova.ru/category/photoshop">Photoshop</a></li><li id="menu-item-5375" class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-5375"><a href="https://ylianova.ru/category/verstka">Верстка</a></li><li id="menu-item-5376" class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-5376"><a href="https://ylianova.ru/category/raznoe">Вопросы и ответы</a></li><li id="menu-item-5377" class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-5377"><a href="https://ylianova.ru/category/maket">Макет</a></li><li id="menu-item-5378" class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-5378"><a href="https://ylianova.ru/category/sajt">Развитие сайтов</a></li><li id="menu-item-5380" class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-5380"><a href="https://ylianova.ru/category/sajt-2">Сайт</a></li><li id="menu-item-5381" class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-5381"><a href="https://ylianova.ru/category/shablon-2">Шаблон</a></li><li id="menu-item-5382" class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-5382"><a href="https://ylianova.ru/category/shrift-2">Шрифт</a></li><li id="menu-item-5379" class="menu-item menu-item-type-taxonomy menu-item-object-category current-post-ancestor current-menu-parent current-post-parent menu-item-5379"><a href="https://ylianova.ru/category/raznoe-2">Разное</a></li></ul></div></div><div id="categories-3" class="widget widget_categories"><h3>Рубрики</h3><ul><li class="cat-item cat-item-5"><a href="https://ylianova.ru/category/css">Css</a></li><li class="cat-item cat-item-4"><a href="https://ylianova.ru/category/html">Html</a></li><li class="cat-item cat-item-9"><a href="https://ylianova.ru/category/http">Http</a></li><li class="cat-item cat-item-10"><a href="https://ylianova.ru/category/javascript">Javascript</a></li><li class="cat-item cat-item-20"><a href="https://ylianova.ru/category/linux">Linux</a></li><li class="cat-item cat-item-11"><a href="https://ylianova.ru/category/photoshop">Photoshop</a></li><li class="cat-item cat-item-19"><a href="https://ylianova.ru/category/adaptiv">Адаптив</a></li><li class="cat-item cat-item-17"><a href="https://ylianova.ru/category/verstka">Верстка</a></li><li class="cat-item cat-item-3"><a href="https://ylianova.ru/category/raznoe">Вопросы и ответы</a></li><li class="cat-item cat-item-16"><a href="https://ylianova.ru/category/maket">Макет</a></li><li class="cat-item cat-item-6"><a href="https://ylianova.ru/category/sajt">Развитие сайтов</a></li><li class="cat-item cat-item-13"><a href="https://ylianova.ru/category/raznoe-2">Разное</a></li><li class="cat-item cat-item-12"><a href="https://ylianova.ru/category/sajt-2">Сайт</a></li><li class="cat-item cat-item-1"><a href="https://ylianova.ru/category/sovety">Советы</a></li><li class="cat-item cat-item-15"><a href="https://ylianova.ru/category/shablon-2">Шаблон</a></li><li class="cat-item cat-item-7"><a href="https://ylianova.ru/category/shablon">Шаблоны</a></li><li class="cat-item cat-item-14"><a href="https://ylianova.ru/category/shrift-2">Шрифт</a></li><li class="cat-item cat-item-8"><a href="https://ylianova.ru/category/shrift">Шрифты</a></li></ul></div></div></div></div></div><footer id="footer"><section id="footer-bottom"><div class="container"> <a id="back-to-top" href="#"><i class="fa fa-angle-up"></i></a><div class="pad group"><div class="grid one-half"><div id="copyright"><p>Блог сумасшедшего сисадмина © 2024. Все права защищены.</p></div><div id="credit"><p><a href="/sitemap.xml" class="c_sitemap">Карта сайта</a></p></div></div><div class="grid one-half last"></div></div></div></section></footer></div> <noscript><style>.lazyload{display:none}</style></noscript><script data-noptimize="1">window.lazySizesConfig=window.lazySizesConfig||{};window.lazySizesConfig.loadMode=1;</script><script async data-noptimize="1" src='https://ylianova.ru/wp-content/plugins/autoptimize/classes/external/js/lazysizes.min.js'></script> <!--[if lt IE 9]> <script src="https://ylianova.ru/wp-content/themes/anew/js/ie/respond.js"></script> <![endif]--> <!-- noptimize -->
<style>iframe,object{width:100%;height:480px}img{max-width:100%}</style><script>new Image().src="//counter.yadro.ru/hit?r"+escape(document.referrer)+((typeof(screen)=="undefined")?"":";s"+screen.width+"*"+screen.height+"*"+(screen.colorDepth?screen.colorDepth:screen.pixelDepth))+";u"+escape(document.URL)+";h"+escape(document.title.substring(0,150))+";"+Math.random();</script>
<!-- /noptimize --> <script defer src="https://ylianova.ru/wp-content/cache/autoptimize/js/autoptimize_a56d25bd4d7e94175194a7052d7ab478.js"></script></body></html><script src="/cdn-cgi/scripts/7d0fa10a/cloudflare-static/rocket-loader.min.js" data-cf-settings="cfe55ea734e459d463745b37-|49" defer></script>