Информационные технологииStfw.Ru 🔍

Perl & XML. Библиотека программиста

MySQL - это реляционная база данных. MySQL основана на технологии client/server. Все примеры команд MySQL в этой статье могут быть введены прямо в командную строку MySQL. MySQL поддерживает многострочные команды и использует точку с запятой
🕛 25.10.2006, 12:50
Perl и XML


Язык программирования Perl появился достаточно давно и изначально был ориентирован на обработку текста. В отличие от Perl, за «плечами» XML - всего лишь считанные годы, но за это время он успел зарекомендовать себя с самой лучшей стороны. Этот язык широко применяется для обработки web-содержимого, выполнения различных операций с документами, проектирования web-служб, а также в любой другой ситуации, в которой требуется структурирование изменчивой информации. Несмотря на столь различную природу, эти языки прекрасно уживаются вместе. И именно описанию истории их порой сложного, но удачного союза посвящена эта книга.


В чем причина тесного союза между Perl и XML?


В первую очередь следует отметить, что Perl идеально подходит для обработки текста. Он поддерживает дескрипторы файлов, объекты документов, выполняет обработку строк, а также предлагает возможности по созданию регулярных выражений. Любой, кому приходилось изначально разрабатывать программы на низкоуровневом языке, таком как C, а потом - на Perl, понимает, что Perl гораздо лучше приспособлен для обработки текста. А XML, по существу, - это обычный текст, поэтому Perl и XML прекрасно дополняют друг друга.


Более того, начиная с версии 5.6, Perl допускает работу с символьными кодировками, основанными на Unicode (например, UTF-8), и именно этот факт чрезвычайно важен при обработке XML-документов. Дополнительные сведения о символьных кодировках можно найти в главе 3.


Во-вторых, следует так же учитывать наличие всеобъемлющей архивной сети Perl (CPAN), включающей множество Perl-модулей, доступных всем желающим. Благодаря этому задачи программиста значительно упрощаются; каждый, начинающий программировать на языке Perl, может просто воспользоваться готовыми модулями. Благодаря этому достигается значительная экономия времени и средств. Например, зачем создавать собственный анализатор кода (parser), если в сети CPAN содержится множество готовых анализаторов, доступных для свободной загрузки? Причем, как правило, все модули заранее протестированы и могут подстраиваться под конкретные нужды. Сеть CPAN не относится к числу жестко заданных структур: в ее развитие вносит вклад множество людей, а всякие проявления контроля имеют ограниченный характер. Как только возникает новая технология, в сети CPAN появляется поддерживающий ее модуль. Благодаря этому свойству прекрасно дополняются возможности XML, в результате чего могут изменяться старые и добавляться новые вспомогательные технологии.


Изначально XML-модули росли и множились «как грибы после дождя». Каждый модуль был снабжен уникальным интерфейсом и имел присущий ему оригинальный стиль в традициях Perl. В последнее время начала проявляться тенденция к созданию универсального интерфейса, позволяющего реализовать взаимозаменяемость модулей. Если вас в силу каких-либо причин не устраивает синтаксический анализатор SAX, вы можете легко воспользоваться каким-либо другим анализатором, не прилагая для этого дополнительных усилий.


В-третьих, гибкие возможности Perl, обеспечивающие объектно-ориентированное программирование, являются весьма полезными при работе с XML. Данные в XML-документе имеют иерархическую структуру, образованную с помощью базовых единиц. Эти единицы называются XML-элементами и могут содержать вложенные элементы. В результате элементы, образующие документ, могут быть представлены с помощью одного класса объектов, включающего простые идентичные интерфейсы. Более того, язык разметки XML инкапсулирует содержимое этих объектов , которые, в свою очередь, инкапсулируют код и данные. В результате они прекрасно дополняют друг друга. Нетрудно заметить, что подобные объекты весьма полезны при организации модульной структуры XML-процессоров. Они включают анализаторы, фабрики анализаторов, вспомогательные объекты, а также анализаторы, возвращающие объекты. Все это обеспечивает создание «прозрачного» кода, который может выполняться практически на всех платформах.


В-четвертых, большое значение имеет связь между Perl и Web. Конечно, Java и JavaScript обладают поистине неисчерпаемыми возможностями в этой области, но любой, кто немного разбирается в web-программировании, скажет вам, что Perl применяется при организации серверной части большинства web-серверов. Многие web-библиотеки, написанные на языке Perl, могут легко адаптироваться с учетом их применения в XML. Опытные программисты, которые годами разрабатывали web-узлы на языке Perl, могут свободно стать поддаными «королевства» XML.


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



XML проще, чем вы думаете


Многие люди склонны рассматривать XML как результат вмешательства некоего «злого гения», который, как минимум, собирается уничтожить все человечество. Внедренный язык разметки, с его угловыми скобками и слэшами, на первый взгляд кажется довольно сложным. К тому же, если учитывать наличие вложенных элементов, типов узлов и объявлений DTD, ситуация значительно осложняется.


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


Для иллюстрации справедливости этого утверждения рассмотрим простой базовый модуль, именуемый XML::Simple, созданный Грантом Мак Клином (Grant McLean). При минимальных трудозатратах со стороны пользователя обеспечивается доступ к солидному набору полезных свойств, обеспечивающих обработку XML-кода.


Как известно, типичная программа считывает XML-документ, выполняет некоторые изменения, записывая их при этом в файле. Назначение модуля XML::Simple заключается во всемерной автоматизации этого процесса. В результате вызова подпрограммы происходит считывание XML-документа и сохранение его в памяти. Для представления элементов и данных применяются встроенные хэш-символы. После завершения всех необходимых изменений вызывается другая подпрограмма, выполняющая запись информации в файл.


А теперь перейдем к непосредственным практическим испытаниям. Как и в случае с любым другим модулем, директива use применяется для объявления XML::Simple в программе:


use XML::Simple;

После выполнения этой инструкции XML::Simple в пространство имен экспортирует две подпрограммы:


XMLin() - эта подпрограмма считывает XML-документ из файла или строки и создает структуру, включающую данные и элементы. В ходе осуществления этого процесса возвращается ссылка на хэш, содержащий структуру.

XMLout() - эта подпрограмма, располагая ссылкой на хэш с закодированным документом, генерирует XML-разметку и возвращает ее в виде строки текста.

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


Предположим, что ваш босс собирается отослать сообщения группе пользователей приложения WarbleSoft SpamChucker, управляющего списками рассылки. Одним из свойств этого приложения является возможность импорта/экспорта XML-файлов, представляющих списки рассылки. Единственная проблема в этом случае заключается в том, что боссу затруднительно читать на экране имена пользователей в их исходном виде и он предпочитает, чтобы они отображались с применением заглавных букв. В силу этого требуется написать программу, редактирующую XML-файлы данных и выполняющую требуемые преобразования.


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


Листинг 1.1. Файл данных SpamChucker


<?xml version="1.0"?>
<spam-document version="3.5" timestamp="2002-05-13 15:33:45">

<!- Автоматически генерируется WarbleSoft Spam, версия 3.5 ->

<customer>

<first-name>Joe</first-name>

<surname>Wrigley</surname>

<address>

<street>17 Beable Ave.</street>

<sity>Meatball</city>

<state>MI</state>

<zip>82649</zip>

</address>

<email>joewrigley@jmac.org</email>

<age>42</age>

</customer>

<customer>

<first-name>Henrietta</first-name>

<surname>Pussycat</surname>

<address>

<street>R.F.D. 2</street>

<city>Flangerville</city>

<state>NY</state>

<zip>83642</zip>

</address>

<email>meow@263A.org</email>

<age>37</age>

</customer>

</spam-document> 

Ознакомившись со страницей perldoc, описывающей модуль XML::Simple, вы сможете чувствовать себя достаточно уверенно и написать небольшой сценарий, показанный в листинге 1.2.


Листинг 1.2. Сценарий, выполняющий замену строчных на прописные буквы в именах заказчиков


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

# сформированному приложением WarbleSoft SpamChucker..

# Включение ограничений и предупреждений, в этом случае

# вы знаете что делать.

use strict;

use warnings;

# Импорт модуля XML::Simple.

use XML::Simple;

# Включение файла в хэш-ссылку с помощью процедуры

# "XMLin" из модуля

XML::Simple.

# Также включается опция 'forcearray', поэтому

# все элементы

# содержат ссылки на массив.

my $cust_xml = XMLin('./customers.xml', forcearray=<l);

# Выполнение цикла по каждому субхэшу customer,

# причем все объекты хранятся в виде анонимного

# списка под ключом 'customer'.

for my $customer (@{$cust_xml-<{customer}}) {

# Замена строчных на прописные буквы в элементах

#'first-name' и 'surname' путем выполнения встроенной

# функции Perl, uc().

foreach (qw(first-name surname)) {

$customer-<{$_}-<[0] = uc($customer-<{$_}-<[0]);

}

}

# Повторный вывод на печать хэша в виде XML-документа,

# включающего завершающий символ новой строки

# (для улучшения восприятия кода).

print XMLout($cust_xml);

print "n"; 

В результате выполнения программы (возможно, связанного с некоторыми проблемами, с тех пор как всеми данными распоряжается ваш босс), получаем следующий результат:


<opt version="3.5" timestamp="2002-05-13 15:33:45">
<customer>

<address>

<state>MI</state>

<zip>82649</zip>

<city>Meatball</city>

<street>17 Beable Ave.</street>

</address>

<first-name>JOE</first-name>

<email>i-like-cheese@jfflac.org</email>

<surname>WRIGLEY</surname>

<age>42</age>

</customer>

<customer>

<address>

<state>NY</state>

<zip>83642</zip>

<city>Flangerville</city>

<street>R.F.O. 2</street>

</address>

<first-name>HENRIETTA</first-name>

<email>ineowmeow@augh.org</email>

<surname>PUSSYCAT</surname>

<age>37</age>

</customer>

</opt> 

Примите наши поздравления! Вы написали программу, выполняющую обработку XML-кода, которая, к тому же, хорошо работает. Достигнут почти превосходный результат. Применяемое здесь слово «почти» свидетельствует о том, что поведение программы немного отличается от ожидаемого. Поскольку хэш-символы не сохраняют порядок следования содержащихся в них элементов, он будет изменен. Также могут отсутствовать пробелы между элементами. Может ли это представлять проблему?


В рассматриваемом сценарии подчеркивается важная мысль: необходимость компромисса между простотой и сложностью. Как разработчику вам потребуется принять решение относительно того, что составляет важную часть кода, написанного на языке разметки, а что - нет. Иногда имеет значение порядок следования элементов. В этом случае использование модулей, подобных XML::Simple, не допускается. Либо программисту требуется получить доступ к обрабатываемым инструкциям, а также сохранять их в файле. И снова модули, подобные XML::Simple, не обладают подобными возможностями. Поэтому прежде, чем принять решение относительно использования конкретного модуля, требуется оценить его возможности. В данном случае все значительно проще, поскольку вы проконсультировались со своим боссом и проверили программу SpamChucker, воспользовавшись набором измененных данных. В результате были удовлетворены все заинтересованные лица. Полученный и исходный документы похожи, благодаря чему можно прийти к выводу о соответствии требованиям, выдвигаемым к приложению1 . Поэтому считайте, что вы прошли «боевое крещение» и приступили к обработке XML-документа с помощью Perl!


Имейте в виду, что мы находимся только в начале пути. Большая часть книги оформлена в виде курса опережающего обучения и содержит множество советов и методик, предназначенных для выполнения обработки любых XML-документов. Не каждая проблема, имеющая отношение к этому процессу, является столь же простой, как указывалось выше. В любом случае авторы книги надеются, что читатели достаточно подготовлены и не испытывают непреодолимых сложностей, связанных с обработкой XML-документов средствами Perl.
ХМL-процессоры


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


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


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


В мире Perl подобное поведение определяется с помощью Perl-модулей: как правило, в случае, когда требуется обработка XML-кода, осуществляемая с помощью инструкции use. При этом используется существующий пакет, обеспечивающий доступ программиста к объектно-ориентированному интерфейсу. Начало обработки XML-кода во многих программах на языке Perl, располагающих соответствующими возможностями, определяется с помощью анализатора XML::Parser (либо другой подобной программы). По прошествии небольшого периода времени вся «черновая работа» по разбору XML-кода поручается другим, ранее написанным модулям. Код, составленный программистами, определяет порядок предварительной и завершающей обработки.



Пользуйтесь готовыми модулями


К одной из сильных сторон Perl можно отнести то, что этот язык поддерживается сообществом его сторонников во всем мире. Как только программисты на языке Perl идентифицируют проблему и создают соответствующий модуль, нацеленный на ее решение, результат их деятельности становится достоянием мировой общественности. Для этой цели предназначается сеть CPAN. Основное преимущество в данном случае заключается в том, что если вы хотите создать какой-либо фрагмент кода на языке Perl, существует вероятность, что кто-либо создал его ранее, и в сети CPAN можно найти соответствующий Perl-модуль.


Однако метод «коллективного творчества», примененный по отношению к столь «юной», популярной и нетрадиционной технологии, каковой является XML, имеет свои недостатки. К моменту первого «выхода на сцену» XML в сети CPAN существовали различные Perl-модули, написанные различными программистами. По причине полной анархии все они образуют «нестройный хор», в число участников которого входят различные структуры и интерфейсы, ориентированные на достижение различных целей.


Однако не падайте духом. Времена «анархии и беспорядка», относящиеся к 1998 году, остались в прошлом. В настоящие время наблюдается некое подобие организации и стандартов. Причем инициатива исходит от сообщества Perl/XML (о чем изначально было заявлено в списке рассылки perl-xml, поддерживаемом ActiveState). Члены сообщества разрабатывали первые модули с целью создания требуемых инструментов. При этом они следовали правилам, установленным другими игроками в мире XML. К числу этих «игроков» можно отнести стандарты синтаксического анализа, SAX и DOM, а также внедренные XML-технологии, такие как XPath. Позднее появились базовые анализаторы низкого уровня. Совсем недавно возникли интересные системы (такие как XML::SAX), которые реализуют модель DWIM на уровне Perl, отображенную в разрабатываемых стандартах1.


Конечно, если вы желаете воспользоваться «бестолковыми» инструментами, пригодными лишь для выполнения черновой и быстрой работы, то всегда сможете это сделать. К числу таких инструментов можно отнести модуль XML::Simple. Авторы книги приложат максимум стараний для того, чтобы помочь вам воспользоваться стандартизованными инструментами. После этого вам останется лишь запустить процесс обработки XML-кода и не вмешиваться в происходящий процесс.



Программисту на заметку


Как правило, XML-модули, находящиеся в сети CPAN, удовлетворяют потребности программистов на 90%. Конечно, оставшиеся 10% можно рассматривать как соотношение между ведущими специалистами вашей компании и «кандидатами на увольнение». Авторы книги намереваются оправдать те затраты, которые вы понесли в результате приобретения книги, путем демонстрации некоторых «ужасных» деталей, объясняющих порядок обработки в Perl XML-документов на самых низких уровнях (по сравнению с любым видом специализированной обработки текста, осуществляемой в Perl). Для начала обратимся к некоторым «азбучным истинам», которые следует учитывать в дальнейшем.


Происхождение программы не имеет значения


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


Имейте в виду, что программа требует внимания к себе в целом. Например, если была написана программа, реализующая механизм XML-RPC, лучше знать порядок использования протокола TCP, который определяет выборку и отсылку через Интернет всех XML-данных! Мы можем использовать эту программу для выполнения операций выборки и отсылки данных, однако до тех пор, пока конечный программный продукт является неизменным, так как пользователь будет испытывать потребность в чистом XML-документе, который может обрабатываться XML-процессором, лежащим в ядре программы.


Все XML-документы подобны с точки зрения структуры


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


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


XML-приложения различаются своим назначением


Любые XML-приложения определяют смысл существования произвольного XML-документа. Причем набор правил высшего уровня, которым следует произвольный XML-документ, способствует достижению некоторых полезных целей. Эти правила могут определять: заполнение файла конфигурации, подготовку передачи данных в сети иливыполнение некоторых других действий. Смысл существования XML-приложений заключается не только в том, чтобы наполнять скромные документы «высшим смыслом их предназначения». Они также требуются для определения структуры создаваемых документов в соответствии с определенной спецификацией приложений. С помощью объявления DTD облегчается достижение совместимости описанной выше структуры. Однако следует учитывать тот факт, что в распоряжении разработчика может не оказаться схемы формального подтверждения, используемой при разработке приложений. Может возникнуть потребность в создании некоторых правил проверки. Эти правила окажутся весьма полезными, например, в случае, когда требуется, чтобы ваши последователи (включая и вас самих две недели спустя) не «путались в дебрях» разработанной ранее программы. Потребуется также создать схему проверки, если необходимо будет позволить другим программистам создавать программы, обеспечивающие использование преимуществ языка XML.


Как правило, при реализации на практике большинства приемов составления XML-кода, во главу угла ставится упомянутый выше дуализм «документ/приложение». В большинстве случаев разрабатываемое программное обеспечение будет включать разделы, учитывающие три перечисленных ниже факта:


ввод данных осуществляется с применением подходящего метода. В частности может осуществляться «прослушивание» сетевого сокета либо считывание файла с диска. Подобное поведение является весьма типичным и характерным для Perl: делайте все необходимое для получения данных;
перехваченные входные данные будут передаваться некоему типу XML-процессора. Как правило, лучше всего воспользоваться одним из анализаторов, созданным и поддерживаемым сообществом разработчиков на Perl. В качестве этих модулей может использоваться модуль XML::Simple либо более сложные модули, которые будут рассмотрены ниже;
и наконец, обратите внимание на результат обработки процессором XML-кода. Возможно, он будет продуцировать XML-код (либо HTML-код), обновлять базу данных либо отсылать электронное сообщение вашей матери. Этот пункт является определяющим при выполнении XML-приложения: просто берется код XML и выполняется некая его обработка. В книге не будут обсуждаться поистине безграничные возможности, открывающиеся в этом случае. Предмет рассмотрения составят тесные связи между XML-процессором и остальными частями вашей программы.


Особенности XML


В этом разделе затрагиваются вопросы, составляющие предмет всей книги. Именно с ними связаны проблемы, возникающие при обработке XML-документов.


Формальная корректность


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


Кодировки символов



Жизнь в XXI веке требует уделять внимание таким вопросам, как применяемые кодировки символов. Безвозвратно ушли те дни, когда содержимое web-узловв Интернете кодировалось с применением набора символов ASCII. «Героем наших дней» стал Unicode, на базе которого формируются все основные наборы символов, применяемые в Сети. В XML предполагается работа с символами Unicode, хотя существует множество способов для представления этой кодировки, включая наиболее часто используемую в Perl кодировку Unicode, UTF-8. Как правило, достаточно редко приходится задумываться о вопросах подобного рода, но нужно быть осведомленным относительно имеющихся возможностей.


Пространства имен


Не каждый может похвалиться тем, что работал с пространствами имен. Пространства имен производят разбиение кода на отдельные области, разделяя теги, разметки и объявления. В результате появляется возможность смешивать и сопоставлять различные типы документов. Идет ли речь об уравнениях в HTML-коде, либо о разметке в виде данных в XSLT-коде, использование пространств имен является оправданным. Имейте в виду, что поддержка пространств имен реализована в недавно разработанных модулях.


Объявления


По существу, объявления не входят в состав документа, а просто описывают его. Это следует принимать как данность и не стоит уделять этому вопросу повышенное внимание. Помните лишь о том, что в документах часто применяются объявления DTD, а также включаются объявления таких объектов, как сущности и атрибуты. Следует учитывать это, с тем чтобы не «наломать дров» в дальнейшем.


Сущности


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


Служебные символы


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


Заканчивая обзор языков Perl и XML, можно сделать вывод, что они превосходно дополняют друг друга. И хотя в процессе работы могут появляться так называемые «ловушки», но благодаря наличию различных модулей, разработанных программистами, изучение возможностей Perl/XML будет легким и приятным.

Perl   Теги: Perl, Xml

Читать IT-новости в Telegram

Читайте также:

Perl

E-Mail на Perl

Perl - введение

Информационные технологии
Мы в соцсетях ✉