Skip to content

Instantly share code, notes, and snippets.

@leoniv
Last active July 2, 2018 15:06
Show Gist options
  • Save leoniv/b07873b4bbf4cc07573c8cdbccd65b65 to your computer and use it in GitHub Desktop.
Save leoniv/b07873b4bbf4cc07573c8cdbccd65b65 to your computer and use it in GitHub Desktop.
Примитивный xml парсер 1C
//[+> Тест
Procedure PressExecuteButton(Button)
Данные1 = РазобратьXml(XMLReader(XML_V1()));
XDTO1 = ФабрикаXDTO.ПрочитатьXML(XMLReader(XML_V1()));
Данные2 = РазобратьXml(XMLReader(XML_V2()));
XDTO2 = ФабрикаXDTO.ПрочитатьXML(XMLReader(XML_V2()));
XMLReader = XMLReader(XML_V1());
XMLReader.Read();
Данные3 = РазобратьXml(XMLReader);
XMLReader = XMLReader(XML_V1());
XMLReader.Read();
XDTO3 = ФабрикаXDTO.ПрочитатьXML(XMLReader);
ДолжноБытьИсключение = РазобратьXml(XMLReader(INVALID_XML()));
EndProcedure
Function XMLReader(xml)
res = New XMLReader;
res.SetString(xml);
return res;
EndFunction
Function XML_V1()
return "<?xml version=""1.0""?>
|<root>
| <a/>
| <a>texta</a>
| <a/>
| <a>
| <b><c>textc1</c></b>
| </a>
| <a>
| <b><c>textc3</c></b>
| </a>
| <a></a>
| <d><e><![CDATA[<xml></xml>]]></e></d>
| <f/>
| <a>
| <b><c>textc2</c></b>
| </a>
| <f/>
| <f/>
| <f/>
|</root>
|";
EndFunction
Function XML_V2()
return "<?xml version=""1.0""?>
|<root>
|</root>
|";
EndFunction
Function INVALID_XML()
return "<?xml version=""1.0""?>
|<root>
| <a/>
| <a>texta<b>textb</b></a>
| <a/>
|</root>
|";
EndFunction
//[<+ Тест
//[+> Парсер
// Примитывный парсер xml. Разбирает xml в структуру используя <ЧтениеXML>.
// Последовательности разбираются в массив структур.
// <ЧтениеXML> должен указывать на начало xml!
// Не читает атрибуты!
// Не работает когда узел содержит и текст и другие узлы!
// Параметры
// - ЧтениеXML - ЧтениеXML - инициализированный объект чтение XML
// Возвращает Структура
// - Данные - Стрктура - результат разбора
// - Тип - Строка - имя корневого элемента
// Исключение
// - "Ожидался конец элемента..." - когда узел содержит и текст и другие узлы!
Функция РазобратьXml(ЧтениеXML) Экспорт
Результат = ПрочитатьУзел(ЧтениеXML, Новый Структура);
Если ЗначениеЗаполнено(Результат) И Результат.Количество() = 1 Тогда
Для Каждого КЗ из Результат Цикл
Возврат Новый Структура("Данные, Тип", КЗ.Значение, КЗ.Ключ);
КонецЦикла;
КонецЕсли;
Возврат Новый Структура("Данные, Тип", Результат, Неопределено);
КонецФункции
Функция ПрочитатьУзел(ЧтениеXML, Результат)
Пока ЧтениеXML.Прочитать() Цикл
Если ЧтениеXML.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда
ИмяУзла = ЧтениеXML.ЛокальноеИмя;
Значение = ПрочитатьУзел(ЧтениеXML, Новый Структура);
ПрочитатьУзелДобавитьЗначение(Результат, Значение, ИмяУзла);
ИначеЕсли ЧтениеXML.ТипУзла = ТипУзлаXML.Текст Тогда
Возврат ПрочитатьУзелТерминальноеЗначение(ЧтениеXML);
ИначеЕсли ЧтениеXML.ТипУзла = ТипУзлаXML.КонецЭлемента Тогда
Возврат ?(Результат.Количество() = 0, Неопределено, Результат);
КонецЕсли;
КонецЦикла;
Возврат Результат;
КонецФункции
Функция ПрочитатьУзелДобавитьЗначение(Результат, Значение, ИмяУзла)
Если Результат.Свойство(ИмяУзла) Тогда
Если ТипЗнч(Результат[ИмяУзла]) <> Тип("Массив") Тогда
_Значение = Результат[ИмяУзла];
Результат[ИмяУзла] = Новый Массив;
Результат[ИмяУзла].Добавить(_Значение);
КонецЕсли;
Результат[ИмяУзла].Добавить(Значение);
Иначе
Результат.Вставить(ИмяУзла, Значение);
КонецЕсли;
Возврат Результат;
КонецФункции
Функция ПрочитатьУзелТерминальноеЗначение(ЧтениеXML)
Результат = ЧтениеXML.Значение;
ЧтениеXML.Прочитать();
Если ЧтениеXML.ТипУзла <> ТипУзлаXML.КонецЭлемента Тогда
ВызватьИсключение "Ожидался конец элемента. Формат xml вида <c>text<b/><c> не поддерживается.";
КонецЕсли;
Возврат Результат;
КонецФункции
//[<+ Парсер
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment